OpenGL 无绑定纹理:绑定到统一的 sampler2D 数组
OpenGL Bindless Textures: Bind to uniform sampler2D array
我正在研究使用无绑定纹理来快速显示一系列图像。我的参考资料是 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 uniform 属性?另外,我应该使用什么来更新顶点属性 'texindex' - 我的纹理句柄数组或纹理句柄的实际索引?
它是无束缚纹理。你不要"bind"这样的纹理。
在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。您只需要用实际的纹理句柄填充数组。
Also, what should I use to update the vertex attribute 'texindex' - an actual index into my texture handle array or a texture handle?
好吧,两者都行不通。不是你写的那样。
见,ARB_bindless_texture does not allow you to access any texture you want in any way at any time from any shader invocation. Unless you are using NV_gpu_shader5, the code leading to the texture access must be based on dynamically uniform expressions。
所以除非渲染命令中的每个顶点都获得相同的索引或句柄...您不能使用它们来选择要使用的纹理。即使实例化也救不了你,因为动态统一表达式不关心实例化。
如果您想渲染一堆四边形而不必更改它们之间的制服(并且不必依赖 NVIDIA 扩展),那么您有几个选择。大多数支持无绑定纹理的硬件也支持 ARB_shader_draw_parameters. This gives you access to gl_DrawID
, which represents the current index of a rendering command within a glMultiDraw
-style command。该扩展明确声明 gl_DrawID
是动态统一的。
因此您可以使用它来 select 要渲染的纹理。您只需要发出一个多次绘制命令,在其中一遍又一遍地渲染相同的网格数据,但在每种情况下它都会获得不同的 gl_DrawID
索引。
我正在研究使用无绑定纹理来快速显示一系列图像。我的参考资料是 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 uniform 属性?另外,我应该使用什么来更新顶点属性 'texindex' - 我的纹理句柄数组或纹理句柄的实际索引?
它是无束缚纹理。你不要"bind"这样的纹理。
在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。您只需要用实际的纹理句柄填充数组。
Also, what should I use to update the vertex attribute 'texindex' - an actual index into my texture handle array or a texture handle?
好吧,两者都行不通。不是你写的那样。
见,ARB_bindless_texture does not allow you to access any texture you want in any way at any time from any shader invocation. Unless you are using NV_gpu_shader5, the code leading to the texture access must be based on dynamically uniform expressions。
所以除非渲染命令中的每个顶点都获得相同的索引或句柄...您不能使用它们来选择要使用的纹理。即使实例化也救不了你,因为动态统一表达式不关心实例化。
如果您想渲染一堆四边形而不必更改它们之间的制服(并且不必依赖 NVIDIA 扩展),那么您有几个选择。大多数支持无绑定纹理的硬件也支持 ARB_shader_draw_parameters. This gives you access to gl_DrawID
, which represents the current index of a rendering command within a glMultiDraw
-style command。该扩展明确声明 gl_DrawID
是动态统一的。
因此您可以使用它来 select 要渲染的纹理。您只需要发出一个多次绘制命令,在其中一遍又一遍地渲染相同的网格数据,但在每种情况下它都会获得不同的 gl_DrawID
索引。