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 に答える