Skip to main content
GameDev.net gamedev.net
🔒 Locked

Raymarching normal calculation

Started by subi211 Aug 31, 2011 at 9:20 AM 0 replies 3.8k views
Original Post
subi211
subi211
I'm writing my first raymarcher, which at the moment is straight out of Ken Perlin's chapter in Texturing & Modeling: A Procedural Approach.

As he suggests, for lighting I'm calculating the normal at a point by using the density gradient:


vec3 compute_normal(vec3 point, float density, float epsilon)
{
return normalize(vec3(density_function(vec3(point.x - epsilon, point.y, point.z)) - density,
density_function(vec3(point.x, point.y - epsilon, point.z)) - density,
density_function(vec3(point.x, point.y, point.z - epsilon)) - density));
}


However, if the density between the intersection point and the epsilon point is the same, then the normal is 0-length. If the surface is very hard, or the shape is at a constant translucency then this happens pretty much all the time.

None of the example code I've seen online seems to have to do anything to cope with this issue, nor does the book, therefore I must be doing something dumb. Can anyone tell me what it is?
subi211
subi211
I had another good read through the chapter last night and a chat with a friend. As far as I can see, the major stupid thing I did was presume that raymarchers can cope with totally solid objects - it doesn't look like they can, there has to be a fuzzy area between empty space and solid. So that guarantees there will be a gradient to use. To guarantee that we actually hit that gradient and don't march straight from empty to solid, I need to find a point near the start of the fuzzy region, which can be done with a binary chop once density > 0. That gives us the maximum area to work with, and should mean that there is gradient in all directions as long as epsilon is sufficiently small.

If there is still a problem with not enough gradient in an arbitrary direction, then the one place we can guarantee gradient is back along the ray on the first hit. But as that would involve making two vectors at right angles to the ray, that's probably prohibitively expensive to do inside a shader.

Alternatively I could pair each density function with a normal function, but that's a bit rubbish.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.