首页 > 解决方案 > 假设未设置的 sampler2D 制服将读取纹理单元 0 是否安全?

问题描述

我有多个纹理,其中一个在绘制之前绑定到 TEXTURE0。

在我的片段着色器中,我有一个 sampler2D 制服,例如:

uniform sampler2D diffuse;

我曾经在每帧、每个着色器中调用 uniform1f([uniform location], 0) 来明确设置统一读取纹理单元为零,但是在删除这些调用后,我的应用程序仍然可以在我测试的 Linux、Windows 和 Mac 系统上运行. 这不是不设置制服是安全的确凿证据,因此问题是:假设未设置的 sampler2D 制服将读取纹理单元 0 是否安全?

删除 uniform1f 调用的动机是减少绘制调用,这在使用 webassembly 时尤其昂贵,因为调用 javascript 会产生额外的开销。

除了仅在 opengl 4(而不是 WebGL 2)中支持的用户可设置默认值之外,我没有在规范中看到任何提及默认值的内容。我应该注意到更改后控制台中没有错误。

标签: glslwebgl2

解决方案


假设未设置的 sampler2D 制服将读取纹理单元 0 是否安全?

是的,它是安全的。

WebGL 和 WebGL2 中的 Uniforms 默认为 0

规范部分 2.12.16

当程序成功链接时,属于程序对象的默认统一块的所有活动统一被初始化:浮点统一为 0.0,整数统一为 0,布尔统一为 FALSE

在浏览器中针对不良驱动程序的一致性测试变通方法中对此进行了测试。

虽然我们在它的属性默认为 0, 0, 0, 1。

第 2.8 节

所有通用顶点属性的初始值为 (0.0, 0.0, 0.0, 1.0)。

自 2011 年 WebGL 发布以来,我在几乎所有我编写的程序中都使用了这两个功能,并继续在 WebGL2 中使用

至于减少 WebGL 调用,不将 uniform 设置为 0 似乎不太可能成为高性能和非高性能之间的区别。如果 CPU 是您的瓶颈(许多基于 GPU 的程序,GPU 本身就是瓶颈)并且如果瓶颈在于对 WebGL 的调用,那么您可以做的事情

  • 不要在渲染时做任何你可以在初始化时做的事情。例如,在初始化时查找统一位置。

  • 不要在渲染时更改属性,在初始化时设置顶点数组对象。

  • 如果不需要,请不要使用采样器对象。在 WebGL2/OpenGL ES 3.0 之前,成千上万的应用程序都没有使用它们,因为它们不存在

  • 使用统一的缓冲区对象。理想情况下,您可能希望将统一缓冲区对象拆分成组,例如 (1) 所有着色器之间共享的东西,例如视图、投影、viewProjection 矩阵、任何相机信息等。 (2) 由许多对象共享的东西,例如灯光和材质设置(3) 对象特定的事物。对于每个模型不改变的东西,这意味着您可以通过每个统一缓冲区对象的 1 个 webgl 调用来设置它们。

  • 考虑批处理解决方案,例如实例化绘图基于纹理的批处理


推荐阅读