gpt4 book ai didi

java - 光线追踪三角形的问题(方向和着色)

转载 作者:行者123 更新时间:2023-11-30 10:36:25 26 4
gpt4 key购买 nike

编辑:我发现由于屏幕坐标和世界坐标之间的差异,所有像素都颠倒了,所以这不再是问题。
编辑:在遵循@TheVee 的建议(使用绝对值)后,我的图像变得更好了,但我仍然看到颜色问题。

我在光线追踪三角形方面遇到了一些麻烦。这是我的 previous question 的后续行动关于同一主题。这个问题的答案让我意识到我需要采取不同的方法。我采用的新方法效果更好,但我现在发现我的光线追踪器存在几个问题:

  1. 有一个三角形从不呈现颜色(它始终是黑色,即使它的颜色应该是黄色)。

这是我期待看到的:
Expected

但这是我实际上看到的:
Actual

  1. 解决第一个问题的调试,即使我删除了所有其他对象(包括蓝色三角​​形),黄色三角形始终呈现黑色,所以我不认为这是我发送的阴影光线的问题出去。我怀疑这与三角形/平面相对于相机的角度有关。

这是我的光线追踪三角形流程,它基于 this website 中的流程.

  1. 判断射线是否与平面相交。
  2. 如果是,则确定光线是否在三角形内部相交(使用参数坐标)。

下面是判断光线是否射中平面的代码:

private Vector getPlaneIntersectionVector(Ray ray)
{
double epsilon = 0.00000001;
Vector w0 = ray.getOrigin().subtract(getB());
double numerator = -(getPlaneNormal().dotProduct(w0));
double denominator = getPlaneNormal().dotProduct(ray.getDirection());
//ray is parallel to triangle plane
if (Math.abs(denominator) < epsilon)
{
//ray lies in triangle plane
if (numerator == 0)
{
return null;
}
//ray is disjoint from plane
else
{
return null;
}
}
double intersectionDistance = numerator / denominator;

//intersectionDistance < 0 means the "intersection" is behind the ray (pointing away from plane), so not a real intersection
return (intersectionDistance >= 0) ? ray.getLocationWithMagnitude(intersectionDistance) : null;
}

一旦我确定射线与平面相交,下面是确定射线是否在三角形内的代码:

private boolean isIntersectionVectorInsideTriangle(Vector planeIntersectionVector)
{
//Get edges of triangle
Vector u = getU();
Vector v = getV();

//Pre-compute unique five dot-products
double uu = u.dotProduct(u);
double uv = u.dotProduct(v);
double vv = v.dotProduct(v);
Vector w = planeIntersectionVector.subtract(getB());
double wu = w.dotProduct(u);
double wv = w.dotProduct(v);
double denominator = (uv * uv) - (uu * vv);

//get and test parametric coordinates
double s = ((uv * wv) - (vv * wu)) / denominator;
if (s < 0 || s > 1)
{
return false;
}
double t = ((uv * wu) - (uu * wv)) / denominator;
if (t < 0 || (s + t) > 1)
{
return false;
}

return true;
}

我认为我的着色有问题。我认为这与各种三角形的法线有关。这是我在为球体和三角形构建光照模型时考虑的方程式:
Lighting model

现在,这是执行此操作的代码:

public Color calculateIlluminationModel(Vector normal, boolean isInShadow, Scene scene, Ray ray, Vector intersectionPoint)
{
//c = cr * ca + cr * cl * max(0, n \dot l)) + cl * cp * max(0, e \dot r)^p
Vector lightSourceColor = getColorVector(scene.getLightColor()); //cl
Vector diffuseReflectanceColor = getColorVector(getMaterialColor()); //cr
Vector ambientColor = getColorVector(scene.getAmbientLightColor()); //ca
Vector specularHighlightColor = getColorVector(getSpecularHighlight()); //cp
Vector directionToLight = scene.getDirectionToLight().normalize(); //l
double angleBetweenLightAndNormal = directionToLight.dotProduct(normal);
Vector reflectionVector = normal.multiply(2).multiply(angleBetweenLightAndNormal).subtract(directionToLight).normalize(); //r

double visibilityTerm = isInShadow ? 0 : 1;
Vector ambientTerm = diffuseReflectanceColor.multiply(ambientColor);

double lambertianComponent = Math.max(0, angleBetweenLightAndNormal);
Vector diffuseTerm = diffuseReflectanceColor.multiply(lightSourceColor).multiply(lambertianComponent).multiply(visibilityTerm);

double angleBetweenEyeAndReflection = scene.getLookFrom().dotProduct(reflectionVector);
angleBetweenEyeAndReflection = Math.max(0, angleBetweenEyeAndReflection);
double phongComponent = Math.pow(angleBetweenEyeAndReflection, getPhongConstant());
Vector phongTerm = lightSourceColor.multiply(specularHighlightColor).multiply(phongComponent).multiply(visibilityTerm);

return getVectorColor(ambientTerm.add(diffuseTerm).add(phongTerm));
}

我看到法线和光源之间的点积对于黄色三角形是 -1,对于蓝色三角形大约是 -.707,所以我不确定法线是否是错误的方式问题。无论如何,当我添加确保光线与法线之间的角度为正(Math.abs(directionToLight.dotProduct(normal));)时,它导致了相反的问题:
Absolute value of dot products

我怀疑这会是一个小错字/错误,但我需要另一双眼睛来发现我无法发现的东西。

注意:我的三角形有顶点 (a,b,c) , 和边缘 (u,v)使用 a-b 计算和 c-b分别(同样,那些用于计算平面/三角形法线)。 Vector(x,y,z) 组成点,和一个 Ray由原点 Vector 组成和归一化方向 Vector .

下面是我如何计算所有三角形的法线:

private Vector getPlaneNormal()
{
Vector v1 = getU();
Vector v2 = getV();
return v1.crossProduct(v2).normalize();
}

如果我遗漏了您认为对解决这些问题很重要的任何内容,请告诉我。

编辑: 在@TheVee 的帮助下,这就是我最后得到的: "Working" image

z 缓冲和带有三角形的 phong 高光仍然存在问题,但我在这里试图解决的问题已解决。

最佳答案

在包括平面物体在内的场景的光线追踪中,我们从错误的一侧击中它们是一个常见的问题。包含点积的公式是在一个固有假设下提出的,即光从外向法线指向的方向入射到物体上。 这可能只适用于你的三角形的一半可能的方向,你运气不好,无法将它的法向背离光线。

从技术上讲,在物理世界中,三角形的体积不会为零。它由一层很薄的 Material 组成。在任一侧,它都有指向外部的适当法线。分配单个法线是一种合理的简化,因为两者仅符号不同。

但是,如果我们进行了简化,则需要考虑到这一点。在我们的公式中,从技术上讲是向内法线会产生负点积,这种情况下它们不是为这种情况而设计的。这就像光线来自物体内部,或者光线照射到不可能挡住它的表面。这就是他们给出错误结果的原因。负值会减去其他来源的光,根据幅度和实现情况,可能会导致变暗、全黑或数值下溢。

但是因为我们知道正确的法线要么是我们正在使用的法线要么是负法线,我们可以通过采取预防性绝对值来立即修复这些情况,其中隐式假设正点积(在您的代码中,这 angleBetweenLightAndNormal)。一些像 OpenGL 这样的库会为你做这件事,并在顶部使用附加信息(符号)在 two different materials 之间进行选择。 (正面和背面)您可以根据需要提供。或者,它们可以设置为根本不绘制实体对象的背面,因为无论如何它们都会被实体对象的正面 overdraw (称为 face culling ),从而节省大约一半的数值工作。

关于java - 光线追踪三角形的问题(方向和着色),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40599780/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com