## Raymarching Beginners' Thread

**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 ;)

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 ;)

**Quote:**

I'm interested to see how much can be done with a pure raytrace

Have you seen avatar?

Hahahhaa pouetization!

here

here

Xernobyl: not in 4k ;)

las: :D

Plus, I'll join the reign with the standard "cubeminussphere":

Plus, I'll join the reign with the standard "cubeminussphere":

Junge, das sieht aber echt kaputt aus! Wie machst du die schwarzen Raender? :D

Maybe the epsilon for the normal calculation is too big? + Fix your aspect ratio ;)

Render(unter den Augen);

Aspect ratio: Ja. Is ja gut... ;)

Aspect ratio: Ja. Is ja gut... ;)

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 :(

I'm still figuring out how to raytrace a cube :(

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.

Really damn slow... :)

**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... :)

**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.

**Code:**

```
p += (l * d * .25);
```

You are not twisting anything yet, take at least .75 ;)

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?

...but then I tried with 1.0, and accuracy seemed worse. 0.5 seemed worse too. Maybe I was using domain repetition or something?

**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.

See here and the other mentioned threads for the stepsize stuff.

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

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

Now with epsilon at 0.001 and some noise shit:

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...

**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?

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.

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.

I demand code for a spikeball because I am tooo lazy!

tan(). couldn't write the whole function because i am tooo lazy!

yes we can. no tan().

Fake SSS is the new SSAO!