Opengl 渲染动态立方体阵列

Opengl 渲染动态立方体阵列,opengl,glsl,Opengl,Glsl,因此,我正在编写一个程序,它将使用帧缓冲区动态设置一些立方体贴图,我希望将其打包到一个数组中,以便在着色器中使用。我目前已经设置了允许singlular cubemaps的代码,但是我很难让它在cubemaparrays中工作 我的立方体阵列设置功能: void createCubemapArray(GLuint& cubemap) { //Generate an array texture glGenTextures(1, &cubemap); glBi

因此,我正在编写一个程序,它将使用帧缓冲区动态设置一些立方体贴图,我希望将其打包到一个数组中,以便在着色器中使用。我目前已经设置了允许singlular cubemaps的代码,但是我很难让它在cubemaparrays中工作

我的立方体阵列设置功能:

void createCubemapArray(GLuint& cubemap)
{
    //Generate an array texture
    glGenTextures(1, &cubemap);
    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubemap);

    //Create storage for the texture. (4 layers of 1x1 texels)
    glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY,
        1,                    //No mipmaps as textures are 1x1
        GL_RGB8,              //Internal format
        width, height,                 //width,height
        4                   //Number of layers
    );

    for (unsigned int i(0); i != 4; ++i)
    {
        glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY,
            0,                     //Mipmap number
            0, 0, i,                 //xoffset, yoffset, zoffset
            1, 1, 1,                 //width, height, depth
            GL_RGB,                //format
            GL_UNSIGNED_BYTE,      //type
            0);                //pointer to data
    }

    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);
}
这是在我的主函数中调用的。我希望我已经将其设置为允许在运行时向其添加纹理

这就是我如何向其添加帧缓冲区纹理的方法:

    vec3 position = mirrorCam.getPosition();
    view = look_at(position, position + normalise(viewsX[i]), vec3(0.0, -0.5, -0.5));
    drawloop(view, proj, fb[0][i].framebuffer);
    glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemapArray, 0, 0);
drawloop()是我的主渲染循环,它将大部分场景渲染到我传入的帧缓冲区。mirrorCam是我为立方体贴图设置的摄影机对象

然后,要将其传递到着色器中,我有以下几行:

glBindTexture(GL_TEXTURE_2D, cubemapArray);
glUniform1i(glGetUniformLocation(reflectiveShaderID, "cube_array"), 0);
最后,我的着色器代码。缩短至重要部分:

uniform samplerCubeArray cube_array;
//....
void main()
{
//...
fragment_color = texture(cube_array, vec4(textureCoordinates, 0));   
}

当所有这些都被渲染时,我得到一个黑色对象,即没有纹理。但是,当我在单个cubemap中交换时,它工作得很好,因此我确信问题要么在于数组的初始化,要么在于如何将图像绑定到数组。有什么想法吗?

首先,让我们把显而易见的事情放在一边:

如果你想读一本书,你必须

现在,对于稍微不那么明显的问题:

如果您试图渲染到立方体贴图数组的每个面,那么这不是怎么做的。现在还不清楚
i
到底代表什么,但是如果它应该是cubemap数组中第一层的一个面,那么就不是这样做的

请参见,立方体贴图阵列纹理从不使用立方体贴图面目标。相反,它们使用层面。此外,立方体贴图数组纹理不使用
glFramebufferTexture3D
;它们仅允许与
glFramebufferTexture
glFramebufferTextureLayer
一起使用。你可能想用后者

因此,如果希望
i
表示立方体贴图中第一层的面索引,可以执行以下操作:

glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemapArray, 0, i);

我不确定OP是否解决了这个问题,但无论谁需要帮助,让我分享一些示例代码和解释

所以这里的挑战是在数组中存储和使用立方体贴图。 OpenGL为我们提供了一些奇特的函数和枚举来生成立方体贴图纹理,分配内存,并将它们用作渲染目标。让我们一步一步地看一遍

  • 生成立方体贴图数组纹理-不必担心大小/计数,您只需要一个名称

     glGenTextures(1, &cubemap_array);
    
  • 绑定立方体贴图数组纹理-注意特殊的纹理目标

     glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubemap_array);
    
  • 继续添加一些参数-这也是一个重要的步骤,如果没有这些参数,您只能获得一些黑色纹理

     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);
     glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
  • 在渲染过程中,绑定帧缓冲区并将立方体贴图的面绑定到帧缓冲区的颜色附件。(也可以在渲染过程之外执行此操作。)

  • 这里需要注意的重要事项是glFramebufferTextureLayer(…)调用的最后两个参数

    两个参数中的第一个(从末尾算起的第二个)定义要附加到颜色附件的纹理的mip贴图级别。因此,您对上一个答案的评论表明,您的代码无法按预期工作。参考-

    其次,最后一个参数是唯一确定存储在cubemap数组中的cubemap的哪个面用作颜色附件的参数

    其定义如下: '特定立方体贴图的面'='立方体贴图在数组中的位置'*6+'面索引'

    例如,阵列中有12个立方体贴图,但需要将第6个立方体贴图的正面设置为渲染目标。 因此,您需要将最后一个参数设置为-(5)*6+0


    您可以在此处的cubemap数组上下文中了解有关面索引的更多信息-

    “glTexSubImage3D”如果不向它们传递数据,为什么要进行这些调用?如果您正在设置包裹模式,为什么不也设置
    GL\u TEXTURE\u wrap\R
    wrap模式呢?我下面的设置示例包括这些调用。我假设您需要以某种形状或格式初始化层,以便以后可以动态设置值。“I”应该表示面索引值,是的。这是否意味着,如果我想修改下一个立方体贴图,我会做以下操作:“glFramebufferTextureLayer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,cubemapArray,1,I);”?因此,经历了这些,我仍然很困惑。我正在单独创建面,并且我希望能够添加它们。这是否意味着我应该创建单独的立方体贴图,然后将这些立方体贴图作为层添加到立方体阵列中?目前,我已经编辑了使用glFramebufferTextureLayer而不是glFramebufferTexture3D的代码,但仍然没有得到任何纹理。
     glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubemap_array);
    
     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);
     glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
       glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemap_array, 0, cubemap_index * 6 + face);
    
       // Do your rendering stuff here.