0

我有一个每个片段照明的工作,但我想知道如何在模型空间中保持照明计算,我不必在片段着色器中将法线乘以 normalModelMatrix,如下所示。

着色器:ViewMatrix - 相机变换,ModelMatrix - 对象变换。灯光位置 - glm::vec4 lightPos(3.0f, 2.0f, -30.0f, 1.0f)

渲染循环:

glUseProgram(ProgramId);
glUniformMatrix4fv(ViewMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(ViewMatrix));
glUniform4f(lightIntensityUniformLocation, 0.8f, 0.8f, 0.8f, 1.0f);
glUniform4f(ambientIntensityUniformLocation, 0.2f, 0.2f, 0.2f, 0.2f);
glUniform3fv(dirToLightUniformLocation, 1, glm::value_ptr( lightPos));

ModelMatrixStack.push(ModelMatrix);
ModelMatrix = glm::translate(ModelMatrix, glm::vec3(0, 0, -30));
ModelMatrix = glm::rotate(ModelMatrix, 75.0f, glm::vec3(0,0,1)); 
normMatrix = glm::mat3(ModelMatrix);
glUniformMatrix4fv(ModelMatrixUniformLocation, 1, GL_FALSE,           
glm::value_ptr(ModelMatrix));   
glUniformMatrix3fv(normalModelMatrixUniformLocation, 1, GL_FALSE, 
glm::value_ptr(normMatrix));
drawTeapot();

ModelMatrix = ModelMatrixStack.top();
normMatrix = glm::mat3(ModelMatrix);

glUniformMatrix4fv(ModelMatrixUniformLocation, 1, GL_FALSE,  
glm::value_ptr(ModelMatrix));
glUniformMatrix3fv(normalModelMatrixUniformLocation, 1, GL_FALSE,  
glm::value_ptr(normMatrix));
myground.draw();

glUseProgram(0);

顶点着色器:

#version 400

layout(location=0) in vec4 in_position;
layout(location=1) in vec3 in_normal;
out vec3 normal;
out vec4 position;

uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

void main(void)
{
     vec4 vertexPosition = ModelMatrix * in_position;
     gl_Position = ProjectionMatrix * ViewMatrix * vertexPosition;
     normal = in_normal;
     position = vertexPosition;
}

片段着色器:

version 400

in vec3 normal;
in vec4 position;
out vec4 outputColor;

uniform vec3 lightPos;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;
uniform mat3 normalModelMatrix;

void main(void)
{
     vec3 normCamSpace = normalize(normalModelMatrix * normalize(normal));
     vec3 dirToLight = normalize(lightPos - vec3(position));
     float cosAngIncidence = dot(normCamSpace, dirToLight);
     cosAngIncidence = clamp(cosAngIncidence, 0, 1);
     outputColor = (lightIntensity * cosAngIncidence) + ambientIntensity;
}
4

1 回答 1

2

在模型空间中进行照明的计算成本实际上比在眼睛空间中更高,因为您必须为每个模型单独转换光的位置和方向。这些通常发生在 CPU 端。然而,你仍然需要对法线进行转换。

我不必在片段着色器中将法线乘以 normalModelMatrix 的模型空间,如下所示。

该计算在顶点着色器中也适用。把它移到那里。


更新/编辑

为了澄清,修改后的着色器代码:

顶点着色器:

#version 400

layout(location=0) in vec4 in_position;
layout(location=1) in vec3 in_normal;

out vec3 eyespaceNormal;
out vec4 eyespacePosition;

uniform mat4 ModelviewMatrix;
uniform mat3 NormalMatrix; // == inverse(transpose(ModelviewMatrix))
uniform mat4 ProjectionMatrixq;

void main(void)
{
     eyespacePosition = ModelviewMatrix * in_position;
     eyespaceNormal = normalize(NormalMatrix * in_normal);
     gl_Position = ProjectionMatrix * eyespacePosition;
}

片段着色器:

#version 400

in vec3 eyespaceNormal;
in vec4 eyespacePosition;
out vec4 outputColor;

uniform vec3 lightPos;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;

void main(void)
{
     vec3 dirToLight = normalize(lightPos - vec3(eyespacePosition));
     float cosAngIncidence = dot(eyespaceNormal, dirToLight);
     cosAngIncidence = clamp(cosAngIncidence, 0, 1);
     outputColor = (lightIntensity * cosAngIncidence) + ambientIntensity;
}

顺便说一句:你正常的变换矩阵是错误的。为此,您必须使用转置模型视图矩阵的逆矩阵。

于 2012-05-03T09:26:42.727 回答