Dark Bit Factory & Gravity

GENERAL => Projects => Topic started by: Rbz on March 09, 2011

Title: Raymarching Beginners' Thread
Post by: Rbz on March 09, 2011
Here a project page for everyone to start learning raymarching with distance fields (http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf) or also called sphere tracing (http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf).

This thread is inspired on pouet  (http://www.pouet.net/topic.php?which=7920&page=1&x=13&y=10)page with same name, where beginners already made great progress.

Well, I'm also a beginner on this subject but I was managed to understand it's principle reading a great article by @lx:
http://code4k.blogspot.com/2009/10/potatro-and-raymarching-story-of.html#more

So, I've made an example using RenderMonkey 1.82 (http://developer.amd.com/archive/gpu/rendermonkey/pages/default.aspx#download) that use opengl and directx for you to start, it's a colorful rotated cube :).

Also there's an exe with my current progress.

Our function tool box (all code came from pouet):
Code: [Select]
float3 RotateXAxis(float3 p, float angle)
{
    return float3(p.x, p.y * cos(angle) + p.z * sin(angle), p.z * cos(angle) - p.y * sin(angle));
}

float3 RotateYAxis(float3 p, float angle)
{
    return float3(p.x * cos(angle) + p.z * sin(angle), p.y, p.z * cos(angle) - p.x * sin(angle));
}

float3 RotateZAxis(float3 p, float angle)
{
    return float3(p.x * cos(angle) + p.y * sin(angle), p.y * cos(angle) - p.x * sin(angle), p.z);
}

float capsule(float3 p, float r, float c) {
   return lerp(length(p.xz)-r, length(float3(p.x,abs(p.y)-c,p.z))-r, step(c,abs(p.y)));
}

float plane(float3 p)
{
   return abs(p.y);
}

float sphere(float3 p, float r)
{
   return length(p) - r;
}

float cube(float3 p, float r)
{
   return max(max(abs(p.x) - r, abs(p.y) - r), abs(p.z) - r);
}

//distance to a rounded cube:
float distToCBox( float3 p, float3 box, float rad )
{
   return length( max( abs(p) - box + float3(rad,rad,rad), 0.0 ) ) - rad;
}

float3 GetNormal(float3 p)
{
   float eps = 0.1f;

   return
      normalize(
         float3(
            distance(p + float3(eps, 0, 0)) - distance(p - float3(eps, 0, 0)),
            distance(p + float3(0, eps, 0)) - distance(p - float3(0, eps, 0)),
            distance(p + float3(0, 0, eps)) - distance(p - float3(0, 0, eps))));
}

//negative d -> sss, positive d -> ao
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;
}

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

float perlin(vec3 p) {
vec3 i = floor(p);
vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
a.xy = mix(a.xz, a.yw, f.y);
return mix(a.x, a.y, f.z);
}



Choose your preferred api (dx9 or ogl) and start raymarching!

Title: Re: Raymarching Beginners' Thread
Post by: Shockwave on March 09, 2011
That looks great, the twister looks like it's made out of plastacine. :)

I've been reading the Pouet thread a bit, it would be cool if some other people here got interested in this.
Title: Re: Raymarching Beginners' Thread
Post by: efecto on March 09, 2011
Interesting stuff and I've been trying meself, but somehow I'm limited to planes, spheres and cylinders.
Cubes just don't work :(
Probably something in the calling code before the shader.

It's on my todo list but first concentrate on destruction entry

Title: Re: Raymarching Beginners' Thread
Post by: Xetick on March 09, 2011
The pouet thread(s) are a wealth of information when it comes to raymarching.

For the ones that want to see some example of what can be done with raymarching
(http://www.plane9.com/content/scenes/70/scene.jpg)

The following two are essentially a bunch of sin/cos values and thats the fun part with it. The work/reward ration is really good with raymarching. Once you have something working it requires very little work to make interesting scenes.
(http://www.plane9.com/content/scenes/25/scene.jpg)
(http://www.plane9.com/content/scenes/41/scene.jpg)

This isn't realtime though, 1fps I heard. But has global illumination. I really like the design and how this is synced to the music.
[youtube]http://www.youtube.com/watch?v=BtEQ2cz-NfM[/youtube]

Haven't looked into it that much but it's certainly on my list of things to do
Title: Re: Raymarching Beginners' Thread
Post by: combatking0 on March 09, 2011
I've always wanted to try 3D rendering software, but found the big contenders (including "Maya") to be too processor intensive and fiddly to use.

I think I'll give RenderMonkey a try.

Does the term raymarching refer to a lighting effect or a distortion effect?
Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 09, 2011
@combatking0: the basic concept is constructing a ray from your camera position into your scene, from that point you will be "marching" in steps until you hit a surface and then you can extract information from this surface like colors etc.

Btw, I've managed to add shadows and ambient occlusion, this code was kinda provided by las/mercury on here (http://www.pouet.net/topic.php?which=7931&page=2), I'll post an image and perhaps an .exe tomorrow :)

Code: [Select]
//negative d -> sss, positive d -> ao
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;
}

// 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);
}
Title: Re: Raymarching Beginners' Thread
Post by: Kirl on March 10, 2011
Great stuff rbz, hope to get started as well someday, love the movie you posted!

CK, have a look at Cinema4d by Maxon. It's one of the more user friendly, fully featured 3d software packages around. I'm somewhat of an expert on it, so you can shoot me mail whenever you get stuck.
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on March 10, 2011
K+ for rounding up this info, This is exactly what I've been needing for my voxel engine. I was planning on going down the Sparse Octree Voxel Traversal meathod but I really hated the idea of stepping forward finding a voxel that was full and backing up only to step forward by half the original step size. With this meathod the ray is constantly moving forward. You never have to take a step backwards and you still have a step size that will accellerate vast empty expanses spending more time in densely populated areas.

At the moment I am testing my voxel engine at a resolution of 640x480 in an environment of 256x256x256 so long as most of the visible voxels are close by I can even push the resolution up to 1024x768 with no obvious slow down, but once you enter into an open area its far too slow to even think of any resolution higher than 640x480.

Thanks for gathering all of this info into one post.

Edit - Hehehe It worked like a dream worth some extra karma to rbz
 Resolution=1024x768
 Environment=128x128x128
 Framerate is acceptable
Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 10, 2011
Well done Rain_storm, it works pretty well here on 1280x1024 res and I believe it's software rendered?

Here's an image with shadows added.
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on March 10, 2011
Yup thats all software rendered. The best thing is:
rgba == 0, distance != 0 (empty voxels)
rgba != 0, distance == 0 (filled voxels)
looks like a marriage made in heaven

I've been playing around with the cube distance function from your first post. Its starting to look like a morphed square but still aint got anything 3D yet. Will keep at this.

Do you think it would be possible to model a SuperShape as a distance function? That would be awesome.
Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 10, 2011
Quote
Do you think it would be possible to model a SuperShape as a distance function? That would be awesome.
I also don't know, need try more of those math formulas.

But I think you can do some nice things with just sin and cos while distorting basic shapes like a sphere.
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on March 11, 2011
Okay I got the cube distance function to work, quite slow but its working nonetheless, My GFX card (is card the right word when its the internal built into the motherboard variety) is ancient technology, without the benefit of shaders, so this is all done in software.

Next I'll be moving on to GetNormal...
Code: [Select]
float3 GetNormal(float3 p)
{
   float eps = 0.1f;
   return
      normalize(
         float3(
            distance(p + float3(eps, 0, 0)) - distance(p - float3(eps, 0, 0)),
            distance(p + float3(0, eps, 0)) - distance(p - float3(0, eps, 0)),
            distance(p + float3(0, 0, eps)) - distance(p - float3(0, 0, eps))));
}

This is awesome stuff, I'm like a child on Christmas morning here.

Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 11, 2011
Nice work!

Here's a "domain repetition", a trick with "mod(p,1.0)" (glsl) or "fmod(p,1.0)" (hlsl), thanks iq/rgba for that :), added "ao + noise" which was provided by las/mercury once again :).

Code: [Select]
float perlin(vec3 p) {
vec3 i = floor(p);
vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
a.xy = mix(a.xz, a.yw, f.y);
return mix(a.x, a.y, f.z);
}
Title: Re: Raymarching Beginners' Thread
Post by: combatking0 on March 11, 2011
Thanks Kirl and Rbz. K+'s there for explaining how it works and for suggesting some 3D software for beginners. I'll have a look at it.
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on March 11, 2011
How do you take the intersection / union of two objects?
Here I am trying to break out of the ray traversal loop if
the ray is intersecting the cube but outside the sphere. This should give the intersection (a cube with a sphere cut out of its center) but instead Im getting the union (a sphere and cube overlapping)

Code: [Select]
    real d1 = cube(ray, 8.0);
    real d2 = sphere(ray, 10.0);
    if ((d1 < 0.0) && (d2 > 0.0)) {
        break;
    }
    real d = min(d1, d2);

Edit : I figured it out it was the distance that I was taking for the step sometimes it was less than the minimum step size and it ended up breaking out of the loop because of that

Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 11, 2011
Try it using "max" instead and negating d1 or d2:, you should get same results without "if" statement:
max(d1, d2);
max(-d1, d2);
max(d1, -d2);
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on March 11, 2011
Thanks rbz thats much more efficient and cleaner, but now I have another problem with the capsule function. It uses lerp and step.
Code: [Select]
float capsule(float3 p, float r, float c) {
   return lerp(length(p.xz)-r, length(float3(p.x,abs(p.y)-c,p.z))-r, step(c,abs(p.y)));
}

I figured out that lerp is just a linear interpolation, o it should be the exact same as taking the average, is this correct?
Code: [Select]
lerpx = (ax+bx)/2
lerpy = (ay+by)/2
lerpz = (az+bz)/2

But what is the step function? Does anyone know how I translate that into c?
Code: [Select]
step(c,abs(p.y))
Title: Re: Raymarching Beginners' Thread
Post by: Rbz on March 11, 2011
"lerp(a,b,s)" (hlsl) or "mix(a,b,s)" (glsl) linearly interpolate between a and b.
Code: [Select]
return a+s*(b-a);
And step(a,x) returns (x >=a ) ? 1 : 0
Code: [Select]
if(x>=a) return 1;
else return 0;


Title: Re: Raymarching Beginners' Thread
Post by: Xetick on March 12, 2011
I think I'll give RenderMonkey a try.

Depending on what you want to do. Plane9 (http://www.plane9.com) might be worth looking at for experimentation projects.

The good

The bad

I haven't tried render monkey though so I'm not sure of its advantages
Title: Re: Raymarching Beginners' Thread
Post by: benny! on March 26, 2011
Awesome thread. Needs to have a deeper look at in soon!
Title: Re: Raymarching Beginners' Thread
Post by: Shockwave on April 25, 2011
Seems like someone else has had the same idea as Rain Storm;

http://www.pouet.net/prod.php?which=56879
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on April 25, 2011
Thats a minecraft hack not a demo. Funny that it doesn't run on this machine (much like Minecraft)

I'm heavily into modding games and I've played around with Minecrafts internals. Theres just something about the usage of java as a source language, lwjgl as an interface to OpenGL and there's definately something fishy about these two texture maps...
Title: Re: Raymarching Beginners' Thread
Post by: ninogenio on April 25, 2011
really really great stuff rbz and rain,

i will need to break all the info up and try some stuff out. cheers.
Title: Re: Raymarching Beginners' Thread
Post by: las on May 25, 2011
Nice :)
Keep it coming!

(http://research.mercury-labs.org/schillerdings.png)
Posted that one on pouet already, but that's the last thing I'll post in public for a while.
I'm working on "something".

I use FX Composer and Rendermonkey.
FX Composer works better with HLSL and doesn't crash that often...
And for some reason I like Rendermonkey to archive the stuff.
Title: Re: Raymarching Beginners' Thread
Post by: benny! on May 25, 2011
Hey las,

screeny looks very interesting! Looking forward to see "something" soon ;-)

Best,
benny!
Title: Re: Raymarching Beginners' Thread
Post by: Shockwave on May 25, 2011
Lovely choice of colours in that screenshot Las.  I wonder what it looks like in motion :)
Title: Re: Raymarching Beginners' Thread
Post by: las on May 28, 2011
Thanks :)
Seems I killed the conversation here.

Just go ahead and play around with the stuff, keep posting screenshots and asking questions!
Title: Re: Raymarching Beginners' Thread
Post by: Hotshot on May 28, 2011
The picture of it look great :)
Title: Re: Raymarching Beginners' Thread
Post by: rain_storm on July 05, 2011
I came across this link, its got some awesome algebraic raytracing worthy of a read:
http://chuyeshov.com/ray.html
Title: Re: Raymarching Beginners' Thread
Post by: efecto on August 24, 2011
Finally got a bit of a raymarcher working.
(yeah, finally back looking at an ide  :) )

Have a problem with iq's box function thou.
Anyone know the HLSL alternative for maxcomp.
HLSL doesn't seem to know that, neither seems google :(

Title: Re: Raymarching Beginners' Thread
Post by: hellfire on August 25, 2011
maxcomp( v ) returns the largest component of the given vector v.
For example:
Code: [Select]
vec3 v( 3.0, 5.0, 1.0 );
float m= maxcomp(v);
results in m= 5.0.
Title: Re: Raymarching Beginners' Thread
Post by: efecto on August 25, 2011
Thanks Hellfire!
K++

Title: Re: Raymarching Beginners' Thread
Post by: Raizor on April 19, 2012
A couple of new things I've come across that are quite interesting:

Sunset on the sea experiment (Raymarched sea tutorial) (http://www.postronic.org/h3/pid65.html)

Progress on Raymarching an infinite city (http://y-alice.blogspot.co.uk/search/label/ray%20marching) and here it is running in the GLSL Sandbox (http://glsl.heroku.com/e#2233.0). It's worth checking out the GLSL Sandbox gallery (http://glsl.heroku.com/) as there are some lovely examples of Raymarching various things.

This is also worth a look (http://www.mazapan.se/news/2010/07/15/gpu-ray-marching-with-distance-fields/). It's DirectX HLSL (rather than OpenGL GLSL). This is what got me going with Raymarching a while back. I converted this to GLSL at the time (I'll try and dig up the code and post the conversion).