具有可选属性的 GLSL 着色器

GLSL shader with optional attributes

我正在尝试创建一个 übershader 来表示一些波前数据,这些数据可能包含也可能不包含某些属性,例如:

  1. 一个或多个对象可能包含 uv 坐标和纹理
  2. 一个或多个对象可能包含每个顶点的法线贴图
  3. 一种或多种材质可能会使用不同的照明类型进行渲染,并且包含用于凹凸贴图的纹理

等等。

现在,为此创建一个 übershader 可能是也可能不是一个好主意(我正在试验),但我面临的问题是某些属性已指定而某些属性未指定(缺少制服,例如未设置的纹理采样器使用打开和关闭采样功能的布尔制服进行处理。

当一个属性 both 未分配(这意味着没有 glEnableVertexAttribArray,在 GLSL v 3.00 中会发生什么例如,但也没有缓冲区 bound/anything) 并且 未在 GLSL 程序中用于读取 (例如,我将使用统一 boolean 来关闭纹理查找,当缺少 UV 坐标时,虽然我可能仍会在顶点和片段着色器之间将坐标插入为 in/out,如下所示:

// Vertex shader
in vec3 vn;
out vec3 fvn;

[...]

fvn = vn;

...)?

这是对 glsl 的合法使用,还是我会遇到奇怪的兼容性问题(我正在为移动设备开发,正如 OpenGL ES3.0 标签所暗示的那样)?

我正在寻找第一手经验或权威来源,

谢谢!

始终指定属性。您可以选择是从数组中获取它们,还是使用当前值。

要使用数组中的数据,您可以调用:

glEnableVertexAttribArray(loc);

启用属性数组时,会从上次 glVertexAttribPointer() 调用时绑定为 GL_ARRAY_BUFFER 的缓冲区中获取属性。

要使用当前属性值,您调用:

glDisableVertexAttribArray(loc);

虽然禁用了属性数组,但用于属性的值由最后一次调用 glVertexAttrib4f() 或来自同一 glVertexAttrib*() 系列的另一个函数给出,默认值为 (0.0 , 0.0, 0.0, 1.0) 如果您从不调用任何这些函数。

所以拥有属性 "not specified" 不是问题,因为它从未真正未指定。唯一需要注意的是,在未使用 glVertexAttribPointer() 指定有效数组的情况下,不要启用属性数组。最安全的方法是为未使用的属性调用 glDisableVertexAttribArray()