【问题标题】:OpenGL Bindless Textures: Bind to uniform sampler2D arrayOpenGL Bindless Textures:绑定到统一的 sampler2D 数组
【发布时间】:2017-04-14 00:29:44
【问题描述】:

我正在研究使用无绑定纹理来快速显示一系列图像。我的参考资料是 OpenGL 4.5 红皮书。这本书说我可以使用这个片段着色器在着色器中对无绑定纹理进行采样:

#version 450 core
#extension GL_ARB_bindless_texture : require

in FS_INPUTS {
   vec2 i_texcoord;
   flat int i_texindex;
};

layout (binding = 0) uniform ALL_TEXTURES {
   sampler2D fs_textures[200];
};

out vec4 color;

void main(void) {
   color = texture(fs_textures[i_texindex], i_texcoord);
};

我创建了一个如下所示的顶点着色器:

#version 450 core

in vec2 vert;
in vec2 texcoord;
uniform int texindex;

out FS_INPUTS {
   vec2 i_texcoord;
   flat int i_texindex;
} tex_data;

void main(void) {
   tex_data.i_texcoord = texcoord;
   tex_data.i_texindex = texindex;
   gl_Position = vec4(vert.x, vert.y, 0.0, 1.0);
};

如你所见,我对发生的事情的理解有点弱。

在我的 OpenGL 代码中,我创建了一堆纹理,获取它们的句柄,并使它们常驻。我用来获取纹理句柄的函数是“glGetTextureHandleARB”。可以使用另一个函数“glGetTextureSamplerHandleARB”,我可以在其中传递采样器位置。这是我所做的:

Texture* textures = new Texture[load_limit];
GLuint64* tex_handles = new GLuint64[load_limit];

for (int i=0; i<load_limit; ++i)
{
    textures[i].bind();
    textures[i].data(new CvImageFile(image_names[i]));
    tex_handles[i] = glGetTextureHandleARB(textures[i].id());
    glMakeTextureHandleResidentARB(tex_handles[i]);
    textures[i].unbind();
}

我的问题是如何将我的纹理句柄绑定到片段着色器的 ALL_TEXTURES 统一属性?另外,我应该使用什么来更新顶点属性 'texindex' - 我的纹理句柄数组或纹理句柄的实际索引?

【问题讨论】:

    标签: opengl glsl textures


    【解决方案1】:

    这是 无绑定 纹理。您不会将此类纹理“绑定”到任何东西。

    bindless texturing 中,采样器的数据值是一个数字。具体来说,glGetTextureHandleARB 返回的数字。纹理句柄是 64 位无符号整数。

    在着色器中,buffer-backed interface blocks(UBO 和 SSBO)中的 sampler 类型的值是 64 位无符号整数。所以一个采样器数组在结构上等同于一个 64 位无符号整数数组。

    因此,在 C++ 中,与您的 ALL_TEXTURES 块等效的结构将是:

    struct AllTextures
    {
        GLuint64 textures[200];
    };
    

    当然,假设您正确使用std140 布局。否则,您必须查询结构的布局。

    此时,您将缓冲区视为与任何其他 UBO 用法没有区别。通过将AllTextures 粘贴到缓冲区对象中为着色器构建数据,然后将该缓冲区作为 UBO 绑定到绑定 0。您只需使用实际的纹理句柄填充数组。

    另外,我应该使用什么来更新顶点属性 'texindex' - 我的纹理句柄数组或纹理句柄的实际索引?

    好吧,谁都行不通。不是你写的那样。

    请看,ARB_bindless_texture 不允许您在任何时间通过任何着色器调用以任何方式访问您想要的任何纹理。除非您使用的是 NV_gpu_shader5,否则导致纹理访问的代码必须基于dynamically uniform expressions

    因此,除非您的渲染命令中的每个顶点都获得相同的索引或句柄...您不能使用它们来选择要使用的纹理。即使是实例化也不会拯救你,因为动态统一的表达式并不关心实例化。

    如果您想渲染一堆四边形而不必更改它们之间的制服(并且不必依赖 NVIDIA 扩展),那么您有几个选择。大多数支持无绑定纹理的硬件也支持ARB_shader_draw_parameters。这使您可以访问gl_DrawID,它表示渲染命令within a glMultiDraw-style command 的当前索引。并且该扩展明确声明gl_DrawID 是动态统一的。

    因此您可以使用它来选择要渲染的纹理。您只需发出一个多重绘制命令,在其中一遍又一遍地渲染相同的网格数据,但在每种情况下它都会获得不同的gl_DrawID 索引。

    【讨论】:

    • 谢谢,这很有帮助! OpenGL 很难!
    • 我能够让我发布的代码正常工作。我只需要像你提到的那样使用 UBO 附加到 ALL_TEXTURES。我仍在使用整数 i_texindex 来索引 fs_textures。如果我遍历 fs_textures,无论我加载多少纹理,只有前半部分纹理有效(50 个纹理,只有 25 个出现)。另一半似乎被 Linux 图形调试器所说的被称为“左前颜色”或“左后颜色”的可绘制对象所覆盖。我已经确认正确加载了完整的纹理数组。我被这个难住了!你以前见过这个吗?
    • 想通了!再次感谢您的帮助!
    • 当你谈到无绑定统一表达式时,我有点困惑。您说我无法选择每个四边形将具有哪种纹理 - 这意味着 - 每个四边形都必须使用相同的纹理。如果是这样,拥有ALL_TEXTURES 有什么意义?
    • @CygnusX1:这样您就可以在不绑定纹理的情况下进行渲染。因此,术语“无约束”。这不是“永远不会改变状态”或“在一次绘制调用中渲染所有内容”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多