当然可以使用6个帧缓冲对象(FBOs),每个面一个。或者在绘制之前使用一个FBO并附加每个面。在这两种情况下,立方体贴图面将像任何其他2D纹理一样进行处理,您可以与普通的2D纹理或渲染缓冲一起使用它。如果硬件支持所有可能的方式,可能没有太大的区别。
但是,也可以一步完成所有绘制操作,因此我很好奇如何完成这个过程,于是我做了一些研究。
要创建一个带有所有立方体贴图面附加到单个附加点的FBO,我使用了以下代码(用D语言编写):
glGenTextures(1, &tDepthCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, tDepthCubeMap);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (uint face = 0; face < 6; face++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT24,
width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
}
glGenTextures(1, &tColorCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, tColorCubeMap);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (uint face = 0; face < 6; face++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_FLOAT, null);
}
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, tDepthCubeMap, 0);
glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, tColorCubeMap, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
if (!isValidFBO()) {
glDeleteFramebuffersEXT(1, &fbo);
fbo = 0;
}
- 如果您只想要深度图,您需要在验证之前(以及绘制之前)将glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);更改为glDrawBuffer(GL_NONE);
- MIN和MAG过滤器必须设置为有效值(默认情况下为GL_NEAREST_MIPMAP_LINEAR)
- 所有纹理的宽度和高度必须相同
要渲染立方体贴图的面,您需要一个几何着色器。以下着色器缺少一些旋转,但应该清楚它所做的事情。gl_Layer用于将基元定向到正确的面(0 = +X,1 = -X,...)。
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main(void) {
int i, layer;
for (layer = 0; layer < 6; layer++) {
gl_Layer = layer;
for (i = 0; i < 3; i++) {
gl_Position = gl_PositionIn[i];
EmitVertex();
}
EndPrimitive();
}
}