【发布时间】:2020-05-14 02:31:06
【问题描述】:
我正在尝试通过动态阴影映射和前向渲染在我的自定义渲染器上实现阴影(稍后会实现延迟渲染)。例如,一切都正确渲染到用于生成阴影贴图的帧缓冲区。但是,当使用默认帧缓冲区正常渲染场景时,只会渲染天空盒(这意味着使用了默认帧缓冲区),我唯一的假设是问题与深度缓冲区有关,因为禁用了对 DrawActors(.. .)(在 ForwardRenderShadows 中)似乎可以解决问题,但如果这样做,我将无法生成深度图。对此事有何建议?
代码:
void Scene::DrawActors(const graphics::Shader& shader)
{
for(const auto& actor : actors_)
actor->Draw(shader);
}
template <typename T>
void ForwardRenderShadows(const graphics::Shader& shadow_shader, const std::vector<T>& lights)
{
for(const auto& light : lights)
{
if(light->Shadow())
{
light->DrawShadows(shadow_shader);
DrawActors(shadow_shader); //removing this line "solves the problem"
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
}
/*
shadow mapping is only implemented on directional lights for the moment, and that is the
relevant code that gets called when the process starts, more code details at the end of code
snippet.
*/
void DirectionalLight::SetupShadows()
{
glGenFramebuffers(1, &framebuffer_);
glGenTextures(1, &shadow_map_);
glBindTexture(GL_TEXTURE_2D, shadow_map_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, constants::SHADOW_WIDTH, constants::SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_map_, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw std::runtime_error("Directional light framebuffer is not complete \n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ShadowSetup(true);
}
void DirectionalLight::DrawShadows(const graphics::Shader& shader)
{
if(!ShadowSetup())
SetupShadows();
glViewport(0, 0, constants::SHADOW_WIDTH, constants::SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
glClear(GL_DEPTH_BUFFER_BIT);
shader.Use();
projection_ = clutch::Orthopraphic(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 100.0f);
transform_ = clutch::LookAt(direction_ * -1.0f, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f});
shader.SetUniformMat4("light_transform", projection_ * transform_);
}
void DirectionalLight::Draw(const graphics::Shader& shader)
{
shader.SetUniform4f("light_dir", direction_);
shader.SetUniform4f("light_color", color_);
shader.SetUniformMat4("light_transform", transform_);
shader.SetUniformMat4("light_projection", projection_);
shader.SetUniformInt("cast_shadow", shadows_);
glActiveTexture(GL_TEXTURE12);
shader.SetUniformInt("shadow_map", 12);
glBindTexture(GL_TEXTURE_2D, shadow_map_);
}
对 repo 进行编码:https://github.com/rxwp5657/Nitro
问题的相关文件:
- include/core/scene.hpp
- include/core/directional_light.hpp
- include/core/light_shadow.hpp
- include/core/directional_light.hpp
include/graphics/mesh.hpp
src/core/scene.cpp
- src/core/directional_light.cpp
- src/core/light_shadow.cpp
- src/core/directional_light.cpp
- src/graphics/mesh.cpp
最后,我到目前为止尝试的是:
- 使用 glDepthMask(GL_FALSE) 和 glDisable(GL_DEPTH_TEST) 停用深度测试 //同样的问题。
- 将深度函数更改为 glDepthFunc(GL_ALWAYS); // 没有想要的结果;
【问题讨论】:
-
OpenGL 调试很繁琐。大多数情况下,我试图通过代码凝视来解决我的问题(并且它以某种方式主要工作)但这真的......很乏味。通过google "opengl debugger",我发现了这个:Debugging Tools on khronos.org,Learn OpenGL - Debugging。我记得一位同事曾经用一个工具支持我,其中所有的 GL 状态变化都在一个工具中直观地显示出来(但不幸的是,我忘记了他用于此操作的内容)。
-
嗨,谢夫,感谢您的评论。是的,OpenGL 调试真的很乏味,到目前为止我遇到的大多数问题都是因为缓冲区布局不正确,即使在那些情况下,您也知道问题可能就在那里,甚至会生成一些颜色输出来调试着色器,但在这种情况下,我甚至不能那样做。例如,我的开发环境是在 MacOS 上,但似乎我必须稍微改变一下 Windows 才能充分利用这些工具,每当我有任何进展时,我都会再次发表评论。谢谢;)。
-
我问了我的同事。他告诉我这个工具是apitrace。在其文档中。它声称也支持 OS/X。
-
Scheff,感谢您的工具,我刚刚发现了错误,apitrace 确实有效。所以,问题是我的顶点数据被擦除或其他东西,通常一个顶点是由一个位置、法线、切线、纹理坐标等形成的,但是当使用帧缓冲区时,数据被“覆盖”,现在缓冲区只有法线。然而,这并不是最奇怪的事情,法线顶点数据被位置数据覆盖,其他属性(切线、真实法线等)消失了。我将不得不回顾发生了什么,因为这只发生在帧缓冲区中。谢谢:)