OpenGL 定向光着色器
OpenGL directional light shader
我想使用 OpenGL 和 GLSL 向我的场景添加定向光。问题是理论上正确的方法会得到错误的结果。
在顶点着色器中,我执行以下操作:
光线的方向在世界坐标中给出,并使用 viewMatrix 转换为相机坐标。使用法线矩阵将顶点的法线转换为相机坐标。
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;
}
这个着色器导致光线不是静止的而是随着相机移动的结果。使用此行更改顶点着色器:
vary_directionalLight_direction = transpose(inverse(viewMatrix)) * vec4(lightDir, 1.0);
有预期的结果。
那我哪里做错了或者哪里有误会?
这里是完整的着色器代码:
顶点着色器:
# 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);
}
片段着色器:
# version 330
in vec2 vary_textureCoord;
in vec3 vary_normal;
in vec4 vary_directionalLight_direction;
uniform sampler2D tex;
out vec4 out_color;
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;
}
变换矩阵如下所示:
( 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);
我想使用 OpenGL 和 GLSL 向我的场景添加定向光。问题是理论上正确的方法会得到错误的结果。
在顶点着色器中,我执行以下操作:
光线的方向在世界坐标中给出,并使用 viewMatrix 转换为相机坐标。使用法线矩阵将顶点的法线转换为相机坐标。
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;
}
这个着色器导致光线不是静止的而是随着相机移动的结果。使用此行更改顶点着色器:
vary_directionalLight_direction = transpose(inverse(viewMatrix)) * vec4(lightDir, 1.0);
有预期的结果。 那我哪里做错了或者哪里有误会?
这里是完整的着色器代码:
顶点着色器:
# 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);
}
片段着色器:
# version 330
in vec2 vary_textureCoord;
in vec3 vary_normal;
in vec4 vary_directionalLight_direction;
uniform sampler2D tex;
out vec4 out_color;
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;
}
变换矩阵如下所示:
( 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
:
vary_directionalLight_direction = vec4(mat3(viewMatrix) * lightDir, 1.0);