我如何在OpenGL中使用立方体贴图数组来渲染带有阴影贴图的多个点灯?



我阅读并实现了以下教程:https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows

现在我想把它推广到我的场景中渲染多点灯光,我该怎么做呢?我听说立方体映射数组可以用来做这样的事情,它们到底是如何工作的呢?有人能给我举个例子吗?

(我回答这个问题是为了我自己和未来的几代人,因为目前还没有关于如何使用立方体映射数组的简单的谷歌教程。)

如果你想传递多个cubemap阴影映射到一个着色器,并且你不知道有多少,那么cubemap数组是一个很好的解决方案。它们的工作原理类似于3D纹理,其中每一层都是一个立方体图。在片段着色器中,你可以为它们创建一个采样器,如下所示:

uniform samplerCubeArray cubeMapArray;

你可以通过以下方式将数组纹理绑定到它:

glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_PointLightDepthMaps.m_DepthTexture);

你可以从samplerCubeArray中采样,就像你从cubemap中采样一样,但在这种情况下,你的向量得到第四个元素,这是要采样的层。例如:

texture(cubeMapArray, vec4(dir, 3)).r

将从数组中的第四个立方体映射中采样。要创建自己的cubemap数组作为深度纹理,您可以使用以下模板:

void Renderer::initCubemapDepthMap(CubemapDepthMap& map)
{
glGenTextures(1, &map.m_DepthTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, map.m_DepthTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage3D(
GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_DEPTH_COMPONENT, m_ShadowCubeMapResolution, m_ShadowCubeMapResolution, 6 * m_MaxPointLights + 6 * m_MaxSpotLights, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
glGenFramebuffers(1, &map.m_FrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, map.m_FrameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, map.m_DepthTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
const int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!n";
throw 0;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

注意,你需要使用GL_TEXTURE_CUBE_MAP_ARRAY作为你的纹理类型,你需要使用glTexImage3D。当调用glTexImage3D时,层数是你需要立方体地图的数量乘以6,因为每个立方体地图的面都像一个单独的层一样被分配。当你在片段着色器中采样时,你不需要考虑到这一点!

在渲染阴影贴图时,像绑定其他缓冲区一样绑定缓冲区。当你将深度纹理传递给着色器时,你传递了整个立方体贴图数组,不需要混淆单独的图层。

最新更新