# pouët.net

Go to bottom

category: code [glöplog]
smash: yep, I fully understand that. There's 2 reasons I'm looking at this though:

1. in a complex scene, many objects are quite simple. Getting the distance outside the loop makes the loop simpler, faster, and in some cases more accurate. I'd call that a good optimisation :)

2. I'm interested to see how much can be done with a pure raytrace. So far, it's more than I thought, maybe 'complex enough' is possible?

I guess there's a 3 too: I need to improve my maths skills, and also learn more about raytracing/raymarching etc. Even a failed experiment is worth doing when you want to learn ;)
added on the 2011-02-20 18:20:54 by psonice
Quote:
I'm interested to see how much can be done with a pure raytrace

Have you seen avatar?
added on the 2011-02-20 20:22:13 by xernobyl
Hahahhaa pouetization!
here
added on the 2011-02-20 20:28:17 by las
Xernobyl: not in 4k ;)
added on the 2011-02-20 20:43:36 by psonice
las: :D

Plus, I'll join the reign with the standard "cubeminussphere":
added on the 2011-02-22 11:49:53 by raer
Junge, das sieht aber echt kaputt aus! Wie machst du die schwarzen Raender? :D
added on the 2011-02-22 12:30:09 by las
Maybe the epsilon for the normal calculation is too big? + Fix your aspect ratio ;)
added on the 2011-02-22 12:33:59 by las
Render(unter den Augen);
Aspect ratio: Ja. Is ja gut... ;)
added on the 2011-02-22 13:24:19 by raer
i guess it's the normal epsilon too big also - it should be pixel size at most, smaller still seems to work better. Nice rounded cube though :)

I'm still figuring out how to raytrace a cube :(
added on the 2011-02-22 13:53:41 by psonice
The black stuff is because lighting uses the sphere's normal at that point I suppose. The other artifacs go away with if (l < 0.002) in the raymarch function.

Code:``` varying vec3 v,EP; void main(){ gl_Position=gl_Vertex; v = vec3( gl_ModelViewMatrix*gl_Vertex ); EP= vec3( gl_ModelViewMatrix*vec4(0,0,-1,1) ); } ```

Code:``` varying vec3 v,EP; float sphere(vec3 p, float r) { return sqrt(p.x * p.x + p.y * p.y + p.z * p.z) - r; } float rbox(vec3 p, vec3 s, float r) { return length(max(abs(p)-s+vec3(r),0.0))-r; } float field(vec3 p) { float ds = sphere(p, 0.6); float db = rbox(p, vec3(0.5,0.5,0.5), 0.1); return (max(-ds, db)); } vec3 grad(vec3 p) { vec2 e = vec2(0.01, 0.0); return (vec3(field(p+e.xyy), field(p+e.yxy), field(p+e.yyx)) - field(p)) / e.x; } vec4 rm(vec3 p, vec3 d, float maxSteps){ vec3 startPos = p; float l, i; for(i=0.; i<1.; i+=1.0/maxSteps){ l = field(p); p += (l * d * .25); if (l < 0.002) { vec3 n = grad(p); float r = max(-dot(n,d), 0.0); return vec4(r, r, r, 1); } } return vec4(0, 0, 0, 1); } void main() { vec3 p=EP; //set ray origin vec3 d=v-p; //set ray direction gl_FragColor = rm(p, d, 100); } ```

Really damn slow... :)
added on the 2011-02-22 15:07:10 by raer
Code:`vec2 e = vec2(0.01, 0.0);`

This is the distance between point samples for your normal, 0.01 should be smaller than 1/(no. of pixels). I use 0.001.

Also, you have the normal calculation inside the raymarch loop. Does that play nicely with the glsl compiler? I thought (at least on older cards) that with a branch both sides of the branch are executed, which would mean your normal gets calculated for every step along the ray. That might be wrong though.

The 'other' way is to return just the length of the ray from the rm function. The other 2 bits of the vec3 get used for the number of iterations (which gets used for 'iteration count glow') and the size of the last step (wtf is that useful for anyway?). Then you calculate the end point from ray direction + length, and calculate your normal outside of the loop.
added on the 2011-02-22 15:34:07 by psonice
Code:``` p += (l * d * .25); ```

You are not twisting anything yet, take at least .75 ;)
added on the 2011-02-22 15:55:29 by las
Is that the reason for the .25? I wondered that, why we can't just use 1.0 :)

...but then I tried with 1.0, and accuracy seemed worse. 0.5 seemed worse too. Maybe I was using domain repetition or something?
added on the 2011-02-22 16:07:52 by psonice
Quote:

...and the size of the last step (wtf is that useful for anyway?)

Good question, I implemented it - remove it ;)
Maybe I though about stepping back or something like that.
added on the 2011-02-22 16:20:36 by las
See here and the other mentioned threads for the stepsize stuff.
added on the 2011-02-22 16:28:35 by las
thanks :)

Also, I just found a HUGE optimisation: when calculating the normal, use the distance function, NOT the raymarch function. Man, did I feel stupid when I saw that :D
added on the 2011-02-22 17:00:50 by psonice
Now with epsilon at 0.001 and some noise shit:
added on the 2011-02-22 19:05:43 by raer
And, no, the gradient function branch does not seem to always get executed in parallel. I'll try moving it out of the raymarch function though, just to see if speed does change...
added on the 2011-02-22 19:10:49 by raer
Code:``` Also, I just found a HUGE optimisation: when calculating the normal, use the distance function, NOT the raymarch function. Man, did I feel stupid when I saw that :D ```

WTF are you doing the whole time then to get your normals?
added on the 2011-02-22 19:47:33 by las
las: raymarching the scene from the camera position 6 times :O (it was an error, i wondered why suddenly a simple scene was going slow as fuck on my moderately fast work box!) I was joking about that being an optimisation btw ;)

Speaking of normals, I still didn't get iq's optimisation to work. With fairly large epsilon values I can see it shading, but obviously then it's all wrong.. lower values, and it's just a black screen.
added on the 2011-02-22 23:07:08 by psonice
I demand code for a spikeball because I am tooo lazy!
added on the 2011-02-24 13:03:54 by las
tan(). couldn't write the whole function because i am tooo lazy!
added on the 2011-02-24 13:22:16 by pommak

yes we can. no tan().
added on the 2011-02-24 16:29:15 by las
added on the 2011-02-24 16:47:37 by las
Fake SSS is the new SSAO!
added on the 2011-02-24 16:48:25 by kb_