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 4 de 10 · Ray marching en GLSL

Normales

Hacia dónde apunta la superficie. El mapa de orientación.

Para iluminar algo primero hay que saber hacia dónde mira cada punto de su superficie. Eso es la normal: una flecha perpendicular a la cáscara.

No la tenemos guardada, pero la SDF nos la regala: mides la distancia en seis puntitos alrededor del hit (un poco a la izquierda, a la derecha, arriba, abajo, adelante, atrás) y la diferencia te apunta hacia afuera. Eso es el gradiente. Pintamos n*0.5+0.5 para verlo: cada eje un color.

El gradienteLa normal es la dirección en la que la SDF crece más rápido. Restar map(p+e)-map(p-e) en cada eje mide esa pendiente. normalize la deja de largo 1. Una esfera muestra todo el arcoíris RGB porque mira en todas direcciones.
PruebaMueve el 0.0 de hueShift(col, 0.0) y giras toda la paleta de la normal. Cambia el radio 1.0 también.

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 col=mix(vec3(0.04,0.05,0.09), n*0.5+0.5, hit);
  col=hueShift(col, 0.0);
  gl_FragColor=vec4(col,1.0);
}
close