OpenGL无绑定纹理:绑定到统一的sampler2D数组 [英] OpenGL Bindless Textures: Bind to uniform sampler2D array

查看:699
本文介绍了OpenGL无绑定纹理:绑定到统一的sampler2D数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究使用无约束纹理来快速显示一系列图像.我的参考是OpenGL 4.5红皮书.这本书说我可以使用此片段着色器在着色器中采样无约束纹理:

I am looking into using bindless textures to rapidly display a series of images. My reference is the OpenGL 4.5 redbook. The book says I can sample bindless textures in a shader with this fragment shader:

#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);
};

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

I created a vertex shader that looks like this:

#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);
};

您可能会注意到,我对正在发生的事情的掌握有些薄弱.

As you may notice, my grasp of whats going on is a little weak.

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

In my OpenGL code, I create a bunch of textures, get their handles, and make them resident. The function I am using to get the texture handles is 'glGetTextureHandleARB'. There is another function that could be used instead, 'glGetTextureSamplerHandleARB' where I can pass in a sampler location. Here is what I did:

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'-指向纹理句柄数组或纹理句柄的实际索引?

My question is how do I bind my texture handles to the ALL_TEXTURES uniform attribute of the fragment shader? Also, what should I use to update the vertex attribute 'texindex' - an actual index into my texture handle array or a texture handle?

推荐答案

这是 bindless 纹理.您不会将这样的纹理绑定"到任何东西.

It's bindless texturing. You do not "bind" such textures to anything.

无边纹理中,采样器的数据值为数字.具体来说,是glGetTextureHandleARB返回的数字.纹理句柄是64位无符号整数.

In bindless texturing, the data value of a sampler is a number. Specifically, the number returned by glGetTextureHandleARB. Texture handles are 64-bit unsigned integer.

在着色器中,sampler的值在缓冲区支持的接口块中键入(UBO和SSBO)是64位无符号整数.因此,采样器数组的结构等效于64位无符号整数的数组.

In a shader, values of sampler types in buffer-backed interface blocks (UBOs and SSBOs) are 64-bit unsigned integers. So an array of samplers is equivalent in structure to an array of 64-bit unsigned integers.

因此在C ++中,等效于ALL_TEXTURES块的结构为:

So in C++, a struct equivalent to your ALL_TEXTURES block would be:

struct AllTextures
{
    GLuint64 textures[200];
};

当然,假设您正确使用了std140布局.否则,您将不得不查询结构的布局.

Well, assuming you properly use std140 layout, of course. Otherwise, you'd have to query the layout of the structure.

在这一点上,您将缓冲区与其他UBO用法一样对待.通过将AllTextures粘贴到缓冲区对象中,为着色器构建数据,然后将该缓冲区作为UBO绑定到绑定0.您只需要在数组中填充实际的纹理手柄即可.

At this point, you treat the buffer as no different from any other UBO usage. Build the data for the shader by sticking an AllTextures into a buffer object, then bind that buffer as a UBO to binding 0. You just need to fill the array in with the actual texture handles.

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

Also, what should I use to update the vertex attribute 'texindex' - an actual index into my texture handle array or a texture handle?

好吧,没人能工作.不是你写的方式.

Well, neither one will work. Not the way you've written it.

请参见 ARB_bindless_texture 不允许您访问任何纹理您可以随时以任何方式通过任何着色器调用进行操作.除非您使用NV_gpu_shader5,否则导致纹理访问的代码必须基于动态统一表达式

See, 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.

因此,除非渲染命令中的每个顶点都具有相同的索引或句柄...否则,不能使用它们来选择要使用的纹理.即使实例化也无法挽救您,因为动态统一表达式并不关心实例化.

So unless every vertex in your rendering command gets the same index or handle... you cannot use them to pick which texture to use. Even instancing will not save you, since dynamically uniform expressions don't care about instancing.

如果要渲染一堆四边形而不必更改它们之间的统一性(并且不必依赖NVIDIA扩展),那么您可以选择几种方法.大多数支持无边界纹理的硬件还支持 ARB_shader_draw_parameters .这使您可以访问gl_DrawID,它表示渲染命令中的当前索引. glMultiDraw样式的命令.该扩展名明确声明gl_DrawID是动态统一的.

If you want to render a bunch of quads without having to change uniforms between them (and without having to rely on an NVIDIA extension), then you have a few options. Most hardware that supports bindless texture also supports 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. And that extension explicitly declares that gl_DrawID is dynamically uniform.

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

So you could use that to select which texture to render. You simply need to issue a multi-draw command where you render the same mesh data over and over, but it gets a different gl_DrawID index in each case.

这篇关于OpenGL无绑定纹理:绑定到统一的sampler2D数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆