-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,对变换方向向量而不是点进行必要的调整。因此,模型视图转换已应用于所有positionlightPos2normal

然后,所有这三个值(应用了插值)都被传递到片段着色器中,您可以在其中计算漫反射光照项:

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

现在,这里有几个问题:

  • nMat即使它们已经被转换,您也正在将正常矩阵再次应用于两个向量。它没有害处,因为如果对两个向量应用相同的旋转,点积不会改变,但这没有意义。
  • 所有使用的值 ( position, lightPos2, normal) 都由模型视图矩阵转换。所以它们的相对位置/方向与它们最初的完全一样。计算结果将与将其应用于相应的未变换向量时的结果相同。

您需要确定要用于照明计算的坐标系。至少有几个选项。对您来说最简单的一种可能是使用眼睛坐标空间。为此,您可以在将其传递到着色器之前将视图变换应用于灯光位置,然后在着色器代码中直接使用此灯光位置,无需任何额外的变换。

由于您说镜面照明按需要工作,并且您在lightPos那里使用制服,所以它可能就像使用该变量而不是lightPos2在漫反射计算中一样简单。

于 2014-12-27T21:30:07.357 回答