WebGL的enableVertexAttribArray是不是必须成对出现disableVertexAttribArray?

Number of views 143

我不太清楚顶点属性数组影响的范围。我有几个不太相同的着色器程序与不同数量的顶点属性。当我调用glEnableVertexAttribArray时它影响的是全局么?比如我调用glEnableVertexAttribArray后就不会通过glDisableVertexAttribArray再去禁用它们,这么做貌似是可以正常运行的,但似乎我可能应该在绘制调用之前或其中的某个阶段禁用它们?这有什么影响吗?(我的运行环境是WebGL,所以在Webgl中对应的应该是gl.enableVertexAttribArray和gl.disableVertexAttribArray)。

1 Answers

gl.enableVertexAttribArraygl.disableVertexAttribArray 的使用取决于你的需求以及你的渲染流程。

  1. 作用范围:这些函数的作用范围是当前绑定的顶点数组对象(VBO)。如果你没有显式地创建和绑定 VAO,那么这些设置将应用于默认的 VAO。每次你更改顶点属性的状态(启用/禁用、指定缓冲区等)时,这些状态都将被记住,直到被改变为止。

  2. 是否必须成对出现:从技术上讲,你不需要显式地调用 gl.disableVertexAttribArray 来禁用它们。然而,这样做可以确保在某些情况下不会意外地保留不必要的状态,从而导致性能问题或渲染错误。

  3. 为什么需要禁用

    • 减少不必要的计算:如果某些顶点属性数组没有被使用,但仍然处于启用状态,可能会导致不必要的计算。
    • 避免潜在的冲突:如果你的渲染流程中切换不同的着色器程序,并且这些着色器程序期望不同的顶点属性配置,那么不正确的状态可能导致渲染错误。
  4. 最佳实践

    • 在每次使用新的着色器程序前,最好重置所有顶点属性的状态,以确保它们符合当前着色器的需求。
    • 你可以考虑在每个绘制调用之前启用必要的顶点属性数组,并在绘制调用之后禁用它们。虽然这不是绝对必要,但它可以帮助避免潜在的问题。

示例代码:

function draw() {
    // 启用必要的顶点属性数组
    gl.enableVertexAttribArray(positionLocation);
    gl.enableVertexAttribArray(colorLocation);

    // 绑定和配置顶点缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.vertexAttribPointer(colorLocation, 3, gl.FLOAT, false, 0, 0);

    // 绘制
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // 禁用顶点属性数组(可选)
    gl.disableVertexAttribArray(positionLocation);
    gl.disableVertexAttribArray(colorLocation);
}

总之,虽然不是强制性的,但在许多情况下显式地启用和禁用顶点属性数组是一种良好的做法,可以提高代码的健壮性和可维护性。