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 6 of 10 · Ray marching in GLSL

The floor

A plane + min(). Two shapes share one scene.

A scene with one object is a lonely planet. To add more, you union SDFs with min(): the distance to the nearest thing is the smaller of the two. Sphere or floor, whichever is closer to the ray wins.

The floor is the cheapest SDF on Earth: p.y+1.0 is the vertical distance to a horizontal plane. Union it with the sphere and suddenly there is ground to stand on.

min(a, b) = unionmin of two distances returns the nearest object. It is the union operator: it joins shapes into one scene. Later you will meet max for cuts and smin for soft blends.
PruebaChange p.y+1.0 to p.y+0.6 and the floor rises, the sphere seems to float. The first slider changes the radius (sph=length(p)-1.0).

The code

precision highp float;
float map(vec3 p){
  float sph=length(p)-1.0;
  float flo=p.y+1.0;
  return min(sph, flo);
}
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>20.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);
  vec3 lit=vec3(0.85,0.55,0.35)*(diff*0.9+0.12);
  vec3 sky=mix(vec3(0.05,0.06,0.12), vec3(0.16,0.22,0.42), uv.y*0.5+0.5);
  float fog=1.0-exp(-t*0.08);
  vec3 col=mix(lit, sky, fog);
  col=mix(sky, col, hit);
  gl_FragColor=vec4(col,1.0);
}
close