问题描述
我需要创建一个以场景中心为中心的环境贴图。为此,我使用了一个帧缓冲区和 6 个摄像头来渲染每个角(右、左、上、下、后、前)。
首先,我创建必须包含最终结果的立方体贴图:
unsigned int envMapTex;
glGenTextures(1,&envMapTex);
glBindTexture(GL_TEXTURE_CUBE_MAP,envMapTex);
const unsigned int ENV_WIDTH = 1024,ENV_HEIGHT = 1024;
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
for (unsigned int i = 0; i < 6; ++i)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,GL_RGB,ENV_WIDTH,ENV_HEIGHT,GL_UNSIGNED_BYTE,NULL);
}
glBindTexture(GL_TEXTURE_CUBE_MAP,0);
我创建了仅包含深度值的渲染缓冲区,并将分配给帧缓冲区的深度附件:
unsigned int envMapRBO;
glGenRenderbuffers(1,&envMapRBO);
glBindRenderbuffer(GL_RENDERBUFFER,envMapRBO);
glrenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT32F,ENV_HEIGHT);
我创建了每次迭代时都必须记住的纹理,每个角度的视角:
unsigned int envMapSuppTex;
glGenTextures(1,&envMapSuppTex);
glBindTexture(GL_TEXTURE_2D,envMapSuppTex);
glTexParameteri(GL_TEXTURE_2D,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,NULL);
最后我创建并初始化帧缓冲区:
unsigned int envMapFBO;
glGenFramebuffers(1,&envMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER,envMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,envMapSuppTex,0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,envMapRBO);
glBindRenderbuffer(GL_RENDERBUFFER,0);
glBindTexture(GL_TEXTURE_2D,0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) std::cout << "yep" << std::endl;
else std::cout << "nope" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER,0);
此时我创建了 6 个摄像头的数组:
float aspect = (float)ENV_WIDTH / (float)ENV_HEIGHT;
float near = 1.0f;
float far = 25.0f;
glm::vec3 center = glm::vec3(0.0f,wall_height / 2.0f,0.0f);
Camera envMapCameras[6] = {
Camera(ENV_WIDTH,center,90.0,0.0f,1.0f,near,far),//Positive X
Camera(ENV_WIDTH,-180.0f,//Negative X
Camera(ENV_WIDTH,-90.0f,90.0f,//Positive Y
Camera(ENV_WIDTH,//Negative Y
Camera(ENV_WIDTH,//Positive Z
Camera(ENV_WIDTH,//Negative Z
};
在渲染循环中,每次迭代时:
-
我用相机渲染场景
-
我绑定了立方体贴图和颜色附件
-
我将当前颜色附件分配给立方体贴图的当前面
-
下一个摄像头开始循环
if (firstFrame) { glBindFramebuffer(GL_FRAMEBUFFER,envMapFBO); glViewport(0,ENV_HEIGHT); glClearColor(1.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (unsigned int i = 0; i < 6; ++i) { glDepthFunc(GL_LEQUAL); renderSkyBox(*skyBoxShader,envMapCameras[i]); glDepthFunc(GL_LESS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); renderScene(envMapCameras[i]); glBindTexture(GL_TEXTURE_CUBE_MAP,envMapTex); glBindTexture(GL_TEXTURE_2D,envMapSuppTex); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,&envMapSuppTex); glBindTexture(GL_TEXTURE_CUBE_MAP,0); glBindTexture(GL_TEXTURE_2D,0); }
当我运行时,在该行之后抛出异常:
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,&envMapSuppTex);
所以问题是:如何将帧缓冲区的颜色附件正确分配给立方体贴图的一个面?
P.s.:在“glBindTexture ...”行报告异常,但如果我删除/注释该行,异常就会移动。一般来说,我非常确定它与“glTexImage2D...”行相关。
解决方案
由于 envMapSuppTex 是 GPU 内存中纹理的 ID,我们不能使用 glTexImage2D(),因为它需要 cpu 内存中的指针。因此,我们使用 glcopyTexImage2D() 将纹理复制到我们选择的目标。纹理是从 glreadBuffer()(或 glNamedFramebufferReadBuffer())定义的目标复制的。
就我而言:
glreadBuffer(GL_COLOR_ATTACHMENT0);
glcopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,0);
可以安全地删除 glTexImage2D() 行。
感谢 Hihikomori 的解决方案。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)