1
votes

Alright, so I'm working on a ray tracer using phong shading. So far, everything is good. I've cast rays that have hit the spheres in my scene, applied phong shading to them, and it looks normal.

Now, I'm calculating shadow rays, which is shooting a ray from the point of intersection from the primary ray to the light source, and seeing if it hits any objects on the way. If it does, then it's in a shadow.

However, when computing whether the shadow ray hits any spheres, there seems to be an error with my discriminant that is calculated, which is odd since it's been correct so far for primary rays.

Here's the setup:

// Origin of ray (x,y,z)
origin: -1.9865333, 1.0925934, -9.8653316
// Direction of ray (x,y,z), already normalized
ray: -0.99069530, -0.13507602, -0.016648887

// Center of sphere (x,y,z)
cCenter: 1.0, 1.0, -10.0
// Radius of the sphere (x,y,z)
cRadius: 1.0

, and here's the code for finding the discriminant:

// A = d DOT d
float a = dotProd(ray, ray);

// B = 2 * (o - c) DOT d
Point temp (2.0*(origin.getX() - cCenter.getX()), 2.0*(origin.getY() - cCenter.getY()), 2.0*(origin.getZ() - cCenter.getZ()));
float b = dotProd(temp, ray);

// C = (o - c) DOT (o - c) - r^2
temp.setAll(origin.getX() - cCenter.getX(), origin.getY() - cCenter.getY(), origin.getZ() - cCenter.getZ());
float c = dotProd(temp, temp);
c -= (cRadius * cRadius);

// Find the discriminant (B^2 - 4AC)
float discrim = (b*b) - 4*a*c; 

Clearly, the ray is pointing away from the sphere, yet the discriminant here is positive (2.88) indicating that the ray is hitting the sphere. And this code works fine for primary rays as their discriminants must be correct, yet not for these secondary shadow rays.

Am I missing something here?

3
My guess is what you are missing is an understanding of the mathematics, and what it tells you. Would this algorithm tell you if a LINE intersects a sphere, as opposed to a ray? That is, a line has infinite extent in two directions.user85109
@woodchips A ray is a vector (a point with a direction), so it's infinite in one direction (the direction it's pointing). The formula is based on the function of a sphere. A point P lies on the sphere if it satisfies: ||P - Pc|| = r^2, where Pc is the center of the sphere, and r is the radius. For a ray, a point P is on the ray if P = Q + td, where Q is the starting point of the ray, d is the direction, and t is the "time". Here's a link incase my explanation falls short: wiki.cgsociety.org/index.php/Ray_Sphere_Intersectionuser1115016
Yes. And while you have carefully copied down definitions of a line and ray, you simply have not bothered to understand the equations that go ahead and implement that which you reference. A positive or negative discriminant does NOT mean there is a solution for the intersection of a ray. It tells you that a solution exists for the infinite LINE intersecting the sphere if the discriminant is positive!!!!!!! (Actually, non-negative is the criterion of interest.) Read that document you reference yourself, and read it thoroughly.user85109
If the line DOES intersect the sphere, one next can determine if that intersection point is in the direction along the ray that the ray actually points.user85109
@woodchips I'm flattered you think I copied down the definition. And I've read the document through, and no where does it mention "line" on the page. However, your explanation does make sense, in that it detects hits on both sides of the ray (ie. the line). Guess that gives me something to work on for now. Thanks.user1115016

3 Answers

3
votes

So short answer for my problem, in case someone finds this and has the same problem:

The discriminant tells you whether a hit exists for a line (and not for a ray, like I thought). If it's positive, then it has detected a hit somewhere on the line.

So, when calculating the t-value(s) for the ray, check to see if they're negative. If they are, then it's a hit BEHIND the point of origin of the ray (ie. the opposite direction of the ray), so discard it. Only keep the positive values, as they're hits in the direction of the ray.

Even shorter answer: discard negative t-values.

Credit goes to woodchips for making me realize this.

0
votes

The issue is, the trick to finding the intersection of a line and a sphere requires the solution of a quadratic equation. Such an equation has one of three possibilities as a solution - there are 0, 1, or 2 real solutions to that equation. The sign of the discriminant tells us how many real solutions there are (as well as helping us to solve for those solutions.)

If a unique solution exists, then the line just kisses the surface of the sphere. This happens when the discriminant is exactly zero.

If two solutions exist, then the line passes through the sphere, hitting the surface in TWO distinct points.

If no real solution exists (the case where the discriminant is negative) then the line lies too far away from the sphere to touch it at all.

Having discovered if the line ever goes near the sphere or not, only then do we worry if the ray hits it. For this, we can look at how we define the ray. A ray is a half line, extending to infinity in only one direction. So we look to see where on the line the intersection points happen. Only if the intersection happens on the half of the line that we care about is there a RAY-sphere intersection.

The point is, computation of the discriminant (and simply testing its sign) tells you ONLY about what the line does, not about where an intersection occurs along that line.

Of course, a careful reading of the link you yourself provided would have told you all of this.

-1
votes

Pretty sure "o-c" should be "c-o"

You're shooting a ray off in the wrong direction and finding the intersection on the other side of the sphere.