2012-11-08 25 views
12

は、私は次のような結果を得ます私がしてはいけない鏡面を参照してください(2番目の画像)。 1つのspehereライトは頂点シェーダで、もう1つはフラグメントで行われます。ここでGLSLの鏡面反射照明

は私の頂点ライトシェーダがどのように見えるかです: 頂点:

// Material data. 
uniform vec3 uAmbient; 
uniform vec3 uDiffuse; 
uniform vec3 uSpecular; 
uniform float uSpecIntensity; 
uniform float uTransparency; 

uniform mat4 uWVP; 
uniform mat3 uN; 
uniform vec3 uSunPos; 
uniform vec3 uEyePos; 
attribute vec4 attrPos; 
attribute vec3 attrNorm; 
varying vec4 varColor; 

void main(void) 
{ 
    vec3 N = uN * attrNorm; 
    vec3 L = normalize(uSunPos); 
    vec3 H = normalize(L + uEyePos); 
    float df = max(0.0, dot(N, L)); 
    float sf = max(0.0, dot(N, H)); 
    sf = pow(sf, uSpecIntensity); 

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf; 
    varColor = vec4(col, uTransparency); 
    gl_Position = uWVP * attrPos; 
} 

フラグメント:

varying vec4 varColor; 

void main(void) 
{ 

    //vec4 col = texture2D(texture_0, varTexCoords); 
    //col.r += uLightDir.x; 
    //col.rgb = vec3(pow(gl_FragCoord.z, 64)); 
    gl_FragColor = varColor; 

} 

これは、コードからの私の供給されたデータが間違っている、可能です。uNは世界の行列です(逆行列ではなく、転置されていません。 UWVP - ワールドビュー投影行列。

問題がどこにあるのかについては、何か考えていただければ幸いです。

[EDIT]ここに私の光の計算は、フラグメントで行われます 頂点シェーダファイル:

uniform mat4 uWVP; 
uniform mat3 uN; 
attribute vec4 attrPos; 
attribute vec3 attrNorm; 
varying vec3 varEyeNormal; 

void main(void) 
{ 
    varEyeNormal = uN * attrNorm; 
    gl_Position = uWVP * attrPos; 
} 

フラグメントシェーダファイル:

// Material data. 
uniform vec3 uAmbient; 
uniform vec3 uDiffuse; 
uniform vec3 uSpecular; 
uniform float uSpecIntensity; 
uniform float uTransparency; 

uniform vec3 uSunPos; 
uniform vec3 uEyePos; 
varying vec3 varEyeNormal; 

void main(void) 
{ 
    vec3 N = varEyeNormal; 
    vec3 L = normalize(uSunPos); 
    vec3 H = normalize(L + uEyePos); 

    float df = max(0.0, dot(N, L)); 
    float sf = max(0.0, dot(N, H)); 
    sf = pow(sf, uSpecIntensity); 

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf; 

    gl_FragColor = vec4(col, uTransparency); 
} 

[EDIT2]ヨアキムが指摘したように、私は「wasnフラグメントシェーダでvarEyeNormalを正規化します。それを修正した後、結果はフラグメントシェーダではるかに優れています。私はuEyePosでnormalize関数も使用していましたので、specularはもはや暗い面にはなりません。すべての助けに感謝します。

enter image description here

+0

私はあなたがあなたの法線を否定すべきであると考えています。(暗い側の明るい点) –

+0

このように:vec3 negNormal = vec3(-attrNorm.x、-attrNorm.y、-attrNorm.z); vec3 N = uN * negNormal; ?これで私は鏡面を全く見ません。 – SMart

+0

私は、鏡面反射が陽性であれば、拡散光が正でなければならない第2の画像について話していました。あなたはこれからjsfiddleを作ることができますか? –

答えて

19

短い答え:あなたは代わりの頂点シェーダでは、フラグメントシェーダでvarEyeNormalを正規化する必要があります。

長い答え: スムーズな照明を得るには、頂点ごとではなくピクセルごとに法線を計算する必要があります。頂点シェーダで計算された変化は、断片シェーダに渡される前に線形補間されますが、場合によってはショートカットとしては機能しますが、他の場合は悪化します。

三角形のエッジが表示されている理由は、法線間の補間により、頂点間のすべてのピクセルで1.0未満の法線が生じるためです。

これを修正するには、頂点シェーダではなく、フラグメントシェーダで法線を正規化する必要があります。

正規行列は、モデルビューのみ回転および翻訳が含まれている場合、モデルビューマトリクスの3×3の上部に相当するモデルビュー行列の逆行列の転置の上部の3x3、(スケーリングなし)

なければならない

通常の行列についての詳細は、以下を参照してください。http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

(下記のコメントに従って正しさのために編集。)

+5

正常な行列についての点は間違っています。これは、モデルビュー行列の上位3x3の逆数**および**転置である。モデルビュー行列に回転と平行移動のみがある場合、それはモデルビュー行列の上部3x3とまったく同じです(反転と転置が回転のためにキャンセルされ、翻訳がとにかく取り込まれるためです)。これはおそらく、 OPがそれを反転させるかどうかの違いを作らない。 –

+2

あなたは正しいです、私は私の答えを編集しました –