OpenGL定向灯着色器

时间:2017-12-27 12:13:07

标签: opengl glsl shader light

我想使用OpenGL和GLSL为我的场景添加定向光。问题在于理论上正确的方法有错误的结果。

在顶点着色器中,我执行以下操作:

光的方向以世界坐标给出,并使用viewMatrix转换为相机坐标。使用法线矩阵将顶点的法线转换为相机坐标。

sed

因此两个矢量都在相机坐标中并传递给片段着色器。片段着色器使用法线和光的方向计算光强度。

void main () {
    vary_textureCoord = attribute_textureCoord;
    vary_normal = mat3(normalMatrix) * attribute_normal;

    vary_directionalLight_direction = viewMatrix * vec4(lightDir, 1.0);

    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(attribute_position, 1.0);
}

此着色器导致光线不是静止的,而是与相机一起移动。改为使用此行更改顶点着色器:

void main () {
    vec3 normalizedNormal = normalize(vary_normal);
    vec4 color = texture(tex, vary_textureCoord);

    float directionalLightIntensity = max(0.0, dot(normalizedNormal, normalize(-vary_directionalLight_direction.xyz)));

    out_color =  color * directionalLightIntensity;
}

有所需的结果。 那么我做错了什么或者我在哪里有误会?

这里是完整的着色器代码:

Vertexshader:

vary_directionalLight_direction = transpose(inverse(viewMatrix)) * vec4(lightDir, 1.0);

Fragmentshader:

# version 330

layout(location = 0) in vec3 attribute_position;
layout(location = 2) in vec2 attribute_textureCoord;
layout(location = 3) in vec3 attribute_normal;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 normalMatrix;
uniform vec3 lightDir;

out vec2 vary_textureCoord;
out vec3 vary_normal;
out vec4 vary_directionalLight_direction;

void main () {
    vary_textureCoord = attribute_textureCoord;
    vary_normal = mat3(normalMatrix) * attribute_normal;

    vary_directionalLight_direction = viewMatrix * vec4(lightDir, 1.0);

    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(attribute_position, 1.0);
}

1 个答案:

答案 0 :(得分:1)

转换矩阵如下所示:

( X-axis.x, X-axis.y, X-axis.z, 0 )
( Y-axis.x, Y-axis.y, Y-axis.z, 0 )
( Z-axis.x, Z-axis.y, Z-axis.z, 0 )
( trans.x,  trans.y,  trans.z,  1 ) 

如果要转换位置,则必须将完整转换矩阵应用于该位置。

mat4 viewMatrix;
vec3 pos;
vec4 viewPos = viewMatrix * vec4(pos, 1.0);

这会将视图的方向和位置应用于位置pos

但方向没有根源。方向只有一个方向。这意味着,如果你想通过视图变换方向向量,那么你必须将它乘以4 * 4 viewMatrix的左上角3 * 3部分:

vary_directionalLight_direction = vec4(mat3(viewMatrix) * lightDir, 1.0);