Hi @supervga , yes! I refer to those, I actually learnt it from iquilez hahaha
Everything in the screenshots, except the sky, is modeled with distance fields, it's 100% code. Rendering is done by ray-marching, but it uses techniques a little bit more advanced than usual to optimize rendering time. For example, rendering is performed in multiple steps with different compute shaders in pipeline reading and writing to memory:
- “Direct 16X”. Compute the “safe distance” of the underlying 4x4 grid of pixels. The “safe distance” is the distance that all underlying pixels can advance they ray origins in their respective ray directions without hitting anything. If you normally march in a line, this marches in a cone.
- “Direct 1X”. This is the traditional ray-march, but it uses the output from the “Direct 16X” phase, to advance the initial position of the ray origin.
- “Shadows 16X”. Analog to Direct 16X, but for shadow rays
- “Shadows 1X”.
- “Final”. AO and lighting.
Thanks @joej !
For the tracks, there is a combination of techniques. At the highest level, they are placed in a hexagonal tile. There is a small integer 2D texture in which each pixel encodes how each tile must be: orientation and type. This texture needs to be filled in a smart way (or manually), to ensure continuity of the pattern. In my game's case, I used the Wave Function Collapse to fill the texture at initialization time (on the CPU). You can read about it here: https://github.com/mxgmn/WaveFunctionCollapse
At the low level, the track is another distance field, based on a box and 4 cylinders. But they are modified to give a smooth figure. It's no longer a pure distance field, but it's good enough. The curve used (viewing it from top), it's a simple circular arc of 60 degrees (to match the hexagonal tiling: 360/6=60).
Could there be glossy reflections as well?
I guess there is some way, but I haven't think much about it (nor it is implemented).
What acceleration structure do you use?
There is no automatic acc structure. In practique, most models have some kind of AABB approximation DF before computing the complex DF: if the result of the AABB DF is high, it uses that, if it's low, it computes the real distance.
How's support for physics? People say SDF is fast for collision detection, but i think finding closest points on two convex objects still requires some iterative search?
Unit's physics are approximated with a sphere. The DF is used to compute the distance of the world to the center of those spheres. For the game case, this was good enough. It's really fast, the DF is evaluated on the GPU, all units in a single Compute Dispatch. The rest of the logic is done on the CPU.
How do you create the scenes? Editor or using external tool like Blender?
Pure code. However, the engine it's designed to allow fast iterations. Apart from hot-reloading on file changes, the distribution of the shader code into multiple smaller shaders, makes shader compilation faster.