OpenGL定向光着色器 [英] OpenGL directional light shader
问题描述
我想使用OpenGL和GLSL向我的场景添加定向光.问题在于这样做的理论上正确的方法会产生错误的结果.
I want to add directional light to my scene using OpenGL and GLSL. The problem is that the theoretically correct way to do so has the wrong results.
在顶点着色器中,我执行以下操作:
In the vertex shader I do the following:
光的方向以世界坐标为单位,并使用viewMatrix转换为相机坐标.使用法线矩阵将顶点的法线转换为摄影机坐标.
The direction of the light is given in world-coordinates and transformed using the viewMatrix to camera-coordinates. The normal of the vertex is transformed using the normal-matrix to camera-coordinates.
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);
}
因此,两个向量都在相机坐标中,并传递给片段着色器.片段着色器使用法线和光的方向来计算光强度.
So both vectors are in camera-coordinates and passed to the fragment shader. The fragment shader calculates the light intensity using the normal and the direction of the light.
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;
}
此着色器导致的结果是光线不是静态的而是随相机一起移动的.改为使用此行更改顶点着色器:
This shader leads to the result that the light is not static but moves along with the camera. Changing the vertex shader using this line instead:
vary_directionalLight_direction = transpose(inverse(viewMatrix)) * vec4(lightDir, 1.0);
具有所需的结果. 那么我在做错什么,或者在哪里有误解?
has the desired results. So what am I doing wrong or where do I have a misunderstanding?
以下是完整的着色器代码:
Here the full shader codes:
顶点着色器:
# 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);
}
Fragmentshader:
Fragmentshader:
# 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 )
如果要变换位置,则必须将完整的变换矩阵应用于该位置.
If you want to transform a position, then you have to apply the full transformation matrix to the position.
mat4 viewMatrix;
vec3 pos;
vec4 viewPos = viewMatrix * vec4(pos, 1.0);
这会将视图的方向和位置应用于位置pos
.
This applies the orientation and the position of the view to the position pos
.
但是方向没有原点.方向只有方向.这意味着,如果要通过视图转换方向矢量,则必须将其乘以4 * 4 viewMatrix
:
But a direction has no origin. A direction has only an orientation. This means, if you want to transform a direction vector, by the view, then you have to multiply it by the upper left 3*3 part of the 4*4 viewMatrix
:
vary_directionalLight_direction = vec4(mat3(viewMatrix) * lightDir, 1.0);
这篇关于OpenGL定向光着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!