Raytraced Shadows Problem - raytracing

I've got a problem with shadowrays in my raytracer.
Please have a look at the following two pictures
3D sMax:
alt text http://neo.cycovery.com/shadow_problem.gif
My Raytracer:
alt text http://neo.cycovery.com/shadow_problem2.jpg
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!

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!

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.

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.

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.

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?

I had the same issue and in my case an if statement where if the dot prod of the light direction and the normal is positive, did the trick.
the pseudocode is:
bool shadow_hit(light, shader_ctx){
....
if(dot(light.dir, shader_ctx.normal) > 0) return false
...
return true;
}

Related

Looking for some pointers for voxelisation strategies

To voxelise a mesh basically means to be able to determine for a point(x,y,z) if it is either inside or outside a mesh.
A mesh here is just a raw set of triangles. Being outside the mesh means that there is a ray from the point (with any direction) that does not intersect the mesh from any viewpoint.
For a well behaved, closed, non intersecting mesh, that is easy: Trace a ray in any direction, if the number of intersections is odd, the point is inside.
But for a "bad" mesh, composed of open parts this is terrible. For example the mesh could be two cubes connected by an open cylinder that sticks into both of them.
ZBuffer rendering solves this fine for one viewpoint. But the issue is for any viewpoint. To me the problem is well defined, but not obvious to solve.
I am looking for some pointers on how to approach this problem. There must be tons of research for it. Any links to papers? Or am I missing something in how to think about the problem?
It's possible if all of the surfaces on your meshes have a "sidedness" to them, i.e. they have a front side and a back side.
Then to determine if a point is inside the mesh you can trace a ray from the point in any direction, and keep a count of intersections like this:
if the ray goes through the back side and out the front side (i.e. emerging from the inside to the outside), then add one.
if the ray goes through the front side and out the back side, (i.e. entering the inside from the outside), then subtract one.
if the mesh surface is double sided, do not add or subtract anything.
If the final count is positive, or if the point lies exactly on any surface, then the point is inside the mesh.
You need to add the restriction that it's never possible to see an exposed back side of a surface from outside the mesh. This is equivalent to saying that the mesh should always render correctly from all exterior viewpoints with back-face culling turned on.
For the example with the cube and open cylinder, for the cube to be solid, its surfaces should be single sided (making them double-sided would mean defining a hollow cube with infinitely thin walls).
The mesh surface of the cylinder would also have to be single-sided, or else it also would have infinitely thin walls, and points inside the cylinder (that aren't inside the cubes) would not be inside the mesh. As long as the ends of the cylinder are stuck inside the cube, the restriction is not broken since you can never see an exposed back side of a face.
If one of the cubes is removed, then the restriction is not met and this algorithm will fail.

three.js - Overlapping layers flickering

When several objects overlap on the same plane, they start to flicker. How do I tell the renderer to put one of the objects in front?
I tried to use .renderDepth, but it only works partly -
see example here: http://liveweave.com/ahTdFQ
Both boxes have the same size and it works as intended. I can change which of the boxes is visible by setting .renderDepth. But if one of the boxes is a bit smaller (say 40,50,50) the contacting layers are flickering and the render depth doesn't work anymore.
How to fix that issue?
When .renderDepth() doesn't work, you have to set the depths yourself.
Moving whole meshes around is indeed not really efficient.
What you are looking for are offsets bound to materials:
material.polygonOffset = true;
material.polygonOffsetFactor = -0.1;
should solve your issue. See update here: http://liveweave.com/syC0L4
Use negative factors to display and positive factors to hide.
Try for starters to reduce the far range on your camera. Try with 1000. Generally speaking, you shouldn't be having overlapping faces in your 3d scene, unless they are treated in a VERY specific way (look up the term 'decal textures'/'decals'). So basically, you have to create depth offsets, and perhaps even pre sort the objects when doing this, which all requires pretty low-level tinkering.
If the far range reduction helps, then you're experiencing a lack of precision (depending on the device). Also look up 'z fighting'
UPDATE
Don't overlap planes.
How do I tell the renderer to put one of the objects in front?
You put one object in front of the other :)
For example if you have a camera at 0,0,0 looking at an object at 0,0,10, if you want another object to be behind the first object put it at 0,0,11 it should work.
UPDATE2
What is z-buffering:
http://en.wikipedia.org/wiki/Z-buffering
http://msdn.microsoft.com/en-us/library/bb976071.aspx
Take note of "floating point in range of 0.0 - 1.0".
What is z-fighting:
http://en.wikipedia.org/wiki/Z-fighting
...have similar values in the z-buffer. It is particularly prevalent with
coplanar polygons, where two faces occupy essentially the same space,
with neither in front. Affected pixels are rendered with fragments
from one polygon or the other arbitrarily, in a manner determined by
the precision of the z-buffer.
"The renderer cannot reposition anything."
I think that this is completely untrue. The renderer can reposition everything, and probably does if it's not shadertoy, or some video filter or something. Every time you move your camera the renderer repositions everything (the camera is actually the only thing that DOES NOT MOVE).
It seems that you are missing some crucial concepts here, i'd start with this:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
About the depth offset mentioned:
How this would work, say you want to draw a decal on a surface. You can 'draw' another mesh on this surface - by say, projecting a quad onto it. You want to draw a bullet hole over a concrete wall and end up with two coplanar surfaces - the wall, the bullet hole. You can figure out the depth buffer precision, find the smallest value, and then move the bullet hole mesh by that value towards the camera. The object does not get scaled (you're doing this in NDC which you can visualize as a cube and moving planes back and forth in the smallest possible increment), but does translate in depth direction, ending up in front of the other.
I don't see any flicker. The cube movement in 3D seems to be super-smooth. Can you try in a different computer (may be faster one)? I used Chrome on Macbook Pro.

Shadow Mapping - artifacts on thin wall orthogonal to light

I'm having an issue with back faces (to the light) and shadow mapping that I can't seem to get past. I'm still at the relatively early stages of optimizing my engine, however I can't seem to get there as even with everything hand-tuned for this one piece of geometry it still looks like garbage.
What it is is a skinny wall that is "curved" via about 5 different chunks of wall. When I create my depth map I'm culling front faces (to the light). This definitely helps, but the front faces on the other side of the wall are what seem to be causing the z-fighting/projective shadowing.
Some notes on the screenshot:
Front faces are culled when the depth texture (from the light) is being drawn
I have the near and far planes tuned just for this chunk of geometry (set at 20 and 25 respectively)
One directional light source, coming down on a slight angle toward the right side of the scene, enough to indicate that wall should be shadowed, but mostly straight down
Using a ludicrously large 4096x4096 shadow map texture
All lighting is disabled, but know that I am doing soft lighting (and hence vertex normals for the vertices) even on this wall
As mentioned here it concludes you should not shadow polygons that are back faced from the light. I'm struggling with this particular issue because I don't want to pass the face normals all the way through to the fragment shader to rule out the true back faces to the light there - however if anyone feels this is the best/only solution for this geometry thats what I'll have to do. Considering how the pipeline doesn't make it easy/obvious to pass the face normals through it makes me feel like this isn't the path of least resistance. And note that the normals I am passing are the vertex normals, to allow for softer lighting effects around the edges (will likely include both non-shadowed and shadowed surfaces).
Note that I am having some nasty Perspective Aliasing, but I'm hoping my next steps are to work on cascaded shadow maps, but without fixing this I feel like I'm just delaying the inevitable as I've hand-tightened the view as best I can (or so I think).
Anyways I feel like I'm missing something, so if you have any thoughts or help at all would be most appreciated!
EDIT
To be clear, the wall technically should NOT be in shadow, based on where the light is coming from.
Below is an image with shadowing turned off. This is just using the vertex normals to calculate diffuse lighting - its not pretty (too much geometry is visible) but it does show that some of the edges are somewhat visible.
So yes, the wall SHOULD be in shadow, but I'm hoping I can get the smoothing working better so the edges can have some diffuse lighting. If I need to have it completely in shadow, then if its the shadow map that puts it in shadow, or my code specifically putting it in shadow because the face normal is away, I'm fine with that - but passing the face normal through to my vertex/fragment shader does not seem like the path of least resistance.
Perhaps these will help illustrate my problem better, or perhaps bring to light some fundamental understanding I am missing.
EDIT #2
I've included the depth texture below. You can see the wall in question in the bottom left, and from the screenshot you can see how i've trimmed the depth values to ~0.4->1. This means the depth values of that wall start in the 0.4 range. So its not PERFECTLY clipped for it, but its close. Does that seem reasonable? I'm pretty sure its a full 24 or 32 bit depth buffer, a la DEPTH_COMPONENT extension on iOS. For #starmole, does this help to determine if its a scaling error in my projection? Do you think the size/area covered of my map is too large, hence if it focuses closer it might help?
The problem seems to be that you are
Culling the front faces
Looking at the back face
Not removing the light from the back face because it's actually not lit by the normal - or there is some inaccuracy in the computation
Probably not adding some epsilon
(1) and (2) mean that there will be Z-fighting between the shadow map and the back faces.
Also, the shadow map resolution is not going to help you - just look at the wall in the shadow map, it's one pixel thick.
Recommendations:
Epsilons. Make sure that Z > lightZ + epsilon
Epsilons. Make sure that the wall is facing the light (dot of normal > epsilon) to make sure the wall is shadowed if it's very nearly orthogonal

Orthographic 3D Backface Culling using Surface Normals

I'm creating an HTML5 canvas 3D renderer, and I'd say I've gotten pretty far without the help of SO, but I've run into a showstopper of sorts. I'm trying to implement backface culling on a cube with the help of some normals calculations. Also, I've tagged this as WebGL, as this is a general enough question that it could apply to both my use case and a 3D-accelerated one.
At any rate, as I'm rotating the cube, I've found that the wrong faces are being hidden. Example:
I'm using the following vertices:
https://developer.mozilla.org/en/WebGL/Creating_3D_objects_using_WebGL#Define_the_positions_of_the_cube%27s_vertices
The general procedure I'm using is:
Create a transformation matrix by which to transform the cube's vertices
For each face, and for each point on each face, I convert these to vec3s, andn multiply them by the matrix made in step 1.
I then get the surface normal of the face using Newell's method, then get a dot-product from that normal and some made-up vec3, e.g., [-1, 1, 1], since I couldn't think of a good value to put in here. I've seen some folks use the position of the camera for this, but...
Skipping the usual step of using a camera matrix, I pull the x and y values from the resulting vectors to send to my line and face renderers, but only if they have a dot-product above 0. I realize it's rather arbitrary which ones I pull, really.
I'm wondering two things; if my procedure in step 3 is correct (it most likely isn't), and if the order of the points I'm drawing on the faces is incorrect (very likely). If the latter is true, I'm not quite sure how to visualize the problem. I've seen people say that normals aren't pertinent, that it's the direction the line is being drawn, but... It's hard for me to wrap my head around that, or if that's the source of my problem.
It probably doesn't matter, but the matrix library I'm using is gl-matrix:
https://github.com/toji/gl-matrix
Also, the particular file in my open source codebase I'm using is here:
http://code.google.com/p/nanoblok/source/browse/nb11/app/render.js
Thanks in advance!
I haven't reviewed your entire system, but the “made-up vec3” should not be arbitrary; it should be the “out of the screen” vector, which (since your projection is ⟨x, y, z⟩ → ⟨x, y⟩) is either ⟨0, 0, -1⟩ or ⟨0, 0, 1⟩ depending on your coordinate system's handedness and screen axes. You don't have an explicit "camera matrix" (that is usually called a view matrix), but your camera (view and projection) is implicitly defined by your step 4 projection!
However, note that this approach will only work for orthographic projections, not perspective ones (consider a face on the left side of the screen, facing rightward and parallel to the view direction; the dot product would be 0 but it should be visible). The usual approach, used in actual 3D hardware, is to first do all of the transformation (including projection), then check whether the resulting 2D triangle is counterclockwise or clockwise wound, and keep or discard based on that condition.

Box backface culling

Assume I have a camera defined by its position and direction, and a box defined by its center and extents (three orthogonal vectors from the box center to face centers). Face is visible when its outer surface is facing the camera and invisible when its inner surface is facing it.
It seems obvious that depending on box position and orientation there may be 1-3 faces of the box visible. Is there some clever way how to determine which faces are visible? An obvious solution would be to compute 6 dot-products of the face normal against the face-camera vector for each face. Is there a better way?
Note: perspective projection will be used, but I do not think it matters, the property of "facing camera" seems independent to a projecting.
I believe the method you described is the normal way to do this. It's a very fast calculation so you shouldn't be worried too much about speed. This is the same method they use to reduce the number of calculations for ray-triangle intersection algorithms. If the front of the face isn't visible, the method doesn't continue calculations for that face. See this paper for a c++ implementation of this algorithm. It's in the first half of the calculations. http://jgt.akpeters.com/papers/MollerTrumbore97/code.html
The only cleverness is that if a face of the cube is visible, the opposing face definitely isn't. At least in a regular perspective projection.
Note that the opposite might not be true: if a face is invisible, the opposing face might be invisible too. This is because the type of projection does matter. Imagine the cube being really up close to the camera, which is looking straight at one face. Then rotate the cube slightly, and while with a parallel projection, another face would immediately become visible, in a perspective projection this doesn't happen.

Resources