使用具有多个采样器制服的单个纹理图像单元

时间:2013-10-20 02:11:27

标签: opengl glsl opengl-3

我正在编写一个跟踪当前绑定纹理的批处理系统,以避免不必要的glBindTexture()调用。我不确定是否需要跟踪特定批次已经使用了哪些纹理,这样如果纹理被使用了两次,它将被绑定到需要它的第二个采样器的不同TIU。 / p>

OpenGL应用程序是否可以在同一着色器阶段为多个采样器使用相同的纹理图像单元?那些不同着色器阶段的采样器呢?例如:

片段着色器:

...
uniform sampler2D samp1;
uniform sampler2D samp2;

void main() { ... }

主程序:

...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glUniform1i(samp1_location, 0);
glUniform1i(samp2_location, 0);
...

我没有看到为什么这不起作用的原因,但是如果着色器程序还包含这样的顶点着色器呢:

顶点着色器:

...
uniform sampler2D samp1;

void main() { ... }

在这种情况下,OpenGL应该将samp1的两个实例视为引用相同的位置。因此,在顶点和片段着色器中使用相同的纹理单元。我已经读过在两个不同的着色器阶段使用相同的纹理对GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS进行双重计算,但这似乎与此相矛盾。

在我的硬件(HD 6870)上进行快速测试时,以下所有方案均按预期工作:

  • 1 TIU用于同一着色器阶段的2个采样器制服
  • 1 TIU用于1个采样器制服,用于2个着色器阶段
  • 1 TIU用于2个采样器制服,每个制服发生在不同的阶段。

但是,我不知道这是否是我应该对所有硬件/驱动程序产生的行为,或者是否存在性能影响。

1 个答案:

答案 0 :(得分:4)

希望这会清除你的一些困惑,我使用了旧版本的规范。为简单起见,较新版本还有两个附加阶段(曲面细分控制/评估),因此讨论稍微复杂一些。

OpenGL 3.3 (Core Profile) - 2.11。顶点着色器 - 第80页

  

纹理访问

     
    

着色器可以查找纹理贴图。顶点,几何或片段着色器可用的纹理图像单元的最大数量分别是依赖于实现的常量GL_MAX_VERTEX_TEXTURE_IMAGE_UNITSGL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITSGL_MAX_TEXTURE_IMAGE_UNITS的值。顶点着色器,几何着色器和片段着色器组合使用的GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS纹理图像单元的值不能超过GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS。如果顶点着色器,几何着色器和片段处理阶段中的多个访问相同的纹理图像单元,则每个此类访问将分别针对texture (sampler, coords)限制进行计数。

  

根据每个阶段使用的独特采样器数量施加限制。两个具有不同名称但引用相同纹理单元的采样器制服在使用确定方面实际上是相同的。用法指的是执行类似GL_MAX_..._IMAGE_UNITS的操作,如果这不是很明显的话。仅仅声明一个采样器并为其赋值不会让您更接近实现定义的限制,您实际上必须在运行时 使用 采样器并且如果它与同一阶段中另一个使用过的采样器具有相同的值,则不计算在内。

至于多次使用相同的纹理对象,这不是{{1}}限制的全部内容。您可以将相同的纹理绑定到所有48个纹理单元(GL3.3中的最低实现要求 - 这有效地要求每个阶段至少16个纹理)如果您愿意,此限制是指您使用的不同采样器的数量(再次,请参阅在着色器阶段。实际上,您可能希望将相同的纹理绑定到多个纹理单元,如果您需要使用最近邻居过滤一次,另一次使用线性或不同的包裹状态。

如果您想知道所有驱动程序/硬件的行为,请始终参考正式的OpenGL规范。我为您挑选了相关信息,但是如果您将来了解如何搜索重要细节,那将会很好。自OpenGL 1.0以来的每个规范都可以从http://www.opengl.org/registry/免费获得。