5 comments

[ 3.0 ms ] story [ 23.6 ms ] thread
Tl;dr: SDFs are really slow but cool because they can compactly define complex stuff; demoscene uses it. Sort of the functional programming to trad renderings OOP. Would be cool if it was faster. Optimizing an algorithm for CPU rendering using recursive divide and conquer, 1 core with one object gets 50 fps. 100 fps if you lerp a 10x10 pixel patch instead of doing 1 pixel. Algorithm isn’t optimized, fully. Also, turns out the author’s idea is previously known but somewhat obscure, it is referred to as “cone marching”
Holy crap! The demo is hitting 30 FPS from certain angles, on my decade-old CPU
Played around with the code to implement a little bit of SIMD. Was able to squeeze out a decent improvement, ~250 fps avg, ~140 low, ~333 high (on an m4). Looks pretty straightforward to do threading with as well. Cool stuff! Could work to bring more gpu stuff back down to the cpu.
Unsurprisingly, it turns out that other people had already thought of applying the multi-pass technique on GPU, but the idea is not very widely known.

The demoscene is particularly insular, but even within the field of computing in general it seems that there is not a lot of knowledge diffusion between all the different areas, leading to some reinventions (often with distinct terminology.)

I do this in a more crude fashion (like the article mentions) on the GPU in an old personal project.

I just run a low-res (256x256) pre-pass and store the distances to a floating point texture. I then use that pre-pass texture as the starting point (minus some delta) when drawing full-screen. This makes it really nice and performant, even for complex SDF shapes.

I think a common misconception in GPU programming is that branching is slow. It is only really slow when neighboring fragments diverges on those logic branches.

The quick pre-pass step gets close enough to the SDF surface that more fragments are in lockstep with each other and terminates at the same time, eliminating the expensive re-runs the GPU driver has to do. More experimentation is needed on my end. I do this in the browser with WebGL so accurate profiling is sometimes difficult.

I experimented with different resolutions and number of pre-pass steps but found it was sufficient on most GPU's with a single prepass run (subject to change the more I test).