Raymarching Toolbox Thread
category: code [glöplog]
Under some circumstances the ao version with abs() does not work properly...
This seems to be more correct :)
Only difference, starting value for o and additions instead of subtractions.
What's the best way to crunch those two into one function?
This seems to be more correct :)
Code:
float ao(vec3 p, vec3 n, float d, float i) {
float o,v;
for (o=1.;i>0.;i--) {
o-=(i*d-f(p+n*i*d))/exp2(i);
}
return o;
}
float sss(vec3 p, vec3 n, float d, float i) {
float o,v;
for (o=0.;i>0.;i--) {
o+=(i*d+f(p+n*i*d))/exp2(i);
}
return o;
}
Only difference, starting value for o and additions instead of subtractions.
What's the best way to crunch those two into one function?
Okay... tricks
sss = ao(p,n,-d,i)-1.;
Works properly.
Code:
float ao(vec3 p, vec3 n, float d, float i) {
float o,v;
for (o=1.;i>0.;i--) {
o-=(i*d-f(p+n*i*abs(d)))/exp2(i);
}
return o;
}
sss = ao(p,n,-d,i)-1.;
Works properly.
Sorry for spamming...
negative d -> sss, positive d -> ao
Code:
float ao(vec3 p, vec3 n, float d, float i) {
float o,s=sign(d);
for (o=s*.5+.5;i>0.;i--) {
o-=(i*d-f(p+n*i*d*s))/exp2(i);
}
return o;
}
negative d -> sss, positive d -> ao
I would not mind hosting a wiki related to raymarching.
I just set one up, never did before so I have not set any settings yet. Let me know if there is interest in using this.
http://rmwiki.gammalyrae.com/index.php/Main_Page
I just set one up, never did before so I have not set any settings yet. Let me know if there is interest in using this.
http://rmwiki.gammalyrae.com/index.php/Main_Page
Imho this threads still works pretty well and there's no need for a wiki yet.
Quote:
Imho this threads still works pretty well and there's no need for a wiki yet.
You have my vote. I'll cleanup and add the good info to my webpage also but this thread will certainly do and everyone here already have an account to add to the thread.
Fine, I will remove it then.
Decipher's (?) noise used in Muon Baryon and Magnus found here
Code:
/* Given a position, this function generates a 3D co-ordinates based,
* reconstructible static noise. */
float noise(vec3 position)
{
position.x += position.y * 57. + position.z * 21.;
return sin(cos(position.x) * position.x);
/* The following is an alternative for the previous line:
* return fract(position.x * position.x * .0013) * 2. - 1.; */
}
/* Given a position, this function generates a 3D co-ordinates based,
* reconstructible linearly interpolated smooth noise.
*
* This function uses the noise() function above for its underlying
* noise texture. */
float smooth_noise(vec3 position)
{
vec3 integer = floor(position);
vec3 fractional = position - integer;
return mix(mix(mix(noise(integer),
noise(integer + vec3(1, 0, 0)),
fractional.x),
mix(noise(integer + vec3(0, 1, 0)),
noise(integer + vec3(1, 1, 0)),
fractional.x),
fractional.y),
mix(mix(noise(integer + vec3(0, 0, 1)),
noise(integer + vec3(1, 0, 1)),
fractional.x),
mix(noise(integer + vec3(0, 1, 1)),
noise(integer + 1.), fractional.x),
fractional.y),
fractional.z) * .5 + .5;
}
/* Given a position, this function constructs the oh-so-famous Perlin
* noise. */
float perlin(vec3 position)
{
return smooth_noise(position * .06125) * .5 +
smooth_noise(position * .125) * .25 +
smooth_noise(position * .25) * .125;
}
Instead of
you might want to use
Code:
vec3 fractional = position - integer;
you might want to use
Code:
vec3 fractional = smoothstep(0., 1., position - integer);
las: Your smooth_noise is rather the famous perlin noise. However its not true perlin noise since you use different permutation values. Not that it matters since this is about speed but just so anyone that uses it knows what they are using.
Your perlin function is a fractal sum
Your perlin function is a fractal sum
Xentic: You're right, last time when I was posting it on pouet I must have commented wrongly. Sorry for my mistake. The second is Perlin while the last one is a very cheap and approximate fractal sum of Perlin. Thanks for the heads up.
There are several ways to create shadows...
This is what I tried and it seems to work nice for simple objects/scenes.
This is what I tried and it seems to work nice for simple objects/scenes.
Code:
// p pos, l direction to light - normalized, d stepwidth, i number of steps
float shadow(vec3 p, vec3 l, float d, float i) {
float o;
for (o = 0.; i > 0.; i--) {
o += f(p+l*i*d);
}
return clamp(o, 0.0, 1.0);
}
Another way...
Code:
//p point as usual. l direction to lightsource - normalized, r "some kind of shadow hardness", d stepwidth, i number of steps
float shadow(vec3 p, vec3 l, float r, float d, float i) {
float o;
for (; i>0.; i--) {
o=min(f(p+l*i*d),r);
}
return max(o/r, 0.);
}
//sample usage
shadow(p, normalize(vec3(sin(t)*2.0, 10.0+abs(sin(t))*2.0, 3.0*cos(t))-p), 0.5, 0.5, 7.0);
Improve this code ;)
Code:
//repeat around y axis n times
void rp(inout vec3 p, float n) {
float w = 2.0*pi/n;
float a = atan(p.z, p.x);
float r = length(p.xz);
a = mod(a+pi*.5, w)+pi-pi/n;
p.xz = r*vec2(cos(a),sin(a));
}
//sample
rp(p, 6.0);
return box(p+vec3(0.5,0.0,0.0), vec3(0.15, 1.85, 1.85));
My own soft shadow function:
Code:
// pos = point on surface, l = light position, r = shadow softness factor, f = shadow strength, i = step count
float softShadow(vec3 pos, vec3 l, float r, float f, float i) {
float d;
vec3 p;
float o = 1.0, maxI = i, or = r, len;
for (; i>1.; i--) {
len = (i - 1.) / maxI;
p = pos + (l * len);
r = or * len;
d=ƒ(p);
o -= d < r ? (r - d)/(r * f) : 0.;
if(o < 0.) break;
}
return o;
}
That last one is for point lights btw. It does seem to work ok with a normalised light direction too, and it kind of works for AO if you feed it a normal.
Discussion about a trick for 1k raymarchers :: lighting
Ohh damn, I forget that one :)
That trick is indeed worth mentioning
That trick is indeed worth mentioning
Generalized rotation macro:
Usage: R(p.yz,time)
(yes, constructions like p.yz.x actually work in HLSL)
Code:
#define R(p,a) p=float2(p.x*cos(a)+p.y*sin(a),p.y*cos(a)-p.x*sin(a));
Usage: R(p.yz,time)
(yes, constructions like p.yz.x actually work in HLSL)
Works in GLSL too.
KK: Of course they should. The swizzle operator returns just another vector. And considering the whole thing is implemented with the KISS ideology, swizzling a swizzled vector should function just fine. :)
Code:
float sphere(float x, float y, float z, float r)
{
return sqrt(x * x + y * y + z * z) - r;
}
Obvious GLSL equivalent (might by faster?)
Code:
float sphere(vec3 p, float r) {
return length(p) - r;
}
Code:
#define R(p,a) p=cos(a)*p+sin(a)*float2(-p.y,p.x); // hlsl
I'm usually using this shorter form for rotation