https://www.shadertoy.com/view/ldS3DW
球体注释版
float sphere(vec3 ray, vec3 dir, vec3 center, float radius)
{
vec3 rc = ray-center;
float c = dot(rc, rc) - (radius*radius);
float b = dot(dir, rc);
float d = b*b - c;
float t = -b - sqrt(abs(d));
float st = step(0.0, min(t,d));
return mix(-1.0, t, st);
//mix(x,y,a) a控制混合结果 return x(1-a) +y*a 返回 线性混合的值
//clamp(x,minval,maxval),return min(max(x,minval),maxval);
//step(edge x) if x >= edge return 1 else return 0
//smoothstep(edge0 edge1 x)
//如果x <= edge0 return 0;
//如果x >= edge1 return 1;
//如果egde0 <= x <= edge1,返回Hermite线性插值
//t = clamp((x-edge0)/(edge1 - edge0),0,1);
//return t*t*(3 - 2*t);
//relect(I,N)
//前者是发光向量,后者是平面法向量,返回反射向量,即I-2.0*dot(N,I)*N
//GLSL内建函数https://blog.csdn.net/hgl868/article/details/7876257
}
vec3 background(float t, vec3 rd)
{
vec3 light = normalize(vec3(sin(t), 0.6, cos(t)));
float sun = max(0.0, dot(rd, light));
float sky = max(0.0, dot(rd, vec3(0.0, 1.0, 0.0)));
float ground = max(0.0, -dot(rd, vec3(0.0, 1.0, 0.0)));
return
(pow(sun, 256.0)+0.2*pow(sun, 2.0))*vec3(2.0, 1.6, 1.0) +
pow(ground, 0.5)*vec3(0.4, 0.3, 0.2) +
pow(sky, 1.0)*vec3(0.5, 0.6, 0.7);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (-1.0 + 2.0*fragCoord.xy / iResolution.xy) *
vec2(iResolution.x/iResolution.y, 1.0);
//第二行的作用是把y方向当成-1到1,x方向按照显示器比例缩放
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
vec3 p = vec3(0.0, 0.0, 0.0);
float t = sphere(ro, rd, p, 1.0);
vec3 nml = normalize(p - (ro+rd*t));
vec3 bgCol = background(iTime, rd);
rd = reflect(rd, nml);
vec3 col = background(iTime, rd) * vec3(0.9, 0.8, 1.0);
fragColor = vec4( mix(bgCol, col, step(0.0, t)), 1.0 );
}
打算改成椭球的,但不知为什么调参调不好
float sphere(vec3 ray, vec3 dir, vec3 center,vec3 r)
{
ray -= center;
float ab = r.x*r.x*r.y*r.y;
float ac = r.x*r.x*r.z*r.z;
float bc = r.y*r.y*r.z*r.z;
float c = ray.x*ray.x*bc + ray.y*ray.y*ac + ray.z*ray.z*ab - r.x*r.x*r.y*r.y*r.z*r.z;
float b = ray.x*dir.x*bc + ray.y*dir.y*ac + ray.z*dir.z*ab;
float a = dir.x*dir.x*bc + dir.y*dir.y*ac + dir.z*dir.z*ab;
float d = b*b - c;
float t = (-b - sqrt(abs(d)))/a;
float st = step(0.0, min(t,d));
return mix(-1.0, t, st);
}
vec3 background(float t, vec3 rd)
{
vec3 light = normalize(vec3(sin(t), 0.6, cos(t)));
float sun = max(0.0, dot(rd, light));
float sky = max(0.0, dot(rd, vec3(0.0, 1.0, 0.0)));
float ground = max(0.0, -dot(rd, vec3(0.0, 1.0, 0.0)));
return
(pow(sun, 256.0)+0.2*pow(sun, 2.0))*vec3(2.0, 1.6, 1.0) +
pow(ground, 0.5)*vec3(0.4, 0.3, 0.2) +
pow(sky, 1.)*vec3(0.5, 0.6, 0.7);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (-1.0 + 2.0*fragCoord.xy / iResolution.xy) *
vec2(iResolution.x/iResolution.y, 1.0);
vec3 ro = vec3(0.0, 0.0, -4.0);
vec3 rd = normalize(vec3(uv, 1.0));
vec3 p = vec3(0.0, 0.0, 1.0);
float t = sphere(ro, rd, p, vec3(1.1,1.,1.));
vec3 nml = normalize(p - (ro+rd*t));
vec3 bgCol = background(iTime, rd);
rd = reflect(rd, nml);
vec3 col = background(iTime, rd) * vec3(0.9, 0.8, 1.0);
fragColor = vec4( mix(bgCol, col, step(0.0, t)), 1.0 );
}
椭球和球对比
float eliIntersect( in vec3 ro, in vec3 rd, in Ellipsoid sph )
{
vec3 oc = ro - sph.cen;
vec3 ocn = oc / sph.rad;
vec3 rdn = rd / sph.rad;
float a = dot( rdn, rdn );
float b = dot( ocn, rdn );
float c = dot( ocn, ocn );
float h = b*b - a*(c-1.0);
if( h<0.0 ) return -1.0;
return (-b - sqrt( h ))/a;
}
float sphIntersect( in vec3 ro, in vec3 rd, in vec4 sph )
{
vec3 oc = ro - sph.xyz;
float b = dot( oc, rd );
float c = dot( oc, oc ) - sph.w*sph.w;
float h = b*b - c;
if( h<0.0 ) return -1.0;
return -b - sqrt( h );
}
// Compute fake soft shadows for sphere objects. You can see this in action here:
//
// https://www.shadertoy.com/view/lsSSWV
//
// and
//
// https://www.shadertoy.com/view/XdjXWK
//
//
// Related info: http://iquilezles.org/www/articles/spherefunctions/spherefunctions.htm
//
// Other Soft Shadow functions:
//
// Sphere: https://www.shadertoy.com/view/4d2XWV
// Ellipsoid: https://www.shadertoy.com/view/llsSzn
// Box: https://www.shadertoy.com/view/WslGz4
// Capsule: https://www.shadertoy.com/view/MlGczG