learn GLSL from zero
ToolsCreate with shadersShader MakerFree online shader builderToolkitShader works ready for your siteSketcher LabPaint your landing’s hero with shaders3D StudioThe Three.js editor in your browser
GamesPlay with shadersOnomatoShaderType a word, blow it upThe WatcherAn eye that follows youAetherLiquid glass with an eye insideBloomcoreA word grows a garden of lightPyrokineThrow fire at the wallVoltaicThe pyramid throws lightningSurfSurf a shader ocean

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.
PruebaRaise 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);
}
close