pouët.net

Raymarching Beginners' Thread

category: code [glöplog]
March a couple of times while shifting the view and average. Gives you DOF too if you do it properly.
added on the 2011-05-11 20:59:03 by raer raer
just enforce 32x multisampling via the driver ;)
added on the 2011-05-12 09:55:26 by las las
No DOF with that, but probably faster... :)
added on the 2011-05-12 10:31:56 by raer raer
a13X_B:
Very nice! I demand sourcecode! :)
added on the 2011-05-12 10:39:02 by las las
Indeed, very nice (at least it was once I realised that pic was clickable.. i was wondering what was up with the worlds smallest screenshot ;) You probably want at least shading in the reflections though, to stop them turning pure white.

Speaking of which, my last experiment: http://www.youtube.com/watch?v=nGAqOF5L9Jc

Started off as a cornell box, trying to improve my lighting. It has a mix of AO + soft shadows, but it didn't look all that realistic still. Then I got bored, and added some mirrors. There's 2 reflection bounces I think (so reflected objects also reflect, but nothing beyond that). Guess what, it's slow ;) Probably passable for realtime on a really high end GPU, but I don't have one of those so it's ~5fps at 640x480 for me.
added on the 2011-05-12 11:27:53 by psonice psonice
I have to ask again, as I'm not really getting why it is:
Code: float r2=p.x*p.x+p.y*p.y; float r=r2-p.z*p.z*(1-p.z); float h = 4*r2+((3*p.z-2)*p.z); //2*x + 2*y + z^2 + 2*(z-1)*z float dr=sqrt(h * h);//modulus of the gradient float param1 = 0.1; float param2 = 0.7; return abs( (d-param1) / (dr+param2) ) * 0.75;


I get this result:
BB Image




Now I tried to to derive it myself. The gradient should be the total differential of the function (dx+dy+dz). What I get is:
2*x + 2*y + z^2 + 2*(z-1)*z

When I use that:
Code: float d =p.x*p.x+p.y*p.y - (1.0 - p.z)* p.z*p.z; float dr = 2.0*p.x + 2.0*p.y + p.z*p.z + 2.0*(p.z - 1.0)*p.z; //or dr = 2.0*p.x + 2.0*p.y + 3.0*p.z*p.z - 2.0*p.z; float param1 = 0.1; float param2 = 0.7; return abs( (d-param1) / (dr+param2) ) * 0.75;


it produces:
BB Image

Close, but no cigar. If I put in a sqrt(dr*dr), for getting an absolute value I suppose, I get similar results...
added on the 2011-05-12 11:59:32 by raer raer
@Rare: Don't know why, but I really like the colours in the first shot.
Some mix of the normal and dot(normal, rayDirection)...
added on the 2011-05-12 14:06:56 by raer raer
Trying to understand the process of rendering two triangles to the screen and setting up the rays using perspective projection. I can easily find some code, but I don't quite understand the mathematics. For example using code from iq's intro system examples.

Code:glRects( -1, -1, 1, 1 );

So this pretty much draws a quad. Then in the vertex shader:

Code:uniform vec4 fpar[4]; void main(void) { gl_Position=gl_Vertex; vec3 d=normalize(fpar[1].xyz-fpar[0].xyz); vec3 r=normalize(cross(d,vec3(0.0,1.0,0.0))); vec3 u=cross(r,d); vec3 e=vec3(gl_Vertex.x*1.333,gl_Vertex.y,.75); // eye space ray gl_TexCoord[0].xyz=mat3(r,u,d)*e; // world space ray gl_TexCoord[1]=vec4(.5)+gl_Vertex*.5; // screen space coordinate };

I got the view matrix part. The resolution is 800 x 600. So I understand where 1.333 comes from but I don't understand the math behind multiplying the x component by it or where .75 comes from for z component. Also, I see this is mapping the initial vertices from (0,0) to (1,1). but why?

added on the 2011-05-12 16:49:02 by jazz jazz
Alright, I want to join the fun! Here's my first attempt:

BB Image

I call this masterpiece "Floating Mickey Mouse in marble".. ;)

Written in Processing, thanks to this thread and some snippets from the "Raymarching toolbox" thread.

I must say that while I understand the basics of how the AO works, the code was kind of over my head. I'm not sure if the brighter patch below "mickey" is a bug in my code, or some kind of artifact you get with this method?

Also, holy cow is this slow! Takes a couple of seconds to render in 320x240! No wonder, since even for that low res image my distance function is called 26509453 times. Yep, 26 million times!
Am I doing something wrong, or is that par for the course?
added on the 2011-05-12 17:10:57 by Sdw Sdw
Sdw: i (and others, of course) found that it's about keeping a gentle balance between "number of maximum marching steps" versus "maximum distance to surface (aka 'epsilon')". i suspect one or both of them is chosen too large/small in your case.

jazz: well that eye space ray mapping the initial vertices to be
[-1.333, -1, 0.75] - top left
[-1.333, 1, 0.75] - bottom left
[1.333, 1, 0.75] - bottom right
[1.333, -1, 0.75] - top right
because this shader program is done for every vertex, so 4 times in total.
the x and y coordinates maintain the correct aspect ratio, as you correctly figured out yourself, and the z coordinate defines the focal length of the camera in x and in y direction.
think about the generated eye space vertices as the camera lens/window (which it is, in a simple pinhole camera model), which is then projected from camera to world space.
added on the 2011-05-12 17:22:01 by hcdlt hcdlt
Boy do I feel stupid, I had a bug in my exit-condition, so for all points where the ray totally missed any geometry, I iterated up until I reached my max-iteration.
Down to 1.8 million distance calc per frame, and now it actually MOVES, not very smooth, but still! :D
added on the 2011-05-12 17:30:01 by Sdw Sdw
Sdw: that's exactly what happened to me too! did not believe that you are as clumsy as me at first ;-)
added on the 2011-05-12 17:35:45 by hcdlt hcdlt
sdw: it's a good start. You're doing too many iterations I think - that works out at 345 iterations per pixel. 100 or less is probably fine for this scene, which should take you from spf to fps at least :)

Are you marching until there's a collision, or do you have a cutoff? The last bit of marching before it hits the object is the most expensive, so it's good to bail out early. Instead of checking for distancefunction <= 0 try 0.1 or whatever - play with it until it doesn't look bad :)

Also make sure you're not marching forever if the ray goes past the object. If the total distance is bigger than the distance to the back of the scene, bail out.

The 'shadow ring' is probably a bug in your AO code, or a 'feature' of the implementation. Basically, it does a second raymarch, starting at the point on the surface of the object, and moving along the normal. You only use a few iterations here (like <10 normally). You just take a value for 'how close is the nearest object (near = higher) and sum it for each iteration. That's your shadow. It looks like your AO stops counting the sphere if the ray marches right through it - the value probably turns negative. You need to treat that case as 'maximum shadow' rather than 'no shadow' or worse 'add light'.
added on the 2011-05-12 17:47:17 by psonice psonice
las: It's quite a mess(orientation is wrong and code is nonoptimized too) but here you go(once again thanks knighty for cool method)
Code: float heart(vec3 z) { vec3 z2=z*z; float lp = z2.x + 2.25*z2.y + z2.z - 1.0; float rp = z2.x*z2.z*z.z + 0.08888*z2.y*z2.z*z.z; return lp*lp*lp-rp; } float sextic(vec3 z) //Barth's sexstic { vec3 z2=z*z; vec3 z3=(0.5*(1.+sqrt(5.)))*z2-z2.yzx; float p1=4.*z3.x*z3.y*z3.z; float r2=dot(z,z)-1.; float p2=(2.+sqrt(5.))*r2*r2; return p2-p1; } float dheart(vec3 z) { float vs=heart(z); vec3 v=1./Eps*(vec3(heart(z+vec3(Eps,0.,0.)),heart(z+vec3(0.,Eps,0.)),heart(z+vec3(0.,0.,Eps)) )-vec3(vs)); return vs/(length(v)+Eps); } float dsextic(vec3 z) { float vs=sextic(z); vec3 v=1./Eps*(vec3(sextic(z+vec3(Eps,0.,0.)),sextic(z+vec3(0.,Eps,0.)),sextic(z+vec3(0.,0.,Eps)) )-vec3(vs)); return vs/(length(v)+Eps); }

and then
Code: float f(in vec3 pos) { float scen = plane(pos,vec3(0.0,0.0,1.0),vec3(-1.0)); float heart = dheart(pos); float sextic = max(dsextic(pos*0.6),sphere(pos,3.5)); scen = min(sextic,scen); return min(heart,scen); }

apply materials and voila. I just thought those two would compliment each other.

Meta hearts anyone? Or maybe something with Möbius strip, wouldn't normals go crazy tho?
added on the 2011-05-12 18:06:57 by a13X_B a13X_B
psonice: Once I fixed the "iterate-towards-infinity" bug I mentioned earlier, I'm actually below 30 distance calcs per pixel, and things look good!

You were correct that it was a bug in the AO routine creating the "ring". I had just copy-pasted from the toolbox thread, but once I actually sat down and figured out how it worked, it was just as you said - negative values. My sphere returned a negative distance in the closest AO-steps, making the ring appear. I just added a check where distance <0 is treated as 0 in the AO and everything works great.

Now things are starting to looks so good that I want to run them in fullscreen/highres at reasonable framerate, so I guess I'll need to start looking into GPU programming soon. What's the easiest to get started with?
added on the 2011-05-13 00:12:19 by Sdw Sdw
take a look at IQ's 4k framework
psonice: Right, thanks, and I've got some ideas too. And finally I'm going to implement shading and cool lighting and stuff.

By the way, what about shadows from more than one light-sources?
added on the 2011-05-13 09:25:43 by a13X_B a13X_B
sdw: i really recommend some application that lets you play with the shader, and not worry about anything else. It saves a ton of time, and makes it much easier to get the shader looking good, then you can worry about building the exe at the end. On mac, I use quartz composer - it gives me a glsl shader with live editing and tons of tools to feed the inputs with LFOs, timelines, images or whatever. On PC, maybe VVVV?

Alex: for multiple shadows you just repeat the shadow routine for each light source, then add the shadow values and subtract that from the pixel value. I tend to use a mix of AO and 1 light with soft shadow. At some point I'll probably add more lights but without shadows (for nicer lighting, things like rim lighting really help, don't need shadows, and are super cheap :)
added on the 2011-05-13 10:30:49 by psonice psonice
a13X_B: I'll give metahearts a try - my gf will love it :D
added on the 2011-05-13 13:27:31 by las las
I wanted to do that... :)

The heart you posted is not working for me either...
added on the 2011-05-13 13:47:49 by raer raer
Quote:

sdw: i really recommend some application that lets you play with the shader, and not worry about anything else. It saves a ton of time, and makes it much easier to get the shader looking good, then you can worry about building the exe at the end. On mac, I use quartz composer - it gives me a glsl shader with live editing and tons of tools to feed the inputs with LFOs, timelines, images or whatever. On PC, maybe VVVV?

Or just use WebGL - that makes things pretty straight forward.
Go ahead and "steal" the nice GLSL sandbox from mr. doob or just take what you need from http://pouet.net/prod.php?which=56922.

Maybe bero is going to release ".marchfabrik" - a really nice tool :D
added on the 2011-05-13 14:07:39 by las las
the way heavy glsl shaders are compiled in webgl browsers nowadays just kills a whole idea of shadertoy imo :[

personally i use Derivative Touch - it's a nice tool very similar to vvvv but with Houdini-like interface (same developers) and it does glsl. and it's free for personal use.
added on the 2011-05-13 18:48:00 by ton ton
why you ppl are into glsl so much? if you only knew the power of the hlsl side...
added on the 2011-05-13 19:16:55 by unc unc
because hlsl only works on one platform, and glsl works on pretty much all of them?
added on the 2011-05-13 21:14:42 by psonice psonice

login