微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试将 Framebuffer 的颜色附件分配给 Cubemap 的面时的 OpenGL 异常

如何解决尝试将 Framebuffer 的颜色附件分配给 Cubemap 的面时的 OpenGL 异常

我需要创建一个以场景中心为中心的环境贴图。为此,我使用了一个帧缓冲区和 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
};

在渲染循环中,每次迭代时:

  1. 我用相机渲染场景

  2. 我绑定了立方体贴图和颜色附件

  3. 我将当前颜色附件分配给立方体贴图的当前面

  4. 一个摄像头开始循环

     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);

所以问题是:如何将帧缓冲区的颜色附件正确分配给立方体贴图的一个面?

This is the exception

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 举报,一经查实,本站将立刻删除。