当前位置: 首页 > 知识库问答 >
问题:

统一块中的数组不能用顶点属性索引,对吗?

王宏深
2023-03-14

我想知道我是否可以用我绘制的顶点中包含的值索引到一个统一的缓冲区数组中,比如:

layout (location = 0) in vec3 position;
layout (location = 1) in flat int idx;

layout(binding = 0, std140) uniform uniformValues
    {
        float values[100];
};

void main() 
{
     values[idx];
}

我的理解是这是不可能的因为

'in flat int idx'

很可能不是'动态统一表达式',并且根据留档不能用于索引到统一缓冲区数组中:

在某些地方,GLSL要求表达式是动态统一的。以下所有内容都必须使用动态统一的表达式:

-The index to buffer-backed interface block arrays.

然而,我遇到了来自同一个来源的信息,关于如何访问一系列拥有“无绑定纹理”纹理手柄的采样器,它说(我的重点是):

默认块统一变量中使用的采样器和图像类型可以从句柄而不是绑定点的索引中填充。这些类型现在也可以作为着色器阶段输入/输出传递(在需要时使用平面插值限定符)。它们可以用作顶点属性,在OpenGL端将它们视为64位整数。它们可以用于各种接口块;缓冲区支持的接口块将它们视为64位整数。

我相信这是在说,与其这样做:

layout (location = 0) in flat int textureBinding;

layout (binding = 0) uniform sampler2D textures[16];

void main()
{
     textures[textureBinding];
}

你可以这样做:

layout (location = 0) in flat int bindlessTextureHandle;

layout (binding = 0) uniform textureBuffer 
{
      sampler2D textures[200];
}

void main()
{
     textures[bindlessTextureHandle];
}

“bindlessTextureHandle”不是“动态统一表达式”,如何将其用于索引到统一缓冲区中?

以下所有内容都必须使用动态统一表达式

-The index to buffer-backed interface block arrays.

那么为什么它说你可以用顶点输入的值索引到各种“接口块”中呢?

您还可以索引到:

'uniform sampler2D[16] textures;'

使用“非动态统一表达式”?

共有2个答案

经和洽
2023-03-14

这里有无数独立、重叠的问题。

在统一块中对数组进行索引从来都不限于动态统一表达式(一般情况下,请参见下文)。即使是在GL 3中。x、 可以使用任意索引在缓冲区支持的块中为数组编制索引。

然而,你并不是在问一般数组;你问的是纹理阵列。或者更一般地说,通过无绑定纹理计算采样器类型的整个操作序列。

整个序列必须是动态统一的(除非您使用的是NVIDIA,它允许任意表达式)。无论是索引SSBO数组、使用输入变量直接传递纹理句柄,还是其他任何操作,这都无关紧要。导致获取采样器类型的值必须是动态统一的。

那么为什么它说你可以用顶点输入的值索引到各种“接口块”中呢?

因为你可以。

对“动态均匀”的一个常见误解是它是一个静态属性。表达式本身要么是动态均匀的,要么不是。这接近正确,但实际上并不正确。

有些表达式本质上是动态均匀的。您可以称这些为“静态动态均匀”表达式。例如,常量表达式总是动态均匀的。

然而,动态一致性与表达式的值有关。所有调用(在rendering命令中)必须产生相同的值。着色器阶段的in变量可以是动态统一的,只要它恰好在渲染命令中始终具有相同的值。例如,VS可以使用gl_DrawID(动态统一)从uniform数组中访问一个值,将其作为中的传递给FS,FS可以将该值用作采样器。或者访问一系列采样器。或者别的什么。在draw命令中,所有FS调用将获得相同的值,因此该值在动态上是一致的。

云韬
2023-03-14

我的理解是这是不可能的因为

in flat int idx

很可能不是'动态统一表达式',并且根据留档不能用于索引到统一缓冲区数组中。

您是对的,您需要一个动态统一的值来索引到统一的缓冲区数组中。然而,这:

layout(binding = 0, std140) uniform uniformValues
{
        float values[100];
};

不是一个统一的缓冲区数组。这是单个统一缓冲区对象中的一个数组,可以根据需要将非统一值索引到该数组中。统一的缓冲区阵列应该是:

 layout(binding = 0, std140) uniform myUBO
 {
         float value;
 } myUBOArray[4];

你剩下的问题变得更加模糊。有时您会引用“缓冲区支持的接口块数组的索引”,而您的代码从未使用过该索引。这是关于SSBO的,它使用layout(…)形式的接口块缓冲区foo{…}

那么为什么它说你可以用顶点输入的值索引到各种“接口块”中呢?

因为事实就是这样。您只需要理解,索引到一个接口块数组中与索引其他数组不同(可能在接口块内部定义,也可能不在接口块内部定义,这无关紧要)。

您还可以索引到:

uniform sampler2D[16] textures; with a 'non-dynamically uniform expression'?

不,不在标准GL中。

关于无绑定纹理的第一件事是,这不是迄今为止发布的任何OpenGL版本(在撰写本文时是4.6)的核心功能。它仅定义为一些现代GPU和驱动程序公开的扩展GL_ARB_bindless_纹理,但该功能的可用性远未普及。

第二,上面的扩展规范解释道:“传递给纹理内置函数的采样器和图像句柄必须是动态统一的”,所以它仍然无法实现这一点。但是,扩展名GL_NV_gpu_shader5删除了该限制。因此,在最近的NVIDIA GPU上,你可以将一个非动态统一的索引放入一系列无绑定纹理采样器中——但如果你这样做,性能仍然会受到很大影响。

 类似资料:
  • 通过几何体BufferGeometry的顶点索引属性BufferGeometry.index可以设置几何体顶点索引数据,如果你有WebGL基础很容易理解顶点索引的概念,如果没有也没有关系,下面会通过一个简单的例子形象说明。 比如绘制一个矩形网格模型,至少需要两个三角形拼接而成,两个三角形,每个三角形有三个顶点,也就是说需要定义6个顶点位置数据。对于矩形网格模型而言,两个三角形有两个顶点位置是重合的

  • 我是Java编程的新手,我正在使用数组。在数组中,索引必须是整数,它不允许浮点数或双精度型,所以我使用了长数据类型作为索引,它给出了错误。然而,当我使用字节和短整型和Int时,它的工作原理。我想知道,因为错误是“从多头到int的可能有损转换”,是否只允许在索引中使用int,并且由于字节和短小,这就是为什么它起作用(自动升级)并且long大于int,所以它给出了错误(没有自动取消)请帮助

  • 我正在努力理解这两个,如何使用它们,以及它们是如何联系的。假设我想创建一个简单的地形和一个有纹理的立方体。对于这两个对象,我有三角形、顶点的数组,对于立方体,我有一个包含纹理数据的数组。我的问题是:我如何使用VAOs和VBOs来创建和呈现这两个? null

  • 我需要索引到2个均匀采样的数组中。索引是每帧动态的。也就是说,我有一个动态统一缓冲区,它为片段着色器提供索引。我使用Vulkan API 1.2。在设备功能列表中,我有: 我不确定100%,但看起来这个功能是1.2中的核心。尽管如此,我确实尝试在设备创建期间启用它,如下所示: 然后插入设备创建: 在着色器中,它如下所示: 我得到的是一些奇怪颜色的图像像素组合。如果我改为固定索引,它会正常工作<代码

  • 上一节课绘制的一个案例是线框立方体,不知大家是否注意到,立方体有8个顶点,但是数组列举顶点的时候,因为绘制直线的时候一个点是三条直线公用, 如果绘制函数gl.drawArrays()绘制模式mode使用gl.LINES模式,每绘制一条直线就需要定义两个顶点。在这种情况下一个点可能在顶点数组中多次列举出来,造成数据重复, 这时候要解决数据的复用,大家应该会想到数据库、索引等概念,也就是说把立方体的8

  • 我提出的问题与您在这里看到的几乎相同,但有一个约束条件,即必须使用groovy而不是java语法。理想情况下,答案应该非常简洁。 我有一个简单的人顶点图。每个人都有一个“年龄”属性,列出该人的年龄(以年为单位)。还有“worksFor”标记的边连接成对的人顶点。我希望看到所有边缘,边缘两端的人都具有相同的年龄属性。 然后我想问一个类似的问题,两个年龄相差不到3年。 如前所述,这应该是groovy语