Raymarching Beginners' Thread
category: code [glöplog]
Actually you don't need the abs(). did it just to take a look inside.
Thanks. It works. The question is how and why:
?
Code:
dr=sqrt(4*r2+((3*z-2)*z)^2);//modulus of the gradient
return abs((r-param1)/(dr+param2))*0.75;
?
The general (?) formula is:
DE=scaleFactor*f(x,y...)/(|grad(f(x,y...))|+c)
You can look at it as single step of newton method on the ray going through (x,y...) and which direction is given by the gradient of f() at (x,y...). 'c' is a positive value (could be a constant or a function) that I added in order to avoid getting infinite result. It turns out that for some well choosen 'c' it's possible to get a good distance estimate but that 'c' depends on f(). That's why I kept it as a parameter. Also 'scaleFactor' depends on 'c'. in fact it is the inverse of the Lipschitz constant of
f(x,y...)/(|grad(f(x,y...))|+c).
It is maybe possible to iterate the process:
f(x,y...)_n+1 = f(x,y...)_n/(|grad(f(x,y...)_n)|+c)
Haven't try this yet so no warranty.
DE=scaleFactor*f(x,y...)/(|grad(f(x,y...))|+c)
You can look at it as single step of newton method on the ray going through (x,y...) and which direction is given by the gradient of f() at (x,y...). 'c' is a positive value (could be a constant or a function) that I added in order to avoid getting infinite result. It turns out that for some well choosen 'c' it's possible to get a good distance estimate but that 'c' depends on f(). That's why I kept it as a parameter. Also 'scaleFactor' depends on 'c'. in fact it is the inverse of the Lipschitz constant of
f(x,y...)/(|grad(f(x,y...))|+c).
It is maybe possible to iterate the process:
f(x,y...)_n+1 = f(x,y...)_n/(|grad(f(x,y...)_n)|+c)
Haven't try this yet so no warranty.
what's the name for the msdos raymarching intro with hexagons moving in eyefish with full asm sources ?
Thanks. I'll try that on some other formula.
Barti this one? http://www.pouet.net/prod.php?which=53816
yes, thank you
A teaser :)
Wow! it works even with 6th order algebraic... let's try higher order ones... and non algebraic ones :o)
Code:
#define Phi (0.5*(1.+sqrt(5.)))
#define Tau (1.+2.*Phi)
#define Fn Barth6
float Barth6(vec3 z)//Barth's sexstic
{
vec3 z2=z*z;
vec3 z3=Phi2*z2-z2.yzx;
float p1=4.*z3.x*z3.y*z3.z;
float r2=dot(z,z)-1.;
float p2=Tau*r2*r2;
return p2-p1;
}
float DE(vec3 z)
{
float vs=Fn(z);
//no need to derive gradient analytically.
vec3 v=1./Eps*(vec3(Fn(z+vec3(Eps,0.,0.)),Fn(z+vec3(0.,Eps,0.)),Fn(z+vec3(0.,0.,Eps)))-vec3(vs));
return param1*abs(vs)/(length(v)+param2);
//return param1*vs/sqrt(dot(v,v)+param2*param2);//alternative formula
}
Wow! it works even with 6th order algebraic... let's try higher order ones... and non algebraic ones :o)
Are you trying to raymarch your penis?
it could be cool to see code and renderings following...for those who do not want to/can open a project...
las, Decipher, psonice: Thanks for the kind words.
knighty: Neat, put it to Raymarching toolbox please.
Bartoshe: Here you go
Did anyone notice that this guy is a living collection of metaballs?
knighty: Neat, put it to Raymarching toolbox please.
Bartoshe: Here you go
Did anyone notice that this guy is a living collection of metaballs?
I have the metaballs to make a dolphin see dead deer examples...
It's made my metaballs with add potential and subtract potential.
It was my medium to communicate with dolphins at now.
.scn export of dead deer can make you happy to draw a dolphin.
that's one ugly dolphin. sorry. :D
It doesn't look that bad if you imagine it shaded.
xernobyl: but it isn't shaded. not even HLRed.
Bartoshe: add some potential scale vectors or directional potential and you can do the same in less balls.
Bartoshe: add some potential scale vectors or directional potential and you can do the same in less balls.
so I have this raymarching thing.
It's the first thing I've done in glsl that wasn't completely trivial. It is realtime but it is slow realtime because my graphics card is a rather underpowered Radeon 4650 and also the shader-host and demo-script are in unoptimised lisp and I'm not using the fastest lisp so yeah. Could probably go faster. I have no idea what to do for interesting surfaces to raymarch that couldn't just be raytraced, or anything interesting to do with the surfaces besides that basic phong-shading + color but I'm sure I'll find something before Syntax or prehaps Flashback.
the one really visible error is that it hits iteration_limit on the infinite ground plane (of course), leading to it curve inwards towards any other surface at the horizon, as rays that are near those surfaces hit iteration_limit faster. The solution is to put iteration_limit up, but that slows it down a lot. I think it could look kinda cool though, especially when I get it rotating.
also this thread needs more images.
It's the first thing I've done in glsl that wasn't completely trivial. It is realtime but it is slow realtime because my graphics card is a rather underpowered Radeon 4650 and also the shader-host and demo-script are in unoptimised lisp and I'm not using the fastest lisp so yeah. Could probably go faster. I have no idea what to do for interesting surfaces to raymarch that couldn't just be raytraced, or anything interesting to do with the surfaces besides that basic phong-shading + color but I'm sure I'll find something before Syntax or prehaps Flashback.
the one really visible error is that it hits iteration_limit on the infinite ground plane (of course), leading to it curve inwards towards any other surface at the horizon, as rays that are near those surfaces hit iteration_limit faster. The solution is to put iteration_limit up, but that slows it down a lot. I think it could look kinda cool though, especially when I get it rotating.
also this thread needs more images.
that and it *really* needs some anti-aliasing.
actually the real solution is to find some way to control rays other than a hard limit on the number of iterations/marching steps, but whatever.
main: good start. Nice shadows too. There's some aliasing around the edges, maybe try changing the epsilon value for the normal calculation, I found that can reduce those artifacts a bit.
You can speed it up easily with a few optimisations I suspect, although these are somewhat scene-specific:
- You can raytrace the floor. It's trivial to do, and has no distance limit or artifacts near edges. Even better, you only need to do this once per pixel, not once per step, and you remove it from the distance equation which can help your step size.
- You can make a bounding box for the object in the centre (a sphere would be easy). Raytrace that once, just as a hit test, and only march if it's inside the bounds. You probably don't need to march 25% of the pixels in this scene at all (and more for the shadows).
- Using the bounding box, you can skip any marching outside the bounds. Jump to the front surface, march, if the point is outside the bounds stop the march and use the raytraced ground distance instead.
- You could raytrace the sphere in the middle too, which would speed up the marching through the hole
You can speed it up easily with a few optimisations I suspect, although these are somewhat scene-specific:
- You can raytrace the floor. It's trivial to do, and has no distance limit or artifacts near edges. Even better, you only need to do this once per pixel, not once per step, and you remove it from the distance equation which can help your step size.
- You can make a bounding box for the object in the centre (a sphere would be easy). Raytrace that once, just as a hit test, and only march if it's inside the bounds. You probably don't need to march 25% of the pixels in this scene at all (and more for the shadows).
- Using the bounding box, you can skip any marching outside the bounds. Jump to the front surface, march, if the point is outside the bounds stop the march and use the raytraced ground distance instead.
- You could raytrace the sphere in the middle too, which would speed up the marching through the hole
"the one really visible error is that it hits iteration_limit on the infinite ground plane (of course), leading to it curve inwards towards any other surface at the horizon"
I had the same problem, I solved it (maybe temporarily) by augmenting the epsilon from 0.005 to 0.1. Don't know if it's the right method though...
I had the same problem, I solved it (maybe temporarily) by augmenting the epsilon from 0.005 to 0.1. Don't know if it's the right method though...
Another thing: Introduce a zFar in case you know that after stepping a certain distance into the space there wont be anything you want to hit. Otherwise the rays hitting nothing at all will become the most expensive rays...
For more images I'll just leave this old thing here...
For more images I'll just leave this old thing here...