GLSL:旋转正常

时间:2014-12-27 20:12:30

标签: c++ opengl glsl lightning

有一个场景包含一些物体和地形。当我尝试旋转对象时,法线保持不变。意味着物体的暗侧保持物体的暗侧。 我的镜面闪电正在发挥作用。

顶点着色器:

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;
}

Fragment Shader:

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);
}

1 个答案:

答案 0 :(得分: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(正常矩阵)应用于两个向量,即使它们已经被转换。它没有坏处,因为如果对两个向量应用相同的旋转,点积不会改变,但它没有意义。
  • 所有使用的值(positionlightPos2normal)都由模型视图矩阵转换。所以他们的相对位置/方向与他们原来的完全相同。计算结果与将其应用于相应的未转换向量时的结果相同。

您需要决定要用于照明计算的坐标系。至少有几种选择。最简单的一个可能是使用眼睛坐标空间。要执行此操作,您可以在将视图转换传递到着色器之前将其应用于灯光位置,然后在着色器代码中直接使用此灯光位置,而无需任何其他转换。

由于您说镜面反射照明工作正常,并且您在那里使用制服lightPos,因此可能就像在漫反射计算中使用该变量而不是lightPos2一样简单