使用GL_TEXTURE_2D_ARRAY作为绘制目标

时间:2015-08-03 17:40:54

标签: c++ opengl

我创建了一系列2D纹理,并使用 glTexImage3D 对其进行初始化。然后我使用 glFramebufferTextureLayer 将单独的纹理附加到颜色附件,Framebuffer创建不会抛出错误,一切似乎都很好,直到绘制调用发生。

当着色器尝试访问颜色附件时,将显示以下消息:

OpenGL Debug Output message : Source : API; Type : ERROR; Severity : HIGH;
GL_INVALID_OPERATION error generated. <location> is invalid.

着色器使用 location 限定符访问数组的图层:

layout (location = 0) out vec3 WorldPosOut; 
layout (location = 1) out vec3 DiffuseOut; 
layout (location = 2) out vec3 NormalOut; 
layout (location = 3) out vec3 TexCoordOut; 

文档说 glFramebufferTextureLayer 就像 glFramebufferTexture2D 一样,除了图层参数,所以我可以使用 location 限定符和纹理数组,或者一些其他方式存在吗?

1 个答案:

答案 0 :(得分:3)

我终于设法将纹理数组绑定为颜色缓冲区。很难找到有关该主题的有用信息,因此这里有一条指令:

№1。您需要创建纹理数组并正确初始化它:

glGenTextures(1, &arrayBuffer);
glBindTexture(GL_TEXTURE_2D_ARRAY, arrayBuffer);

// we should initialize layers for each mipmap level
    for (int mip = 0; mip < mipLevelCount; ++mip) {

glTexImage3D(GL_TEXTURE_2D_ARRAY, mip, internalFormat, ImageWidth, ImageHeight,
 layerCount, 0, GL_RGB, GL_UNSIGNED_INT, 0);
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, textureFilter);
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, textureFilter);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mipLevelCount - 1);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

}

请记住,设置纹理参数(如MIN / MAG过滤器和BASE / MAX mipmap级别)很重要。 OpenGL将最大mipmap级别设置为1000,如果你没有提供全部的mipmap,你将得到一个不完整的纹理,除黑屏外你什么也得不到。

№2。在将图层附加到颜色缓冲区之前,不要忘记将 arrayBuffer 绑定到GL_TEXTURE_2D_ARRAY目标:

glBindTexture(GL_TEXTURE_2D_ARRAY, arrayBuffer);

for (unsigned int i = 0; i < NUMBER_OF_TEXTURES; i++) {

glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, arrayBuffer, 0, i);

}

不要忘记使用 glBindTexture 将GL_TEXTURE_2D_ARRAY目标设置为0,否则可以在初始化代码之外修改它。

№3。由于数组中每个图像的 internalFormat 必须保持不变,我建议为深度/模板缓冲区创建单独的纹理:

glGenTextures(1, &m_depthTexture);

...

glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, WindowWidth,
WindowHeight, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, m_depthTexture, 0);

不要忘记为每个颜色缓冲区设置索引:

for (int i = 0; i < GBUFFER_NUM_TEXTURES; ++i)
        DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; //Sets appropriate indices for each color buffer

glDrawBuffers(ARRAY_SIZE_IN_ELEMENTS(DrawBuffers), DrawBuffers);

在着色器中,您可以使用 layout(location = n)限定符来指定颜色缓冲区。

OpenGL 3 Note(NVIDIA): glFramebufferTextureLayer 从OpenGL 3.2(核心配置文件)开始可用,但在NVIDIA上GPU的驱动程序会强制OpenGL版本达到4.5,所以你应该如果您关心兼容性,请指定OpenGL的确切版本。我在我的应用程序中使用SDL2,因此我使用以下调用来设置OpenGL版本:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

延迟着色的结果: Final render Color Buffers of the secondary FBO