Bones of Civilisation 1K shader code

This is the exhaustively documented shader code of the Bones Of Civilisation 1 kilobyte intro. Remember, don’t try this at work!

//
// Bones of Civilisation / Fulcrum
//
// This is the shader part of our 1K intro that won 1st place at the
// Assembly Summer 2025 1K intro competition. To understand this code,
// you'll need basic GLSL shader knowledge, and how ray-marching
// SDFs (signed distance fields) works. A good starting point is
// Rendering worlds with 2 triangles:
// https://iquilezles.org/articles/nvscene2008/rwwtt.pdf
//
// Apart from whitespace, this is the original code in the intro, including
// all minifications and variable renaming. There are nuances that get lost
// in un-minified code. The code only runs on Nvidia, since AMDs new shader 
// compiler is very pedantic and considers a lot of things errors that used
// to be warnings...

// We pass the time (more specifically, the current frame number) in gl_Color.x,
// and rely on truncation to skip the .x . 
// The different scenes start on c = 0, 0.5, 1, 2, 3 and 4
float c=60*gl_Color;

// Rotate a 2D vector some angle c in radians
void n(inout vec2 y,float c)
{
  y=vec2(y.y,-y.x)*sin(c)+y*cos(c);
}

// This is a Signed Distance Field for a variant of the city 
// fractal, as shown on ShaderToy by
// Xor https://www.shadertoy.com/view/cdG3Wd and 
// Leon https://www.shadertoy.com/view/ftG3D1 
// 
// How this fractal works:
// - you start with a completely filled world
// - you cut out a box, repeating along all axis. So this gives you
//   a kind of infinite skyscraper of empty rooms without any doors or
//   windows connecting them.
// - you rotate the space along the up-axis, then cut out another
//   infinite grid of smaller boxes. This will cause holes to start to
//   appear in the walls, and possibly floors of the skyscraper rooms.
// - repeat the rotation and cutting with smaller and smaller boxes,
//   and you have the city fractal.
// 
// Here I'm using independent scaling parameters in each dimension,
// for more variation. The parameters are:
// y = 3D point to evaluate the distance for.
// c = angle to rotate between each layer.
// b, d, e = box scaling parameters along the x, y, z axis.
//    These determine the thickness of the walls and the floors.
//    Typically between .7 and 1.
// l = 3D space scaling factor between each layer. Typically around .5
// t = height of a horizontal cutof plane, to prevent the fractal from
//  being infinitely high

float n(vec3 y,float c,float b,float d,float e,float l,float t)
{
  float m=-y.y-t, // Distance to fractal. Start from a filled world,
                  // with a cutoff at some height
      x=32; // Initial world scaling factor

  for(;x>.01;) //Keep cutting out layers until we've reached a very detailed level.

    // max operation on Signed Distance Fields intersects 2 fields
    m=max( 
        min(y.z, // Min operation on SDFs combines fields. The 2 mins on .x,.y and .z creates walls and floors. 
            min(
                // The mod() creates an infinite grid, abs() mirrors it in even/odd cells for continuity
                // Scale along current world scale and per-axis scale.
                y=x*vec3(b,d,e)-abs(mod(y,x+x)-x), 
                y.y)
            .x),
        m // The distance to the previous layer 
    ),n(y.xz,c),x*=l; // rotate the 3D space along the y axis, and shrink the world scale for the next iteration

  return m; // return the distance
}

void main()
{
  float l=0, // l is the brightness of the pixel this shader is running for.
        x=0, // x is the amount of raymarching steps taken so far,
        e=0, // e is the total distance walked along the ray.
        d; //  d is the current distance to the fractal

  // Define the camera start point, depending on the time c. I just noticed
  // I forgot to move the shared c multiplication in the Z-component to the front...
  // Guess I'll keep it for historical accuracy.
  vec3 y=-.5-vec3(c<1?34:c<2?24:c<3?15:c<4?-30.5:-4.46,
                  c<.5?15:c<1?35:c<2?6:c<3?6.8:c<4?4.9:9.1,
                  c<.5?0:c<1?370*c:c<2?2.9*c:c<3?40*c:c<4?90*c:c*21.4) 

    // This is the direction the camera looks at for this pixel. Constants based on 720p resolution
  ,m=vec3(.0015*gl_FragCoord.xy-vec2(1,.55),.5);

  // rotate the camera down, depending on which scene we're in
  n(m.yz,c<1?1.5:c<2?-.3:c<3?0:c<4?-.2:2.5);

  // Same for left/right
  n(m.xz,.6*fract(c)+(c<1?0:c<2?-.3:c<3?-.7:c<4?.5:-2.5));

  // March 200 steps, half of these will be for the distance, half for the volumetric lighting.
  for(;x++<200;)
    // Find the distance to the fractal for the current scene, and update the total distance walked
    e+=d=c<1?n(y,1.34,.59,.75,c<.5?-c*3:.63,.6,55.):
         c<2?n(y,3.6,.82,.73,.95,.5,16.):
         c<3?n(y,1.53,.89,.73,.95,.45,50.):
         c<4?n(y,-.22,.74,.76,.92,.57,53.):
             n(y,.5,.99,.57,.95,.47,50.),
      
      // After 100 steps, we stop marching, and we switch to a stochastic volumetric
      // lighting walk. For this, we pick a random point on the current ray, then walk
      // towards the light direction. This gives you a noisy volumetric effect.
      //
      // I made a couple of modifications:
      // - instead of using a random() function, I use the city fractal itself. Besides being
      //   smaller, this can also cause a fixed noise pattern on continuous flat surfaces,
      //   bringing out more details from the fractal than using a real noise function.
      // - Instead of only using the intensity of the 2nd ray, I leak in a bit of light based
      //   on the length of the first ray and the last checked distance which shows some details in the shadows

      x==100 ? // switching to volumetric shadow?
          (
              // scale the current position enormously (so that, with the repeating nature of 
              // the city fractal, it becomes nearly random), get the distance, and scale that
              // into the [0-1] interval. Constants found using try & error.
              // For the 1st scene, locally clipping into the geometry gave some black surfaces
              // I wanted to keep, hence the -.1 offset.
              y+=m*e*(.04*n(y*-9e5,1.,.82,.73,.95,.5,50.)+(c<2?-.1:0)),

              // March to the light. Each scene has its own light direction.
              m=vec3(1,c<1?1.4:c<2?.1:c<3?.7:1,1),
              // rotate the light direction over time. Reset for each new scene
              n(m.xy,-mod(c*.5,.5)),
              // Instead of resetting the intensity to 0, show more details based on the length 
              // of the ray and the last distance.
              l=l/e-d*33)
          : // normal ray stepping:
              l+=d*(c<.5?.5:.01), // add more brightness if we're far from the fractal
              m/=length(m), // normalize the direction
              y-=m*d; // adjust the current position on the ray.

  // Render the pixel, and fade out at the end.
  gl_FragColor=min(l,1)*min(1,24.6-c*5);
}