pouët.net

Raymarching Beginners' Thread

category: code [glöplog]
Tip: Helps to initialize l before... :/
added on the 2011-02-25 20:13:24 by raer raer
Shouldn't l be dynamic? Something to do with the distance? A closer object needs a smaller l than an object a few km away.
added on the 2011-02-25 20:19:55 by xernobyl xernobyl
l is dynamic, it's the distance from the nearest surface. The point is to stop the loop when the distance gets so close you don't care about more accuracy, so it's faster.

Btw, any benefit to having the l conditional in the for(..) statement rather than having "if(l<0.0001) break;" inside the loop?
added on the 2011-02-25 21:03:28 by psonice psonice
Sorry. I meant that 0.0001, epsilon.
added on the 2011-02-25 22:13:15 by xernobyl xernobyl
the epsilon is just 'how close to the object is close enough?'. It has to be MUCH smaller than the size of the objects of course.. for me the objects are generally ~0.1 units or bigger in size, the epsilon is 0.0001 or less. Put it another way, 0.0001 is 0.5 pixels away from the object, which is close enough :)
added on the 2011-02-25 22:32:19 by psonice psonice
That explains why when you set it higher you get (visible) banding.
added on the 2011-02-26 01:44:55 by raer raer
psonice: so you can get a function that gives you the size of a pixel at distance D. that can be your error margin.
added on the 2011-02-26 01:50:13 by xernobyl xernobyl
Fond out how mod() works...
BB Image
added on the 2011-02-26 02:13:44 by raer raer
Rare:
The basic rm loop in the toolbox thread does more or less exactly that (I use a crunched version of that)
added on the 2011-02-26 09:58:43 by las las
Does what?
added on the 2011-02-26 19:20:23 by raer raer
xernobyl: the only benefit would be a possible earlier bailout. But you'd have more complexity in the loop to change the epsilon, so I doubt you would gain anything at all.
added on the 2011-02-26 19:37:18 by psonice psonice
What is really beneficial is to have it all branch-free...
added on the 2011-02-26 19:53:14 by raer raer
Uhmm that's wrong I guess.
Code:i<1. && l>.00001;
is also branching - so it's completly up to the GLSL compiler.
Quote:

Does what?

Taking the distance into account for the threshold at least the last version I posted (The one with unc's iteration glow idea)
added on the 2011-02-26 19:59:46 by las las
I know it's branching. I'm just saying in it would be benificial...
Quite different to programming on a CPU.
added on the 2011-02-26 20:20:33 by raer raer
It is possible to get anti-aliasing by jittering the march direction:
Code: vec3 up = normalize(cross(d, vec3(1,0,0))); vec3 right = normalize(cross(d, up)); up = cross(d, right); vec4 r = rm(p, d, 100); vec4 r2 = rm(p, d + 0.002 * up, 100); vec4 r3 = rm(p, d - 0.002 * up, 100); vec4 r4 = rm(p, d + 0.002 * right, 100); vec4 r5 = rm(p, d - 0.002 * right, 100); gl_FragColor = vec4(0.2 * (r + r2 + r3 + r4 + r5).xyz, 1);

How would I do DOF? Move ray start position accordingly?
added on the 2011-02-28 12:58:34 by raer raer
Yeah, same technique, but you move the position 'out' and bend the ray 'in', so the new ray will intersect the original ray at some point along the path (that point is where the camera focuses). Problem is, more DOF needs more samples, and raymarching isn't exactly lightning fast :)

I discussed DOF before with las - think about it, as you march along the ray, you know the distance from the nearest surface. This is exactly what you need to know for 'real' DOF, in a single march. But how do you use that info? It's possibly impossible :(
added on the 2011-02-28 13:13:36 by psonice psonice
Re. the normals generation discussed in the toolbox thread (to avoid polluting that too much), I just tried 3 methods with my current scene:

Code:vec3 g1(vec3 point, vec2 e){ return (vec3(f(point+e.xyy),f(point +e.yxy),f(point +e.yyx))-f(point))/e.x; } vec3 g2(vec3 p, vec2 e) { //vec2 e = vec2(0.001, 0.0); return vec3(f(p+e.xyy), f(p+e.yxy), f(p+e.yyx)) / e.x; } vec3 g3(vec3 p) { vec2 e = vec2(.0001, -.0001); vec4 o = vec4(f(p+e.xyy), f(p+e.yyx), f(p+e.yxy), f(p+e.xxx)); return (o.wzy+o.xww-o.zxz-o.yyx)/(4.*e.x); }


g1/g3 both work flawlessly. g2 doesn't - I get big white patches in the distance with small values of e, and blurry normals with e high enough to remove the white patches. This is really annoying, because g2 should be significantly faster :(
added on the 2011-02-28 13:34:16 by psonice psonice
Code:vec3 g2(vec3 p) { vec2 e = vec2(0.001, 0.0); return vec3(f(p+e.xyy), f(p+e.yxy), f(p+e.yyx)) / e.x; }

works fine for me... (in my limited, shabby example that is)
added on the 2011-02-28 13:43:02 by raer raer
About DOF:
I tried randomly jittering p or d while marching, but that just gives you noisy results. It may work to jitter only when you've found a proper distance, but I can't figure out how atm... :/
added on the 2011-02-28 13:51:45 by raer raer
yeah, you'll need to raymarch several times (at least 3, many more for decent DOF) using fixed positions (maybe some jitter will still help?) and average. Basically, taking the average of several rays that converge on the focus point.

It's probably better to output the depth and fake DOF in post.

And yeah, I'd love to know why the faster normal method doesn't work for me.. it DOES work, but only with low values of e, which makes it useless. Maybe because I'm using lots of stuff with very sharp edges? It looks ok where the sphere + cube intersect in your pic though.
added on the 2011-02-28 14:04:53 by psonice psonice
What I mean is march till you hit a surface and then jitter position found and evaluate field again. That should save you some evaluations of the filed function. I don't know what to do with the results though atm...
added on the 2011-02-28 14:39:04 by raer raer
I don't think that will work (or at least, not well). The ray can pass very close to an object without hitting it, and you will get no DOF effect from that object. You'd maybe get DOF behind objects, but not infront.

Actually, that makes me think of a possible optimisation: say you want an object in the foreground, in focus, with a blurred background. You could raymarch as normal to a set distance (behind the object). That gives you normal speed and the early bailout if the ray hits the object. After that distance, you can change the parameters for a DOF effect (or maybe others), and you can turn down the accuracy to help speed.

added on the 2011-02-28 15:01:01 by psonice psonice
Sucks. Then I need to set up an FBO, render to that. Extra bytes and hassle.
I want to just send a quad down the pipiline again and sample the current back- and depthbuffer... :/
added on the 2011-02-28 15:42:56 by raer raer
Quote:
Actually, that makes me think of a possible optimisation: say you want an object in the foreground, in focus, with a blurred background.

Could work, but sounds a bit specific for one task only...
added on the 2011-02-28 15:46:01 by raer raer
psonice: The 3 f(p) eval approach more or less demands f(p) = 0. this might not be the case, especially if you walk steps like 0.25 * d.
Given that fact that you just have one normal evaluation per pixel the cost is almost neglectable...
added on the 2011-02-28 15:59:30 by las las

login