Raymarching Beginners' Thread
category: code [glöplog]
Very nice already thumbed it up :)
I am not sure but I guess I found a way to do DOF in a cool and simple way by modifying chocks technique (not tested it yet).
This event might be interesting for the german speaking marchers http://metalab.at/wiki/2011-06-18_Demoscene_Outreach_II
This event might be interesting for the german speaking marchers http://metalab.at/wiki/2011-06-18_Demoscene_Outreach_II
Let's talk reflections! I thought it would be easy to do, just start a new raymarch in the direction of the normal, and there you have it. Worked like a charm.
However, my first idea was to have it recursive, and then depending on if the material was reflective or not, keep recursing until either a non-reflective material was hit, or the maximum recursion level was hit.
That didn't work though, as GLSL didn't seem to like recursion at all. So the above screenshot (can a scene be any more unimaginative than that btw.? :D) is done using the raymarch unrolled in two iterations instead, but the code isn't really pretty like that...
And what's a good way of combining the reflections btw.? At the moment I just do final_color=primary_ray_color*0.8+reflected_ray_color*0.2, and adjust the constant depending on how 'reflective' I want something to be, but it doesn't seem to look quite right for high reflectivity values.
You could do reflections in multiple passes, but it would be sort of expensive I think.
sdw: that's roughly how I did it - do the first march, then if it's reflective do a second (lower quality for speed) march. Then a 3rd march, because a reflective ball doesn't look convincing if it's not reflecting in the reflection - look at the reflection of the green ball in your red one. It gets painful at this point ;)
For the reflection colour + light, it depends how you roll it, and what kind of material you're trying to make. E.g. if it's a material that has coloured reflections, you would do "primary_colour * mix(primary_luminance, reflected_luminance, 0.2)". Or, you do something between the two. And btw, mix() is a lot easier to read, and smaller code.
Btw, you have a huge bug in your reflections. The reflected ray doesn't travel along the normal :D Look at the reflection of your green ball on the floor - it looks like a shadow, not a reflection. The ray should reflect around the normal, for this I used:
vec3 reflectedRay = ray - 2. * dot(normal, ray) * normal;
For the reflection colour + light, it depends how you roll it, and what kind of material you're trying to make. E.g. if it's a material that has coloured reflections, you would do "primary_colour * mix(primary_luminance, reflected_luminance, 0.2)". Or, you do something between the two. And btw, mix() is a lot easier to read, and smaller code.
Btw, you have a huge bug in your reflections. The reflected ray doesn't travel along the normal :D Look at the reflection of your green ball on the floor - it looks like a shadow, not a reflection. The ray should reflect around the normal, for this I used:
vec3 reflectedRay = ray - 2. * dot(normal, ray) * normal;
There is a reflect() function in GLSL, which you can use to get the reflecting vector, like this :
vec3 reflectRay = normalize(reflec(ray, normal));
vec3 reflectRay = normalize(reflec(ray, normal));
exactly, and don't forget refract :)
sdw: you can just as easily do reflections iterative as recursive.
las: refraction is much worse as it requires you to raymarch inside objects, take care of internal material changes etc.
las: refraction is much worse as it requires you to raymarch inside objects, take care of internal material changes etc.
For handling "inside/outside" the following snipped might be a good idea to get the proper refraction index.
never tested that ;)
Code:
l = f(p);
[...]
eta = pow(1.3, sign(l));
or maybe
eta = mix(1.3,1./1.3, step(0., l))
[...]
never tested that ;)
And yes, with reflections and refractions things become painful.
Ironically that's one of the biggest advantages of raytracing over rasterizing.
You have to simulate a stack for the recursive stuff and you are fine.
I implemented a simple raytracer exactly doing that a while ago, using a heap data structure to store the required data of the "recursions".
Something like left child -> refraction ray, right child -> reflection ray.
First step is to fill the structure (2 for loops), the second step is to combine the nodes to retrieve the color of each father node. After some steps you reach the root node which then has the final color of your ray (1 for loop).
http://en.wikipedia.org/wiki/Heap_(data_structure)
I'll try to adapt that concept to raymarching (basically it's just a different way to find the intersections). But raymarching does cost much more than a simple intersection test for a sphere.
I guess I have an better idea then using a heap...
I implemented a simple raytracer exactly doing that a while ago, using a heap data structure to store the required data of the "recursions".
Something like left child -> refraction ray, right child -> reflection ray.
First step is to fill the structure (2 for loops), the second step is to combine the nodes to retrieve the color of each father node. After some steps you reach the root node which then has the final color of your ray (1 for loop).
http://en.wikipedia.org/wiki/Heap_(data_structure)
I'll try to adapt that concept to raymarching (basically it's just a different way to find the intersections). But raymarching does cost much more than a simple intersection test for a sphere.
I guess I have an better idea then using a heap...
Thanks psonice, I thought there was something that looked a bit off with the reflections, but the checkerboard reflected in the balls looked OK, so I didn't think more about it - but now it is obvious.
With proper reflecting ray the result looks like this:
http://awesomescreenshot.com/043do5t48
Which looks more correct!
I love this thread btw, I think I would have grown tired long ago if I had been doing this on my own, but posting screenshots and getting feedback and help really gives a boost to motivation!
With proper reflecting ray the result looks like this:
http://awesomescreenshot.com/043do5t48
Which looks more correct!
I love this thread btw, I think I would have grown tired long ago if I had been doing this on my own, but posting screenshots and getting feedback and help really gives a boost to motivation!
question (in alil of gameplay usability relevant situation): given the balls are triangular geometry and the red ball would be behind the blue ball and completely covered. is it still possible to get a reflection of the red ball on the green one in a reasonable matter of time?
Just a year ol' sketch I did running thru a marblish corridor and tracing an enemy around a corner using a mirroring wall .
there are no triangles in these images you are seeing. secondly, the fact that the red ball is hidden to the camera is completely irrelevant to the reflection algorithm, so it works as good and fast as if the ball wasn't hidden.
this is ray-marching/tracing, it has little to do with the way FPS games are made.
this is ray-marching/tracing, it has little to do with the way FPS games are made.
...gameplay?
yeah. thx iq. I know those no triangles. DAMN. I've been her too long to know that and trying rm stuff myself atleast what's capable on my rig. -.- I was just a lil pissed the it still does nothing but some artsy mathematical stuff but doesn't really have much in it to help improve gaming visual fx without eating up the performance.
"this is ray-marching/tracing, it has little to do with the way FPS games are made."
Yet ;)
Yet ;)
Please don't go there. We've all seen what happened... ;)
TODO: raymarching shooter (named kkrieger final).
:D
that antiplanet game is impressive! They've managed to use raytracing in a way that doesn't really use any of the benefits of raytracing, and looks ugly as fuck. That's quite an achievement :D Maybe the coder managed a first basic "raytrace a sphere" experiment, then instead of learning more and improving it he decided to make a game with it?
It is ugly as fuck, but it is from 2002...