2016-11-14 115 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),節省了大約一半的數字作品。