12

シェーダーを使用すると、次の結果が得られます。 ここに画像の説明を入力してください

ここに画像の説明を入力してください

1つの問題は、鏡面反射光が一種の変形であり、球の三角形が表示されることです。もう1つは、鏡面反射光が表示されるべきではない場所に表示されることです(2番目の画像)。1つのspehereライトは頂点シェーダーで実行され、もう1つはフラグメントで実行されます。

頂点ライトシェーダーは次のようになります。頂点:

// 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-世界観の投影行列。

問題がどこにあるかについてのアイデアをいただければ幸いです。

[編集]これがフラグメントで行われた私の軽い計算です:Vertexシェーダーファイル:

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] Joakimが指摘したように、フラグメントシェーダーでvarEyeNormalを正規化していませんでした。それを修正した後、フラグメントシェーダーでの結果ははるかに良くなります。また、uEyePosで正規化関数を使用したので、スペキュラーはダークサイドになりません。すべての助けをありがとう。

ここに画像の説明を入力してください

4

1 に答える 1

19

varEyeNormal簡単な答え:頂点シェーダーではなく、フラグメントシェーダーで正規化する必要があります。

長い答え:スムーズな照明を得るには、頂点ごとではなく、ピクセルごとに法線を計算する必要があります。頂点シェーダーで計算された変化は、フラグメントシェーダーに渡される前に線形補間されます。これは、ショートカットとして優れている場合もあれば、さらに悪い場合もあります。

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

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

正規行列は、Modelview行列の逆行列の転置の上位3x3である必要があります。これは、Modelviewに回転と変換のみが含まれている場合(スケーリングなし)、Modelview行列の上位3x3に相当します。

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

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

于 2012-11-08T12:32:27.567 に答える