2011-01-07 58 views
3

我做了這個非常簡單,完美的工作,執行Phong Relflection Model(沒有實現環境,但是現在不打擾我)。功能應該是自我解釋。實施Blinn-Phong陰影模型的問題

/** 
* Implements the classic Phong illumination Model using a reflected light 
* vector. 
*/ 
public class PhongIllumination implements IlluminationModel { 

    @RGBParam(r = 0, g = 0, b = 0) 
    public Vec3 ambient; 

    @RGBParam(r = 1, g = 1, b = 1) 
    public Vec3 diffuse; 

    @RGBParam(r = 1, g = 1, b = 1) 
    public Vec3 specular; 

    @FloatParam(value = 20, min = 1, max = 200.0f) 
    public float shininess; 

    /* 
    * Calculate the intensity of light reflected to the viewer . 
    * 
    * @param P = The surface position expressed in world coordinates. 
    * 
    * @param V = Normalized viewing vector from surface to eye in world 
    * coordinates. 
    * 
    * @param N = Normalized normal vector at surface point in world 
    * coordinates. 
    * 
    * @param surfaceColor = surfaceColor Color of the surface at the current 
    * position. 
    * 
    * @param lights = The active light sources in the scene. 
    * 
    * @return Reflected light intensity I. 
    */ 
    public Vec3 shade(Vec3 P, Vec3 V, Vec3 N, Vec3 surfaceColor, Light lights[]) { 
     Vec3 surfaceColordiffused = Vec3.mul(surfaceColor, diffuse); 
     Vec3 totalintensity = new Vec3(0, 0, 0); 
     for (int i = 0; i < lights.length; i++) { 
      Vec3 L = lights[i].calcDirection(P); 
      N = N.normalize(); 
      V = V.normalize(); 
      Vec3 R = Vec3.reflect(L, N); // reflection vector 
      float diffuseLight = Vec3.dot(N, L); 
      float specularLight = Vec3.dot(V, R); 
      if (diffuseLight > 0) { 
       totalintensity = Vec3.add(Vec3.mul(Vec3.mul(
         surfaceColordiffused, lights[i].calcIntensity(P)), 
         diffuseLight), totalintensity); 
       if (specularLight > 0) { 

        Vec3 Il = lights[i].calcIntensity(P); 

        Vec3 Ilincident = Vec3.mul(Il, Math.max(0.0f, Vec3 
          .dot(N, L))); 

        Vec3 intensity = Vec3.mul(Vec3.mul(specular, Ilincident), 
          (float) Math.pow(specularLight, shininess)); 

        totalintensity = Vec3.add(totalintensity, intensity); 
       } 

      } 
     } 
     return totalintensity; 
    } 
} 

現在我需要去適應它成爲一個Blinn-Phong illumination model

我使用赫恩和麪包的配方,其次pseudocodes並試圖根據幾種語言的維基百科文章多次來實現它,但它從來沒有工作。 我只是沒有得到鏡面反射,或者他們太弱和/或在錯誤的地方和/或錯誤的顏色。

從許多錯誤的實現中,我發佈了一些看起來錯誤的小代碼。 所以我計算我半路上載體和我的新的鏡面光,像這樣:

Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), Vec3.add(L.normalize(), V).length()); 
float specularLight = Vec3.dot(H, N); 

隨着theese現在應該已經工作變化不大(莫比不正確的強度,但基本上應該是正確的)。但結果是錯誤的。

這裏有兩個圖像。留下它應該如何正確呈現並正確渲染。

right wrong

如果我降低光澤因子可以在右上方看到一個小鏡面光: lower shininess

Altough我明白的Phong照明的概念,並且還簡化更高性能adaptaion blinn phong我正在嘗試幾天,只是不能得到它的工作。任何幫助appriciated。

編輯:

我意識到了錯誤的通過this answer,我感到|L+V| mutiplying而不是計算H.我改deviding當這樣被它劃分:

Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), 1/Vec3.add(L.normalize(), V).length()); 

不幸這並沒有太大的改變。結果是這樣的:

div

,如果我升到了鏡面常數,並降低反光您可以在smilar錯誤的方式更清晰地看到效果:

div2

然而,這師只是正常化。

我想我錯過了一步。因爲這樣的公式對我來說沒有意義。

如果看一下這樣的畫面:http://en.wikipedia.org/wiki/File:Blinn-Phong_vectors.svg

的H至n中的投影是遠小於V至R.如果你改變想象在圖片中的矢量V的角度是相同的,當視線矢量是「在左側」。在向右走時變得越來越不同。

我希望能夠將整個投影乘以2來成爲類似的東西(並且孔點是爲了避免計算R)。儘管我沒有讀任何回合anywehre我要試試這個...

結果:鏡面光的內涵太多(白色區域),並且位置仍然是錯誤的。

我想我在搞點別的東西,因爲反射只是在錯誤的地方。但是什麼?

編輯:現在我讀了維基百科的註釋,N/H的角度實際上是近似一半或V/R。爲了彌補這一點,我應該把我的亮度指數乘以4而不是我的預測。如果我這樣做,我最終沒有可見的鏡面光。

回答

5

想通了!

我不得不否定查看矢量。

+0

我只做過2個3D項目,並將這兩個項目搞砸了。 +1 –

3

當計算H你似乎它的規範來乘以L+V,如:H = (L+V)*|L+V|(由x假設Vec3.mul(v,x)v)。相反,你應該除以規範H = (L+V)/|L+V|

+0

謝謝。不幸的是,這並沒有太大的改變......你能看到我編輯的答案嗎? –