我一直在尝试实现阴影贴图,但是整个场景是黑色的,而它绝对不应该是黑色的。
我在 (4, 1, 4) 处初始化一盏灯,方向为 (0, 0, 0)。这是我的主渲染循环的样子:
glfwMakeContextCurrent(window); // tell openGL we are outputting to this
target_scene->shadow_pass(); // create shadow maps
glViewport(0, 0, width, height); // swap back to our resolution
// render the scene
target_scene->render(target_camera, width / float(height));
// show the rendered scene
glfwSwapBuffers(window);
我知道渲染方法可以正确运行,因为它在实现阴影贴图之前确实工作得很好。
shadow_pass 方法如下所示:
void scene::shadow_pass() const {
glCullFace(GL_FRONT);
// resize the viewport to the shadow resolution
glViewport(0, 0, SHADOW_RES, SHADOW_RES);
// activate the super simple shader for the shadow pass
light_pass_shader->use();
for (const light *lght : lights) {
lght->bind_depth_map(); // activate the framebuffer
light_pass_shader->apply_uniform_mat4(lght->get_light_space(),
"lightSpaceMatrix");
// draw all the objects
for (object *obj : objects) {
light_pass_shader->apply_uniform_mat4(obj->get_model_matrix(),
"model");
obj->draw();
}
// cleanup
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glUseProgram(0);
glCullFace(GL_BACK);
}
这是我计算光空间矩阵并激活帧缓冲区的方法:
const static glm::mat4 lightProjection =
glm::perspective(90.0f, 1.0f, 1.0f, 10.0f);
const glm::mat4 light::get_light_space() const {
return lightProjection * glm::lookAt(this->get_position(),
this->get_direction(),
glm::vec3(0.0f, 1.0f, 0.0f));
}
void light::bind_depth_map() const {
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
}
这就是绘制的样子,它可能没问题,因为它在第二遍中使用。
void object::draw() const {
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
这是我的光通着色器的样子:
#version 430 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 vertexTexCoord;
layout(location = 3) in vec3 vertexTangent;
layout(location = 4) in vec3 vertexBitangent;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(vertexPosition, 1.0);
}
这是我的顶点和片段着色器在主渲染过程中的样子。
#version 430 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 vertexTexCoord;
layout(location = 3) in vec3 vertexTangent;
layout(location = 4) in vec3 vertexBitangent;
out vec2 texCoord;
out mat3 TBN;
out vec3 fragPos;
out vec3 normal;
out vec3 viewPos;
out vec3 shininess;
uniform mat4 model;
uniform mat4 viewProjection;
void main()
{
// Transform the vertex position by the model and view-projection matrices
gl_Position = viewProjection * model * vec4(vertexPosition, 1.0);
texCoord = vertexTexCoord;
// Transform the fragment position by the model matrix only
fragPos = vec3(model * vec4(vertexPosition, 1.0));
// Transform the normal by the model matrix only
normal = mat3(model) * vertexNormal;
// Calculate the TBN matrix using the model matrix only
vec3 T = normalize(mat3(model) * vertexTangent);
vec3 B = normalize(mat3(model) * vertexBitangent);
vec3 N = normalize(mat3(model) * vertexNormal);
TBN = mat3(T, B, N);
}
#version 430 core
#define MAX_LIGHTS 10
#define bias 0.005
in vec2 texCoord;
in vec3 fragPos;
in vec3 normal;
in mat3 TBN;
uniform sampler2D texture0;
uniform sampler2D normal0;
struct Light {
vec3 direction;
vec3 color;
mat4 lightSpaceMatrix;
sampler2D shadowMap;
};
uniform Light lights[MAX_LIGHTS];
uniform int numLights;
uniform vec3 viewPos;
uniform float shininess;
uniform vec3 ambientLight;
out vec4 out_color;
vec3 CalcDirectionalLight(Light light, vec3 norm)
{
vec3 lightDir = normalize(-light.direction);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * light.color;
// Specular shading
vec3 viewDir = normalize(viewPos - fragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
vec3 specular = spec * light.color;
// Shadow calculation
vec4 fragPosLightSpace = light.lightSpaceMatrix * vec4(fragPos, 1.0);
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(light.shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
return (1.0 - shadow) * (diffuse + specular);
}
void main()
{
vec3 norm = texture(normal0, texCoord).rgb;
norm = normalize(norm * 2.0 - 1.0);
norm = normalize(TBN * norm);
vec3 result = ambientLight;
for (int i = 0; i < numLights; ++i) {
result += CalcDirectionalLight(lights[i], norm);
}
vec4 color = texture(texture0, texCoord);
out_color = vec4(result * color.rgb, color.a);
}
帮助我,我很困惑。
我明白了。这只是我将阴影贴图以
depthMap
的形式传递给着色器,然后我尝试在着色器端以 shadowMap
的形式访问它,这当然是无稽之谈。该死的。