learn GLSL from zero
ToolsCrea con shadersShader MakerCrea shaders gratis en líneaToolkitObras de shaders listas para tu webSketcher LabPinta el hero de tu landing con shaders3D StudioEl editor Three.js en tu navegador
GamesJuega con shadersOnomatoShaderEscribe una palabra y explótalaThe WatcherUn ojo que te sigueAetherVidrio líquido con un ojo adentroBloomcoreUna palabra hace crecer un jardín de luzPyrokineAvienta fuego a la paredVoltaicLa pirámide lanza rayosSurfSurfea un océano de shader

Lección 5 de 10 · Ray marching en GLSL

Luz

Difusa: la cara que mira a la luz se prende.

Ya tienes la normal. La luz difusa es una multiplicación: dot(n, lightDir). El producto punto entre la normal y la dirección de la luz vale 1 cuando la superficie mira de frente a la luz, 0 cuando la mira de canto, y lo cortamos en 0 para que no se vuelva negativo.

Eso es todo lo que separa una silueta plana de una esfera con volumen: el lado iluminado brilla, el lado opuesto se apaga. Le sumamos un poco de amb (luz ambiente) para que la sombra no quede negra total.

dot(n, lightDir)El producto punto mide cuánto coinciden dos direcciones. Normal contra luz = qué tan de frente recibe el rayo de luz. max(...,0.0) tira lo que da la espalda. Esa curva del claro al oscuro es lo que tu ojo lee como forma.
PruebaSube amb=0.12 a 0.4 y la sombra se aclara. El primer slider sube la fuerza difusa (diff*0.9).

El código

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