2016-11-14 65 views
2

编辑:我发现所有像素都颠倒了,因为屏幕和世界坐标之间的差异,所以这不再是一个问题。
编辑:在@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,黄色三角形为-170度,蓝色三角形为-707,所以我不确定正常是否是错误的方向。无论如何,当我添加确信光与法线之间的角度为正(Math.abs(directionToLight.dotProduct(normal));),就引起了相反的问题:
Absolute value of dot products

我怀疑,这将是一个小的错字/错误,但我需要另一一双眼睛发现我不能。

注:我的三角形顶点具有(a,b,c),和(u,v)分别使用a-bc-b计算出的边缘(也,那些用于计算平面/三角形正常)。 A 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高,但我的问题在这里试图解决的问题是固定的。

+1

试着在'if(分母ε)'中取绝对值。这些症状看起来像是一个典型的面前和背面多边形问题。请记住,即使“大”,点商品可能很容易出现负面现象,负数肯定小于您的小数点。 –

+0

@TheVee帮助图像看起来更好,但只有阴影。我编辑了这个问题以包含您的建议。任何其他想法? –

+1

嗯,你得到的颜色错误,但没有你在这里公开的代码提到颜色计算。这将是一样的,试图在某个地方得到负面的黄色阴影。 –

回答

1

这是包含平面物体的场景的光线追踪中的一个常见问题,我们从错误的一面击中它们。包含点积的公式表现为内在的假设,即光线从面向外部的法线指向的方向入射到对象上。 这只适用于你的三角形的一半可能的方向,并且你运气不好以使其正常背离光线。

从技术上讲,在物理世界中,你的三角形不会有零音量。它由一层薄薄的材料组成。在任何一方,它都有一个适当的正常指向外部。指定一个单一的法线是一种公平的简化,因为两者在符号上只有不同。

但是,如果我们做了简化,我们需要考虑它。从技术上讲,在我们的公式中,面向内部的法线产生负面的点积,这种情况并不适用。这就像光从物体内部传来,或者它碰到一个表面不可能是它的方式。这就是为什么他们会给出错误的结果。负值将从其他来源中减去光线,并根据其大小和实施情况可能导致变暗,全黑或数字下溢。

但是因为我们知道正确的正常值或者是我们正在使用的正负值,所以我们可以通过采取一个预防性绝对值来立即修复这些情况,其中肯定的点积是隐式地假设的(在您的代码中, angleBetweenLightAndNormal)。一些类似OpenGL的图书馆可以为您提供帮助,并且可以根据需要使用附加信息(符号)在two different materials(正面和背面)之间进行选择。或者,它们可以被设置为根本不绘制固体物体的背面,因为它们将被固体物体的正面透明化(称为face culling),节省了大约一半的数字作品。