C++ 尝试分配帧缓冲区时出现OpenGL异常';s颜色附着到立方体贴图';脸

C++ 尝试分配帧缓冲区时出现OpenGL异常';s颜色附着到立方体贴图';脸,c++,exception,opengl,textures,framebuffer,C++,Exception,Opengl,Textures,Framebuffer,我需要创建一个以场景中心为中心的环境贴图。为此,我使用一个帧缓冲区和6个摄影机渲染每个角(右、左、上、下、后、前) 首先,我创建必须包含最终结果的立方体贴图: unsigned int envMapTex; glGenTextures(1, &envMapTex); glBindTexture(GL_TEXTURE_CUBE_MAP, envMapTex); const unsigned int ENV_WIDTH = 1024, ENV_HEIGHT = 1024; glTexPara

我需要创建一个以场景中心为中心的环境贴图。为此,我使用一个帧缓冲区和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_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (unsigned int i = 0; i < 6; ++i)
{
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, ENV_WIDTH, ENV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
我创建的纹理必须在每次迭代时记住,从各个角度看:

unsigned int envMapSuppTex;
glGenTextures(1, &envMapSuppTex);
glBindTexture(GL_TEXTURE_2D, envMapSuppTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ENV_WIDTH, ENV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
最后,我创建并初始化帧缓冲区:

unsigned int envMapRBO;
glGenRenderbuffers(1, &envMapRBO);
glBindRenderbuffer(GL_RENDERBUFFER, envMapRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, ENV_WIDTH, ENV_HEIGHT);
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);
在渲染循环中,在每次迭代时:

  • 我用照相机渲染场景

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

  • 我将当前颜色附件指定给立方体贴图的当前面

  • 使用下一个摄像头重新开始循环

     if (firstFrame)
     {
         glBindFramebuffer(GL_FRAMEBUFFER, envMapFBO);
         glViewport(0, 0, ENV_WIDTH, ENV_HEIGHT);
         glClearColor(1.0f, 0.0f, 0.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, 0, GL_RGB, ENV_WIDTH, ENV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, &envMapSuppTex);
             glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
             glBindTexture(GL_TEXTURE_2D, 0);
         }
    
    所以问题是:如何正确地将帧缓冲区的颜色附件指定给立方体贴图的面

    备注:异常报告在“glBindTexture…”行中,但如果我删除/注释该行,异常将移动。总的来说,我非常确定它是相对于“glTexImage2D…”行的

    解决方案

    由于envmappsupptex是GPU内存中纹理的ID,因此无法使用glTexImage2D(),因为它需要CPU内存中的指针。因此,我们使用glCopyTexImage2D()将纹理复制到我们选择的目标。纹理是从glReadBuffer()或glNamedFramebufferReadBuffer()定义的目标复制的

    就我而言:

    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 0, 0, ENV_WIDTH, ENV_HEIGHT, 0);
    
    可以安全地删除glTexImage2D()行


    感谢Hihikomori提供的解决方案。

    envMapSuppTex-是gpu内存中纹理的id,但glTexImage2D需要指向主机内存的指针。我建议用空指针替换&envMapSuppTex,然后用glCopyTexImage2D将fbo纹理复制到立方体贴图纹理。@Hikomori感谢您的回复!是的,问题是,envMapSuppTex是GPU内存中纹理的ID。使用glReadBuffer()和glCopyTexImage2D()解决了这个问题。现在我用解决方案编辑帖子。envMapSuppTex-是gpu内存中纹理的id,但glTexImage2D需要指向主机内存的指针。我建议用空指针替换&envMapSuppTex,然后用glCopyTexImage2D将fbo纹理复制到立方体贴图纹理。@Hihikomori感谢您的回复!是的,问题是,envMapSuppTex是GPU内存中纹理的ID。使用glReadBuffer()和glCopyTexImage2D()解决了这个问题。现在我用解决方案编辑帖子。
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, ENV_WIDTH, ENV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, &envMapSuppTex);
    
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 0, 0, ENV_WIDTH, ENV_HEIGHT, 0);