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