Raymarching Beginners' Thread
category: code [glöplog]
That's a good question, actually. maybe because we're afraid to break the "sphere" assertion and pass through objects? but maybe it works. /me goes to test. :)
psonice, you're totally right about this, after testing, it works also. There is no noticable artifacts. It's hard to say if there is any performance improvement from this though. First of all it's hard to see on nvidia hardware with fraps, because there is some kind of vertical sync that adjusts to the framerate immediatelly to a below threshold - 10, 15, 20, 25, 30, 45 and 60 fps. So the difference in framerate between the nearest and linear filtering are probably ~10% and scene dependant..
But the point is that it doesn't provocate any *visible* artifacts, indeed.
But the point is that it doesn't provocate any *visible* artifacts, indeed.
Good, because the point about linear filtering isn't so much the speed, it's that we don't have any choice if we do this in the vertex shader so we'd be fucked if it caused a problem :D
keep in mind that i tried for blocks of 4*4 pixels though ;)
What about doing the raytracing also in the VS? At least if you know that you bounding things stay bigger than a grid thing?
And yeah, your cones are overlapping then... maybe some kind of hexagonal grid would give a better "cone packing" than a simple straight triangle grid!
And yeah, your cones are overlapping then... maybe some kind of hexagonal grid would give a better "cone packing" than a simple straight triangle grid!
Something like this should be a good idea
(and yes i know it's a triangular grid, but this should give the best "overlap/hit" ratio)
psonice: The way we made FD tunnels back in the days. It's exactly what you proposed: Raytracing at some fixed grid, storing uvs/surface properties for the intersections. Then you "expand" the grid into a bitmap by interpolating uvs etc over a rectangle. An adaptive subdivided version of was used for the "real-time raytracing"-demos (heaven7, fresnel etc).
I generated a triangle strip in meander pattern style using some degenerate triangles at the end of each line... The code is very tiny. So let's see whether this was a good idea or not later :)
Your projected cone radius (into the image plane) should be r >= (a/3)*sqrt(3) - where a is the length of one triangle edge.
I am not 100% sure... but I guess you will need way more overlapping to make it work correctly with linear interpolation.
And I don't think linear interpolation is the best approach.
I think using a coverage like this should ensure the whole thing to get the distances properly (even with linear interpolation):
And what you actually want to have is not an interpolation but an min of all intersecting cones per triangle. If you have that - the minimal overlapping is enough (Geometry shaders?).
And I don't think linear interpolation is the best approach.
I think using a coverage like this should ensure the whole thing to get the distances properly (even with linear interpolation):
And what you actually want to have is not an interpolation but an min of all intersecting cones per triangle. If you have that - the minimal overlapping is enough (Geometry shaders?).
kusma: ok, but what's an FD tunnel? Free-directional? I get what you mean though. Anyway, what's wrong with finding new ways to use old tricks? If it speed it up in a simple way, it's a win :)
las: why not use a simple method? There will be cases where the interpolation intersects an object, but you can easily add a 'step back' value. You can fine-tune that and the grid size for each scene, for best speed/accuracy.
And yeah, this would be ideal for a raytrace bounding box stage. It'd be very quick to do, and take a whole section out of the fragment shader. Triangular grids are definitely the way too :)
Additional thought: if you do this, and a vertex hits a plane (maybe it'd work for other objects too?) you could mark that in a separate varying. Just a simple 0 for a plane, 1 for anything else.
In the fragment shader, you can check the value of that varying, and if it's 0 it means the pixel lies on the plane because the nearest vertices hit nothing else. You don't need to march/trace at all, just get the normal and light it. For some scenes you could optimise out whole areas of the screen.
las: why not use a simple method? There will be cases where the interpolation intersects an object, but you can easily add a 'step back' value. You can fine-tune that and the grid size for each scene, for best speed/accuracy.
And yeah, this would be ideal for a raytrace bounding box stage. It'd be very quick to do, and take a whole section out of the fragment shader. Triangular grids are definitely the way too :)
Additional thought: if you do this, and a vertex hits a plane (maybe it'd work for other objects too?) you could mark that in a separate varying. Just a simple 0 for a plane, 1 for anything else.
In the fragment shader, you can check the value of that varying, and if it's 0 it means the pixel lies on the plane because the nearest vertices hit nothing else. You don't need to march/trace at all, just get the normal and light it. For some scenes you could optimise out whole areas of the screen.
Grain of salt: This is just for the first hit and you might miss objects that are small.
It might be good to render all object bounding boxes/spheres/... to the screen, then read from z in the raymarching shader and start tracing there if that'd work.
It might be good to render all object bounding boxes/spheres/... to the screen, then read from z in the raymarching shader and start tracing there if that'd work.
yep, you'd have to tweak it for each scene, and tiny objects would screw it up in some cases. For some scenes though, it might be worthwhile. Same with everything for raymarching really, you have to mix it up plenty to get best speed/quality.
psonice: Because we can do it an a "perfect" way, without missing any object. I'm thinking about doing that without raytracing btw., just low granularity raymarching - I guess the whole thing is very similar too the method texel proposed some time ago.
It will probably break the second you do stuff that makes raymarching cool, e.g. add a sine or random values to a cube or whatnot...
psonice: i wish i could convince you to take up the self-imposed rule that governs me when blogging and similar: only discuss/propose things that you have actually tried out, where you have a good understanding of the limitations and benefits in a real-world case.
because i fucking hate conjecture. :)
because i fucking hate conjecture. :)
I love a bit of conjecture :) (But I'm not discussing the stuff I'm actually working on ;)
The biggest problem with your grid, las, is that it only works for primary rays.
graga: you could use it for reflections/shadows/etc. too, but only in very limited cases (where you know the end point can be interpolated to the next point in the grid without it looking like shit). But the point is to accelerate the primary ray, so it starts close to the surface
Maybe I don't have any secondary rays... ;) Or I am doing something completely different there.
What about generating bounding boxes in a Geometry Shader?
no secondary rays? :O But, no reflections, shadows, SSS, AO, etc! Pure clouds? :D
no conjectures on my side, i've used that in our revision 4k intro... :p
las: i was thinking of something similar to improve indeed! which filtering would you use on an hexagonal grid though? averaging 3 axis linear filters?.. or :)
in general though, you don't really want to minimize the radius of the cone, this is indeed the minimal layout, but conjectures aside, it runs faster the larger cone you wish to raymarch -the epsilon is proportional to t and bigger in this case so your loop exits earlier-. You're losing details though if you do so, but it's acceptable within margins.
las: i was thinking of something similar to improve indeed! which filtering would you use on an hexagonal grid though? averaging 3 axis linear filters?.. or :)
in general though, you don't really want to minimize the radius of the cone, this is indeed the minimal layout, but conjectures aside, it runs faster the larger cone you wish to raymarch -the epsilon is proportional to t and bigger in this case so your loop exits earlier-. You're losing details though if you do so, but it's acceptable within margins.
With newer GLSL you can select "flat" instead of "smooth" (barycentric interpolation) - that flat stuff should do something like nearest neighbour interpolation on the varyings.
Anyone going to try adaptive refinement with geometry shaders? ;)
I just gave psonices simple "first trace bounding stuff" a try, gives my 50% speedup at least and costs close to nothing. Currently the most expensive thing I do is a 3d noise texture lookup - and that's frakkin slow. Playing around with other stuff... :) But I'll need something to speed the stuff up - definitely.
Anyone going to try adaptive refinement with geometry shaders? ;)
I just gave psonices simple "first trace bounding stuff" a try, gives my 50% speedup at least and costs close to nothing. Currently the most expensive thing I do is a 3d noise texture lookup - and that's frakkin slow. Playing around with other stuff... :) But I'll need something to speed the stuff up - definitely.