OpenGL Bindless Textures:绑定到统一的sampler2D数组

时间:2016-11-29 20:52:16

标签: opengl glsl textures

我正在研究使用无绑定纹理来快速显示一系列图像。我的参考是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统一属性?另外,我应该使用什么来更新顶点属性&#39; texindex&#39; - 我的纹理句柄数组或纹理句柄的实际索引?

1 个答案:

答案 0 :(得分:8)

无绑定纹理。你没有&#34;绑定&#34;这样的纹理到任何东西。

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.您只需要使用实际纹理句柄填充数组。

  

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

好吧,两个人都不会工作。不是你写的方式。

请参阅,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索引。