Domain repetition artifact

category: general [glöplog]
Hi guys!! I'm trying to use domain repetition with instanceID technique as explained by Cupe in
NVScene 2015 Session: How to Create Content with Signed Distance Functions (Johann Korndorfer)
but getting a lot of artifact (seems to be related to the mod function). Someone know how i could fix it?
Here is my example in Shadertoy:
Shadertoy Example
Its unavoidable to introduce discontinuities using the "instanceID technique", only when the difference in calculated distance between the cells is small you won't experience any artifacts, the easiest approach to remedy them is a matter of careful tweaking in combination with husbanding your marching steps(right now you're overstepping), a better but in some cases cost prohibitive remedy is to take the surrounding cells into consideration, note that even then you're not necessarily returning the correct distance, ideally you'd write a custom distance estimation function using your knowledge of the domain your variance is happening in.

Let me describe what happens in your code(for the sake of simplicity assuming all spheres have a radius of 1) in the worst case scenario:

you're at [0,0,0] your sphere is at [0,13,0](or rather you offset space by -13 on y), your map function is returning 12, you step 12 units in ray direction [0,0,1], you just crossed two cells without even considering them since your cells are only 5 units on x,z ...
added on the 2018-04-19 18:43:14 by LJ LJ
you can consider adjacent cells but that makes the distance funcion evaluate 27 objects instead of 1 ... e.g. a 3D voronoi would give random 3D spheres without glitches, but is super expensive
This is something three years ago almost immediately ran into as well when initially trying to learn distance fields. The problem is as LJ describes: within a cell, you're only evaluating based on the size of the current cell. This is fine of course, but the problem arises when the ray crosses the cell boundaries, in which case the distance gradient will be wrong. This is still fine if the evaluated one is smaller than the actual one, but otherwise you overestimate and step into or over your geometry.

Solutions include the ones LJ and TropicalTrevor. The brute force solution is to skip the modulus entirely end evaluate each object separately. This is slow and you definitely don't want this. A faster and a robust solution is to evaluate the neighboring cells as well (might need to evaluate neighbors' neighbors as well if you're taking really long steps but up to you based on visual artifacts). This is the correct way that retains the accurate distances. See an example of that here: https://www.shadertoy.com/view/ltSGRG.
added on the 2018-04-19 20:05:34 by noby noby
Another way is to use uniform grid raytracing (as if you are raytracing a Minecraft level) and raymarch within the exact bounds of each cell.
added on the 2018-04-19 20:11:54 by fizzer fizzer
One other thing you can do is, in your distance field, add "walls" around each sell (as literal cubes or infinite 2D boxes you march to), if those walls are larger than the cell they are not visible but they avoid overstepping boundaries too far, meaning if your objects retain a certain distance from the cell border you don't have to evaluate other cells

I made a shadertoy with more comments:

yep, the others have summed it up pretty well. When debugging those discontinuities I find it extremely helpful to visualize the distance on a plane (similar to the the plane in the shadertoy that noby posted and also in the talk). My scale-invariant distance meter from the talk is here: https://www.shadertoy.com/view/ldK3zD (no matter the size of your object, it paints isolines at powers of ten. so you can zoom in and out all the way and really get what's going on. having that thing and sweeping it over the scene was an intant level-up experience.)

Mostly I use what I call "guard objects" in my head (trevor's shadertoy uses inside-out boxes as guard objects). One problem with those is that they effectively limit your maximum step size and you will get horrible artifacts when looking into the distance because your ray will hit the step limit quite early in space... Most of the time you can use your knowledge of the scene to improve this, but it is always different: There is no single solution that works for all scenes, you have to think and play with it every time.
And for completely arbitrary placement of objects in space like those spheres... errr... that mostly doesn't work too well to be honest :)

For on we used a mixture of things: we evaluated exactly two cells, so we could get away with much more relaxed guard objects. But then again, I can't even remember what exactly were the "cells" in this mindfuck SDF.

Also, in case you haven't seen, code from that talk (and more) was cleaned up and released as a library for signed distance functions: http://mercury.sexy/hg_sdf/
added on the 2018-04-19 23:38:10 by cupe cupe
WOWWWWW THANKS A LOT TO ALL!!!! I'll study all the solution that you've posted!!! Thanks thanks thanks!! I'll keep you updated :)