2011-01-07 6 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; 
    } 
} 

今私は、私は、ハーンとパン屋からの数式を使用し擬似コードに続き、いくつかの言語でWikipediaの記事によると、それを複数回実施しようとしたが、それは働いたことはないBlinn-Phong illumination model

になるためにそれを適応させる必要があります。 私は正反射をまったく取得していないか、弱すぎる、および/または間違った場所にいる、および/または色が間違っています。

多くの間違った実装から、すでに間違っているような小さなコードを投稿します。 (正しい強度でmabyませんが、基本的にはそれが正しいはずです)、それはすでに動作するはずtheese少し変更して

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

: は、だから私はそうのように私の半分ベクトルと私の新しい正反射光を計算します。しかし結果は間違っています。

ここに2つの画像があります。それがどのようにレンダリングされるのかを正確かつ適切にレンダリングする方法を残しました。

right wrong

私は光沢率を下げる場合は、右上に小さな正反射光を見ることができます:私はフォン照明の概念を理解し、また、簡略化され、よりパフォーマンスの高い適応におけるAltough lower shininess

blinn phongの私は数日間試していて、ちょうどそれを働かせることができません。どんな助けも訴えられる。残念ながら

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

編集:

私は私が|L+V|によってmutiplyingの代わりに、私はそうdevidingに変更H.を計算するときに、それで割るだと、this answerによってエラーを認識してなされましたこれはあまり変わらない。結果は次のようになります。

div

と私は鏡面定数を上昇し、輝きを下げる場合は、smilar間違った方法で、より明確な効果を見ることができます:

div2

しかし、この正規化だけの除算。

私は一歩足りません。これのような公式はちょうど私に意味をなさないので。

あなたはこの絵を見れば:http://en.wikipedia.org/wiki/File:Blinn-Phong_vectors.svg

NにHの投影がRにVよりもはるかに少ないですし、絵にベクトルVを変更する想像した場合とき視線ベクトルの角度が同じです左端にある。右に行くとますます違うようになります。

私は堂々と2つの投影を掛け合わせて、似たようなものになります(そして、穴のポイントはRの計算を避けることです)。私は何も試しても何も読んでいませんでした。私はこれを試してみようとしています。

結果:鏡面光の強さはあまりにも大きく(白い部分)、位置はまだ間違っています。

私は、反射がちょうど間違った場所にあるので、何か他のものを台無しにしていると思います。しかし何?

編集:N/Hの角度は実際にはおよそ半分またはV/Rであるというメモで、ウィキペディアを読みました。それを補うために、射影ではなく私のshineness指数を4倍にする必要があります。もし私がそうするなら、私は目に見える鏡面光で終わります。 (xVec3.mul(v,x)乗算vを想定)H = (L+V)*|L+V|Hを計算するとき

答えて

5

それを実感してください!

私はをネゲートビューベクトルにする必要がありました。

+0

私は2つの3Dプロジェクトを完了し、これを両方の時間にねじ込みました。 +1 –

3

あなたはのように、その規範によってL+Vを乗算しているようです。代わりに、標準で除算する必要があります。H = (L+V)/|L+V|

+0

ありがとうございました。残念ながら、これはあまり変わっていません...私の編集された答えを見ることができますか? –

関連する問題