The Mine
This is a brief summary of the modeling process behind The Mine at Shadertoy.
The first objects that I added into the scene were the two rails. They are a pair of boxes that extend to infinity along the forward axis. I computed the distance to only the box on the right, and then I mirrored the space so as to achieve symmetry. I also carved an infinite cylinder with a very small radius at the inner part of the rails to add some detail.

The code of the distance function to the rails is straightforward:
// distance from p to box with width b.x, height b.y, and border radius r.
float box(vec2 p, vec2 b, float r) {
return length(max(abs(p)-b, 0.0)) - r;
}
float rails(vec3 p) {
// mirrors the x axis and translates.
vec2 q = vec2(abs(p.x)-1.0, p.y + 1.7);
float d = box(q, vec2(0.1), 0.01); q.x += 0.2;
// carves the cylinder.
return max(d, 0.11 - length(q));
}
Below the rails I included some planks. They are rectangular prisms that repeat along the forward axis. Repetition can be achieved by applying modular arithmetic on the distance function of a box.
float box(vec3 p, vec3 b, float r) {
return length(max(abs(p)-b, 0.0)) - r;
}
float plank(vec3 p) {
vec3 q = vec3(p.x, p.y + 1.9, mod(p.z, 2.0) - 1.0);
return box(q, vec3(1.5, 0.05, 0.2), 0.01);
}


The supports of the mineshaft are boxes that span to infinity on the appropriate axis. I used a shear mapping place them along a diagonal direction. Repetition is achieved by the use of mirroring and modular arithmetic.
float support(vec3 p) {
// translation, mirroring, and modulo.
const vec4 c = vec4(0.15, 0.2, 2.0, 1.2);
vec3 q = vec3(abs(p.x) - c.z, p.y - c.z, mod(p.z, 6.0) - 3.0);
float d = box(q.xz, c.xx, 0.05); // vertical support.
d = min(d, box(q.yz, c.yx, 0.05)); // horizontal support.
q.x += q.y + c.w; // shear mapping
return min(d, box(q.xz, c.xx, 0.05)); // diagonal support.
}





The last part was modelling the cave itself. I placed an infinite cylinder around the track as such that it cuts through the supports to hide their prolongations. I used a superquadric to have control over the roundness of the cave, and fractional brownian motion noise was used to add details to the walls.
float cave(vec3 p) {
// superquadric
const float k = 4.0;
return 1.6-pow(pow(abs(p.x), k) + pow(abs(p.y), k), 1.0/k);
}
vec2 dist_field(vec3 p) {
// warps the XY plane as a function of Z.
p.xy += track(p.z);
// displacement mapping based on fractal brownian motion.
float dist = cave(p) + fbm(p);
dist = min(dist, support(p));
dist = min(dist, plank(p));
dist = min(dist, rails(p));
return dist;
}


The track
function in the above code distorts the space as a function of depth to create a sense of an uneven path. I used a simple sum of sines and cosines to achieve the distortion.
vec2 track(float z) {
float x = cos(0.2*z);
float y = -cos(0.2*z) - 0.1*sin(0.8*z - 2.0);
return vec2(x, y);
}

And that’s all of the modeling! As you can see, I’ve used only simple shapes together with Constructive Solid Geometry techniques to build the whole scene. I think it is really interesting how just a few lines of codes can add a lot to the output image. The shading of these models is based on a simple Lambertian and Phong model, and I used cube mapping to apply textures onto them. There’s nothing fancy, so I think most people can have a look at the code.