OpenGL定向光着色器 [英] OpenGL directional light shader

查看:129
本文介绍了OpenGL定向光着色器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆