Raymarching Beginners' Thread

category: code [glöplog]
... and assuming you can generate an image like you posted above, the remaining thing to do is to perform a distance transform (educate me beautiful), and voilà heightmap.
added on the 2012-06-18 22:21:43 by xTr1m xTr1m
I agree with IQ, first person to do erosion realtime wins ALL the siggraphs.
added on the 2012-06-19 07:03:15 by Mewler Mewler
It seems like you all lost.
Oh, and a WebGL demo is here.
added on the 2012-06-19 12:11:11 by raer raer
Cool! I did something a bit like that a while back (using a height map, then using a separate texture to add water with a shader moving the water downhill to form rivers + lakes... not nearly so successfully as that demo though).

I think the idea was to do erosion in a single step though, rather than iteratively. It's not hard to do it iteratively :)
added on the 2012-06-19 12:22:53 by psonice psonice
Hum, in looked those papers quickly... They explicitly simulate an erosion process. One can have a fast enough simulation for real-time, one can throw enough computing power at it, I do not contradict this.

However, I'm looking for an other kind of princess. It would be a 2d => 1d function which when added to a height-map, erode it. That function would not explicitly simulate an erosion process. If one use distance transform, as explained by xTr1m, the problem is reduced to have a function able to represent some diffusion-aggregation pattern, *without* simulating diffusion-aggregation. (disclaimer : it's for the sport, I don't claim it would be useful)
btw. I'm tinkering with raymarching again and ran into a problem using the blend() operator (colors == normals). This is the blend between a cube and a sphere:
BB Image
this is the same thing with min()
BB Image
Code: float sdSphere(vec3 p, float s) { return length(p) - s; } float sdBox(vec3 p, vec3 s) { vec3 di = abs(p) - s; float mc = maxcomp(di); return mc<0.0 ? mc : length(max(di,0.0)); } vec3 grad(vec3 p, float eps) { vec2 e = vec2(eps, 0.0); return vec3(field(p+e.xyy), field(p+e.yxy), field(p+e.yyx)) / e.x; } vec4 rm(vec3 p, vec3 d, float maxSteps, float maxDist) { vec3 startPos = p; float i=0.; float l=1.; float dist = 1.; float steps = 0.; float epsilon = .0001; for(; i<1. && l>epsilon && dist < maxDist; i+=1.0/maxSteps) { l = blend(sdSphere(p + somemovementshit), sdBox(p + somemovementshit)); p += (l * d * .5); dist = length(startPos - p); steps += 1.; } //calculate normalized z if (l < epsilon) { vec3 n = grad(p, dist * .01); return vec4(abs(n), i); } else { return vec4(0, 0, 0, i); } } void main() { vec4 r = rm(eye, dir, 256, 10.); }

What I'd expect to get is a sphere and a cube and when they are in a certain distance the "merge", but the sphere also disappears sometimes...

Another problem is that the raymarching function needs like 128-256 steps to NOT leave empty parts in the objects (read: return vec4(0, 0, 0, i)) and I'm not sure why.
added on the 2012-06-19 12:40:16 by raer raer
raer: tried a bigger epsilon value? If you need a large value to avoid holes, it implies that the ray is taking too many steps to reach the surface.. which implies that you need to increase the epsilon or the march step.

Not sure on the blend part, it's not something I've gotten as far as using, but how does it work out if you replace it with a straight min()?
added on the 2012-06-19 14:15:19 by psonice psonice
The normal colors does not seem to make sense about what direction that they represent when you compare the two images (for example, the blue on the sphere - is it Z or Y?)
I changed my raymarching loop to
Code: vec4 rm(vec3 origin, vec3 dir, float maxSteps, float maxDist) { float l=1.; float dist = 0.1; float steps = 0; float epsilon = .0001; vec3 p; for(;steps < maxSteps; steps++) { p = origin + dir * dist; l = field(p); if ((abs(l) < epsilon) || dist > maxDist) { break; } dist += l * 0.75; } //calculate normalized z float i = steps / maxSteps; if (abs(l) < epsilon) { vec3 n = grad(p, maxDist * l); return vec4(n, i); } else { return vec4(0, 0, 0, i); } }

And the holes are mostly gone. The blend operator is still an issue...
added on the 2012-06-19 15:42:54 by raer raer
ignore the normal colors.
added on the 2012-06-19 15:43:30 by raer raer
Some images again:
BB Image
BB Image
added on the 2012-06-19 15:50:18 by raer raer
same size/camera/settings, just the operator changed...
added on the 2012-06-19 15:51:05 by raer raer
What do you use as blend operator?
Finding a proper blend operator is not as trivial as one might think.
If somebody has a properly working one - tell us - I tried several formulas from several papers - they all sucked.
added on the 2012-06-19 17:14:37 by las las
I just realised, I have all images on pouet blocked for safety (at work). I might have missed something :)
added on the 2012-06-19 17:16:25 by psonice psonice
DOH. Sorry. I forgot the blend operator while copy-pasting...

Code: float opBlend(float d1, float d2) { float dd = cos((d1 - d2) * PI); return mix(d1, d2, dd); }
added on the 2012-06-19 17:27:38 by raer raer
Lol. I was thinking there was some glsl blend() function I'd forgotten about :D
added on the 2012-06-19 17:44:05 by psonice psonice
ok... opBlend only seems to work when the objects are pretty close to each other. I tried "a13X_B"s metaball-formula from the toolbox thread and it works pretty well.
added on the 2012-06-20 17:43:35 by raer raer
If you're interested in figuring out why that blend op didn't work, i see a pretty big flaw in it: the blending needs to depend on the distance between the two objects, but it doesn't have that info. You're just telling it how far away they are from the current position. They could be the same distance from the point but in opposite directions, so actually far apart.
added on the 2012-06-20 18:07:41 by psonice psonice


I agree with IQ, first person to do erosion realtime wins ALL the siggraphs.

It seems like you all lost.
Oh, and a WebGL demo is here.

i never said anything about realtime. what i sad is that still today nobody has been able to do procedural erosion. procedual as in perlin noise. all solutions are based on simulation, and therefore need a grid (bitmap).

the problem of procedural erosion is actually deeper. erosion is a global process (soil moves from one part to another, etc) yet procedural functions only have (in principle) local knowledge, as they are a function of the point under consideration, f(x,y,z). of course, f could of course cast rays or run some global process internally, but then we are again probably on the domain of simulation, not proceduralism.

there is only one person so far that once claimed to have solved the problem of procedural erosion, but never gave actual code or paper or demo, so the problem pretty much stays unsolved. whoever solves it, wins siggraph :D
added on the 2012-06-21 18:26:49 by iq iq
you mean that "erosion fractal" - thing?
added on the 2012-06-21 19:26:54 by las las
iq - I just wanted to give some pointers on how to implement such a thing...
Yet I don't see how a simulated/iterative process can be easily implemented as a procedural function.
added on the 2012-06-21 21:53:27 by raer raer
what about a combination of: turtle graphics, but instead of drawing lines, draw a FBM deformed line, in terms of: push, rotate x deg left, draw fbm forward, pop, rotate x deg right, draw fbm forward, pop... and/or make a tree of FBM lines using a grammar with L-systems... That should generate a picture similar to what las posted:
BB Image
Finally perform a distance transform. I'd like to see the result of this proposal, anyone got some spare time to test this? :)
added on the 2012-06-21 22:09:11 by xTr1m xTr1m
Using fBm and twisting it a lot => I tinkered a bit in that direction, but so far failed. The problem is that fBm makes planar-graph-like structure, not tree-like structures.

L-Systems => *yes*. They can be evaluated in a procedural fashion. Procedural distance transform on such a beast, still no can do for me...
BB Image

Looks like IQ is up to something! https://twitter.com/iquilezles/status/247802128951832577/photo/1
added on the 2012-09-18 06:44:07 by Mewler Mewler