Lesson 5 of 10 · Ray marching in GLSL
Light
Diffuse: the face looking at the light lights up.
You already have the normal. Diffuse light is one multiplication: dot(n, lightDir). The dot product between the normal and the light direction is 1 when the surface faces the light head-on, 0 when edge-on, and we clamp it at 0 so it never goes negative.
That is all that separates a flat silhouette from a sphere with volume: the lit side glows, the far side dims. We add a little amb (ambient light) so the shadow is not pitch black.
dot(n, lightDir)The dot product measures how much two directions agree. Normal against light = how head-on it catches the light.
max(...,0.0) drops whatever faces away. That curve from bright to dark is what your eye reads as form.Raise
amb=0.12 to 0.4 and the shadow lifts. The first slider boosts diffuse strength (diff*0.9).The code
precision highp float;
float map(vec3 p){
return length(p)-1.0;
}
vec3 nrm(vec3 p){
vec2 e=vec2(0.001,0.0);
return normalize(vec3(
map(p+e.xyy)-map(p-e.xyy),
map(p+e.yxy)-map(p-e.yxy),
map(p+e.yyx)-map(p-e.yyx)));
}
void main(){
vec2 uv=(gl_FragCoord.xy*2.0-R)/R.y;
vec3 ro=vec3(0.0,0.0,3.0);
vec3 rd=normalize(vec3(uv,-1.5));
float t=0.0;
float hit=0.0;
for(int i=0;i<64;i++){
vec3 pos=ro+rd*t;
float d=map(pos);
if(d<0.001){ hit=1.0; break; }
t+=d;
if(t>12.0) break;
}
vec3 pos=ro+rd*t;
vec3 n=nrm(pos);
vec3 lightDir=normalize(vec3(0.8,0.7,0.6));
float diff=max(dot(n,lightDir),0.0);
float amb=0.12;
vec3 base=vec3(0.95,0.45,0.22);
vec3 lit=base*(diff*0.9+amb);
vec3 col=mix(vec3(0.04,0.05,0.09), lit, hit);
gl_FragColor=vec4(col,1.0);
}