views:

345

answers:

5

Hey There! I've got a problem with shadowrays in my raytracer.

Please have a look at the following two pictures

3D sMax:

alt text

My Raytracer:

alt text

The scene is lit by a very bright light, shining from the back. It's so bright that there is no gradient in the shading, just either white or dark (due to the overexposure).

both images were rendered using 3DStudioMax and both use the exact same geometry, just in one case the normals are interpolated across the triangles.

Now consider the red dot on the surface. In the case of the unsmoothed version, it lies in a dark area. this means that the light source is not visible from this triangle, since it's facing away from it. In the smoothed version however, it lies in the lit area, because the interpolated normal would suggest, that the light would be visible at that point (although the actual geometry of the triangle is facing away from the lightsource).

My problem now is when raytraced shadows come in. if a shadowray is shot into the scene, from the red dot, to test whether the light-source is visible or not (to determine shadowing), the shadowray will return an intersection, independent of whether normals are interpolated or not (because intersections only depend on the geometry). Therefore the pixel would be shaded dark.

3dsamx is handling the case correctly - the rendered image was generated with Raytraced shadows turned on. However, my own Raytracer runs exactly into this problem when i turn on raytraced shadows (in my raytracer, the point is dark in both cases, because raytraced shadows determine the point lying in the shadow), and i don't know how to solve it.

I hope someone knows this problem and how to deal with it..

thanks!

+1  A: 

I'm not sure if I understood your problem correctly. It's kind of hard to get which version/result is obtained by which method and what result you consider correct.

Isn't it the case when you need to threat intersection of shadowray with the triangle on which The Red Point ;-) lies as special case. You don't do geometry intersection, as with any other triangle, but only direction check between interpolated normal and shadowray.

Or in more general sense, you say that shadowray stops at a triangle, any triangle, when: a) they intersect and b) interpolated normal of a triangle at intersection point has direction opposite to shadowray.

Tomek Szpakowicz
Hi!I consider the smoothed 3dsmax result as correct and would like to get the same.unfortunately i can't just treat the current triangle as a special case. if the current triangle is facing away from the lightsource, then the shadowray will be shot INTO my object, and since it's going in, it has to go out again, so it will hit another triangle when leaving the object
Mat
Why would you even take into account intersections with triangles from inside of the object?Anyway, I updated my answer with somewhat more general approach.Sorry. It was long time since I programmed this stuff.
Tomek Szpakowicz
If i do not take into account backfacing polygons when casting my shadow rays, then for example a flat plane could not cast shadows onto another flat plane
Mat
But with smoothed objects it's more complicated as you see...And flat plane can have some special two-sided-surface flag or can be simply made of two planes facing in opposite directions.
Tomek Szpakowicz
this sounds like a hack.. there must be some generally valid technique to handle this problem
Mat
So go and read the book on "generally valid techniques" of ray-tracing.What I told you is pointing out that there's no difference in geometry between smoothed and not smoothed object.Just different normals for each point.You have to use them somehow.Think.
Tomek Szpakowicz
Interpolating normal vectors is a hack - and this shadow problem comes about because of it. 0-thickness planes are also hackish because they don't really exist, so don't feel bad if they need an extra flag. Tomek is spot on here.
phkahler
A: 

How you can do it: If the interpolated normal at the point is facing towards the light then the surface is potentially facing the light. If facing away you are in shadow.

In the first case, the two things that would cause a shadow are other objects, and yourself if you are concave object. In the other object that is easy.

Now in the case of yourself, when you cast your ray at the light source, if you are truly 'convex inside point' you will hit yourself twice as you enter then leave the object, thus in shadow.

If you hit yourself a single time, then you must be on the edge of where the light is striking, but as we know at that point we are facing the light (via the smoothed normals) it means we are not shadowed.

Simeon Pilgrim
The above assume you are not doing backface culling of the object towards the light source. If you did then there would be no intersection. Which I think is Tomek's point.
Simeon Pilgrim
+1  A: 

The 'correct' solutions are either to tesselate triangles, or to solve the equation of the surface the triangle belongs to. I have seen only the tessellation. Tessellation gives you the controllable precision and so on...
Otherwise, you should test normal in the point (what I believe '3DStudio' does) and in the case the normal is not facing the light, just set the point as not lit. It has nothing to do with 'self-shading'. Easily this problem can be solved only with tessellation. Good luck!

avp
+1 for just tesselate to the required precision :-) I once read that Pixar tesselates down to sub-pixel triangles, which should entirely eliminate the need to interpolate the normals. It's not easy, but it's not a hack either.
phkahler
A: 

Mat, I believe your problem could be that your shadow ray hits the same triangle that it originates from because it is so close to being tangential (note that it happens right on the border of the light-shadow transition). There are two ways of solving this problem: One approach is to use a "bias" that tests the distance from the ray origin, but I think a better solution is to store a reference to the originating triangle with the ray. If you do a test against this triangle, simply ignore it.

If you happen to be using a spatial index like a BVH, then you could try stepping out of the "box" containing the triangle before doing any intersection tests, but this is less simple than before-mentioned approach and must be approached with more care.

Rehno Lindeque
A: 

It's normal to shift an intersection by a small amount in the direction of the light source when firing shadow rays.

I.e. shadowRay.dir = shadowRay.dir * 0.0001

This avoids the shadow ray intersecting the same primitive as the primary / reflective / refractive ray did.

Perhaps your problem is because you did not do this?

fluffels