WebGL 警告:“属性 0 已禁用。这会显着降低性能”

Posted

技术标签:

【中文标题】WebGL 警告:“属性 0 已禁用。这会显着降低性能”【英文标题】:WebGL warning: "Attribute 0 is disabled. This has significant performance penalty" 【发布时间】:2013-12-16 19:11:26 【问题描述】:

当我运行下面的 javascript/WebGL 代码时(请向下滚动),我在开发控制台中看到以下警告消息:

[.WebGLRenderingContext]
PERFORMANCE WARNING: Attribute 0 is disabled.
This has significant performance penalty

下面的代码成功地在画布上绘制了一个白点。但是,我希望警告消失。我需要在下面的代码中进行哪些更改才能使其停止出现?

html

<!DOCTYPE html>
<html>
<body>
  <canvas id="canvas"  ></canvas>
</body>
</html>

JavaScript:

var
    VERTEX_SHADER_SOURCE = ""+
      "void main() "+
      "  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);"+
      "  gl_PointSize = 10.0;"+
      "",

    FRAGMENT_SHADER_SOURCE = ""+
      "void main() "+
      "  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"+
      "",

    canvas = document.getElementById('canvas'),
    gl = canvas.getContext('webgl'),

    vertexShader = gl.createShader(gl.VERTEX_SHADER),
    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER),

    shaderProgram = gl.createProgram();

// Compile the shaders.
gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);
gl.compileShader(vertexShader);
gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);
gl.compileShader(fragmentShader);

// Create linked program.
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);    

// Clear the canvas.
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Draw the point.
gl.drawArrays(gl.POINTS, 0, 1);

这是一个最小但完整的示例,因此我正在寻找一个可以明确告诉我要更改哪些内容的答案。 Here is a JSFiddle of the case。我在 Chrome 30.0.1599.101(在 OS X 10.8.5 上)中运行它。

【问题讨论】:

要对 webgl 做任何有用的事情,您最终会想要获取属性位置并使用它们(发送顶点、颜色等)。然后警告可能会消失。 【参考方案1】:

这个问题和你的类似:

Getting 'PERFORMANCE WARNING' messages in Chrome

也许会有所帮助。

【讨论】:

谢谢。我遇到了这个问题,但还不够清楚,我无法理解如何将其具体应用于我的案例。 (我希望有一个与库无关的解决方案,但适用于那些尝试直接使用 WebGL 的人。)【参考方案2】:

OpenGL 需要启用属性零,否则它不会渲染任何东西。另一方面,WebGL 所基于的 OpenGL ES 2.0 没有。因此,如果您不启用属性 0,要在 OpenGL 之上模拟 OpenGL ES 2.0,浏览器必须为您创建一个足够大的缓冲区以容纳您请求绘制的顶点数量,并用正确的值填充它(请参阅gl.vertexAttrib),将其附加到属性零并启用它。

它在幕后完成所有这些工作,但重要的是您要知道创建和填充该缓冲区需要时间。浏览器可以进行一些优化,但在一般情况下,如果您假设您在 OpenGL ES 2.0 上运行并使用属性零作为常量,就像您应该能够做的那样,没有警告您将没有浏览器为您模拟 OpenGL ES 2.0 与 OpenGL 不同的功能所做的工作。

在您的特定情况下,警告没有多大意义。看起来你只画了一个点。但是浏览器要弄清楚这一点并不容易,因此它只会在您绘制时警告您并且未启用属性 0。

【讨论】:

这确实有助于理解逻辑,但是,attribute 0 到底是什么,以及我们如何将其启用为某些默认值以免导致性能损失? 见@GladstoneKeep 的回答。最简单的方法是将position 属性绑定到属性0,因为99.99% 的着色器都有positionaPositiona_Position。你可以在链接你的程序之前调用gl.bindAttribLocation(program, 0, "position");来做到这一点 所以在我的演示程序中,我在顶点着色器中定义了attribute vec4 position,在我的js应用程序中,我有var vPosition = gl.getAttribLocation( program, "vPosition" );gl.vertexAttrib3f(vPosition, newPoints[i], newPoints[i + 1], 0.0);,我尝试在调用initShaders之后立即添加gl.bindAttribLocation(program, 0, "vPosition"); (在我打电话给gl.useProgram 之前)但警告仍然存在。 你必须在gl.createProgram之后和gl.linkProgram之前调用bindAttribLocation。 InitShaders 之后为时已晚【参考方案3】:

我已经设法让警告消失,使用此处其他回复中的线索。我将回答我自己的问题,因为我已经为上面提供的案例找到了具体的解决方案。

以下是我为消除警告所做的更改(一般而言):

    在顶点着色器中为位置创建一个属性变量。 创建缓冲区对象,将其绑定到数组缓冲区,并将顶点数据写入其中。 将属性变量绑定到位置0 将缓冲区对象分配给属性变量。 启用对属性变量的赋值。

这里是a diff of the specific changes,这里是a JSFiddle demonstrating the code working without the warning。


以防万一这些链接在未来某个时候失效,我在此处提供相关代码 sn-ps:

顶点着色器源应改为:

attribute vec4 a_Position;
void main() 
  gl_Position = a_Position;
  gl_PointSize = 10.0;

下面的 JavaScript 代码应该插入到gl.useProgram(shaderProgram) 行的正下方:

var vertices = new Float32Array([0.0, 0.0, 0.0]),
    vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.bindAttribLocation(shaderProgram, 0, 'a_Position');
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);

【讨论】:

【参考方案4】:

我最近遇到了同样的问题,并通过显式绑定属性 0 解决了它,但是我的印象是您的解决方案不应该工作。

取自 gl.bindAttribLocation 手册页:

属性变量名称到通用属性索引的绑定 程序对象可以随时通过调用显式分配 glBindAttribLocation。属性绑定直到 glLinkProgram 被调用。链接程序对象后 成功地,通用属性的索引值保持固定 (并且可以查询它们的值)直到下一个链接命令发生。

这详细说明了绑定在链接着色器程序之后才会生效。

指出这一点也可能有用

未显式绑定的活动属性将由 调用 glLinkProgram 时的链接器。

根据经验,它们似乎没有按特定顺序绑定,因此这通常是属性 0 可以禁用的原因(在我的情况下,假设顶点着色器中的第一个用户定义属性将绑定到属性 0 )。

【讨论】:

我在上面的演示 (JSFiddle) 中包含了一个链接,其中包含完整的修改代码,它可以在不引发警告的情况下运行。 (至少在 Mac OS X / Chrome 中。)它不适合你吗? 是的,它工作正常我只是不明白如何哈哈,而且它在我的代码中对我不起作用。老实说,我只是发布了这个答案来添加一些额外的信息,希望它可以在未来帮助人们。

以上是关于WebGL 警告:“属性 0 已禁用。这会显着降低性能”的主要内容,如果未能解决你的问题,请参考以下文章

警告:“太多活动的 WebGL 上下文。最旧的上下文将丢失”(WebGLRenderer.js)

WebGL 警告:texImage:Alpha-premult 和 y-flip 对于非 DOM 元素上传已弃用

清理 Threejs WebGl 上下文

unity发布webgl遇到的问题和解决办法

unity发布webgl遇到的问题和解决办法

glDrawElements:绘制的源纹理和目标纹理相同