-2

いくつかのオブジェクトと地形のあるシーンがあります。オブジェクトを回転させようとすると、法線は同じままです。オブジェクトの暗い面がオブジェクトの暗い面のままであることを意味します。鏡面反射光が機能しています。

頂点シェーダー:

uniform vec3 lightPos;
uniform sampler2D Texture;
varying vec2 TexCoord;

varying vec3 position;
varying vec3 vertex;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 normal;
varying vec3 oneNormal;
varying vec3 lightPos2;

void main()
{
        gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;
        position=vec3(gl_ModelViewMatrix*gl_Vertex);
        vMatrix = mat3(gl_ModelViewMatrix);
        lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
        vertex = vec3(gl_Vertex);
        nMat = gl_NormalMatrix;
        normal=gl_NormalMatrix*gl_Normal;
        oneNormal = gl_Normal;
        TexCoord=gl_MultiTexCoord0.xy;
}

フラグメント シェーダー:

varying vec3 position;
varying vec3 normal;

uniform sampler2D Texture;
varying vec2 TexCoord;

uniform vec3 lightPos;
varying vec3 vertex;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
uniform float shininess;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 oneNormal;
varying vec3 lightPos2;


void main()
{
        float dist=length(vertex-lightPos);
        float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
        vec4 TexColor = texture2D(Texture, TexCoord);
        vec3 ambient=TexColor.rgb*lambient; //the ambient light

    //=== Diffuse ===//
        vec3 surf2light=normalize(position-lightPos2);
        float dcont=max(0.0, 
                    dot( normalize(nMat*(-normal)), nMat*surf2light) );
        vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

    //=== Specular ===//
        vec3 surf2view = normalize(lightPos-position);
        surf2light=nMat*normalize(-vertex);
        vec3 reflection=reflect(-surf2view,normalize(normal));

        float scont=pow(max(0.0,dot(surf2light,reflection)),shininess);
        vec3 specular=scont*lspecular;

        gl_FragColor=vec4((ambient+diffuse+specular)*att,1.0);
}
4

1 に答える 1

0

法線を変換しています。ただし、少なくとも照明計算の一部では、同じ座標空間に変換される光源の位置を使用しています。法線と光源の両方を変換すると、光源に対する法線の方向は再び同じになります。

頂点シェーダーから主要な行を抽出します。

    position=vec3(gl_ModelViewMatrix*gl_Vertex);
    lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
    normal=gl_NormalMatrix*gl_Normal;

gl_NormalMatrixに対応しgl_ModelViewMatrix、ポイントではなく方向ベクトルを変換するために必要な調整を行います。positionしたがって、モデルビュー変換は、 、lightPos2およびのすべてに適用されていますnormal

次に、これら 3 つの値すべて (補間が適用されたもの) がフラグメント シェーダーに渡されます。ここで、拡散照明用語の計算が行われます。

    vec3 surf2light=normalize(position-lightPos2);
    float dcont=max(0.0, 
                dot( normalize(nMat*(-normal)), nMat*surf2light) );
    vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

ここで、いくつかの問題があります。

  • nMat通常の行列である を両方のベクトルに適用していますが、それらは既に変換されています。両方のベクトルに同じ回転を適用しても内積は変わらないため、害はありませんが、意味がありません。
  • 使用されるすべての値 ( positionlightPos2normal) は、モデル ビュー マトリックスによって変換されました。したがって、それらの相対的な位置/方向は、元の位置とまったく同じです。計算の結果は、対応する変換されていないベクトルに適用された場合と同じになります。

ライティングの計算に使用する座標系を決定する必要があります。少なくともいくつかのオプションがあります。最も簡単な方法は、おそらく目の座標空間を使用することです。これを行うには、シェーダーに渡す前にビューの変換をライトの位置に適用し、追加の変換を行わずにこのライトの位置をシェーダー コードで直接使用します。

スペキュラー ライティングが希望どおりに機能し、そこでユニフォームを使用していると言うので、拡散計算のlightPos代わりにその変数を使用するのと同じくらい簡単かもしれません。lightPos2

于 2014-12-27T21:30:07.357 に答える