射线球体相交:判别式是错误的
好吧,我正在使用 phong 着色开发光线追踪器。到目前为止,一切都很好。我已经投射了击中场景中球体的光线,并对它们应用了 phong 阴影,看起来很正常。
现在,我正在计算阴影光线,即从主光线到光源的交点发射光线,并查看它是否击中途中的任何物体。如果确实如此,那么它就处于阴影之中。
然而,当计算阴影光线是否击中任何球体时,我计算的判别式似乎存在错误,这很奇怪,因为到目前为止对于主光线来说它是正确的。
设置如下:
// 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
,这是查找判别式的代码:
// 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;
显然,光线指向远离球体的方向,但这里的判别式为正值 (2.88),表明光线正在撞击球体。该代码对于初级光线效果很好,因为它们的判别式必须正确,但对于这些次级阴影光线则不然。
我在这里错过了什么吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的问题的答案如此简短,以防万一有人发现这个并遇到同样的问题:
判别式告诉您行是否存在命中(而不是否存在 >ray,就像我想的那样)。如果它是积极的,那么它就检测到线路上某处被击中。
因此,在计算射线的 t 值时,请检查它们是否为负值。如果是,那么它是在射线原点后面(即射线的相反方向)的命中,因此丢弃它。仅保留正值,因为它们是沿射线方向命中的。
更短的答案:丢弃负 t 值。
感谢木片让我意识到了这一点。
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、1 或 2 个实数解。判别式的符号告诉我们有多少个真实的解决方案(并帮助我们求解这些解决方案)。
如果存在唯一的解决方案,则该线恰好与球体的表面接触。当判别式恰好为零时,就会发生这种情况。
如果存在两个解,则直线穿过球体,在两个不同的点处撞击表面。
如果不存在真正的解(判别式为负的情况),则该线距离球体太远而根本无法触及它。
在发现这条线是否靠近球体之后,我们才担心光线是否会击中它。为此,我们可以看看如何定义射线。射线是一条半线,仅在一个方向上无限延伸。因此,我们查看直线上交点发生的位置。只有当相交发生在我们关心的线的一半上时,才会存在射线球相交。
要点是,判别式的计算(并简单地测试其符号)仅告诉您该线的作用,而不是该线沿线交叉点的位置。
当然,仔细阅读您自己提供的链接就会告诉您所有这些。
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.
很确定“oc”应该是“co”
您正在向错误的方向发射光线并在球体的另一侧找到交点。
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.