【问题标题】:'glDrawArrays: attempt to access out of range vertices in attribute 1' on Emscripten/OpenGL code (works in native C++) [closed]“glDrawArrays:尝试访问 Emscripten/OpenGL 代码中属性 1 中超出范围的顶点”(在本机 C++ 中工作)[关闭]
【发布时间】:2017-04-09 18:00:45
【问题描述】:

我已将问题范围缩小到此。我有两个属性指向完全相同的数据。在本机 C++ 中构建时,这可以正常工作。但是,当使用 emscripten 构建时,javascript 控制台会在每一帧上显示以下错误:

'glDrawArrays: attempt to access out of range vertices in attribute 1'

当我注释掉“glEnableVertexAttribArray”行以启用第二个属性时,我没有收到此错误。

下面是我的代码。我将从创建数据缓冲区开始:

GLfloat rectangleData[] =
{
    -.5f, -.5f,     0,1,
    -.5f, .5f,      0,0,
    .5f, .5f,       1,0,
    .5f, -.5f,      1,1,
    -.5f, -.5f,     0,1
};
glGenBuffers(1, &rectangleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, rectangleBuffer);
glBufferData(
        GL_ARRAY_BUFFER, sizeof(rectangleData),
        rectangleData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

这是我的纹理四边形绘图代码的相关摘录:

glBindBuffer(GL_ARRAY_BUFFER, rectangleBuffer);

int vertexPosition = Shader::getParameterInfo("vertexPosition")->id;
glVertexAttribPointer(
        vertexPosition, 2, GL_FLOAT,
        GL_FALSE, 16, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vertexPosition);

int vertexTexCoord = Shader::getParameterInfo("vertexTexCoord")->id;
glVertexAttribPointer(
        vertexTexCoord, 2, GL_FLOAT,
        GL_FALSE, 16, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vertexTexCoord);

glDrawArrays(GL_TRIANGLE_FAN, 0, 5);

请注意,我已将第二个属性调整为指向与第一个相同的数据(以降低调试时的复杂性)。我在这里很困惑,真的可以使用新鲜/经验丰富的视角。

编辑:这是BUFFER_OFFSET 的样子:

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

来源:How to cast int to const GLvoid*?

编辑:对于它的价值,这里是等效的 Emscripten 生成的 JS 代码。如果需要,我会发布此引用的任何 JS 代码。

dest=$rectangleData; src=2328; stop=dest+80|0; do {
HEAP32[dest>>2]=HEAP32[src>>2]|0; dest=dest+4|0; src=src+4|0; } while
((dest|0) < (stop|0));
 _glGenBuffers(1,(2300|0));
 $30 = HEAP32[2300>>2]|0;
 _glBindBuffer(34962,($30|0));
 _glBufferData(34962,80,($rectangleData|0),35044);
 _glBindBuffer(34962,0);

$11 = HEAP32[2300>>2]|0;
 _glBindBuffer(34962,($11|0));
 $12 = (__ZN8platform6Shader16getParameterInfoEPKc(17356)|0);
 $13 = HEAP32[$12>>2]|0;
 $vertexPosition = $13;
 $14 = $vertexPosition;
 _glVertexAttribPointer(($14|0),2,5126,0,16,(0|0));
 $15 = $vertexPosition;
 _glEnableVertexAttribArray(($15|0));
 $16 = (__ZN8platform6Shader16getParameterInfoEPKc(17379)|0);
 $17 = HEAP32[$16>>2]|0;
 $vertexTexCoord = $17;
 $18 = $vertexTexCoord;
 _glVertexAttribPointer(($18|0),2,5126,0,16,(0|0));
 $19 = $vertexTexCoord;
 _glEnableVertexAttribArray(($19|0));
 _glDrawArrays(6,0,5);

编辑:更好的是,我将提供在 github 上运行的 JS 代码和 C++ 代码的链接(它在“drawImage()”的底部附近):

https://rawgit.com/jon-heard/Native-WebGL-framework/c134e35ac94fdf3243a9662353ad2227f8c84b43/Native-WebGL-framework/web/index.html

https://github.com/jon-heard/Native-WebGL-framework/blob/c134e35ac94fdf3243a9662353ad2227f8c84b43/Native-WebGL-framework/src/platform/draw.cpp

【问题讨论】:

  • 几个问题。 sizeof(rectangleBuffer) 确实是 20 * sizeof(GLfloat) 而不是指针的大小? BUFFER_OFFSET 是做什么的?
  • @KirillDmitrenko:如果 OP 就是这样写的,那么是的,sizeof(rectangleData) 将评估数组的总大小(如果数组作为函数参数或指针传递,它将不起作用退化。
  • 对应的javascript代码长什么样? C++ 看起来是正确的。

标签: opengl webgl texture-mapping emscripten


【解决方案1】:

错误实际上来自不同的地方,从drawCircle函数形成一个draw call。从外观上看,您忘记禁用未使用的属性数组。 Here 您只使用了一个属性,该属性绑定到 0,但错误是针对属性 1。显然,您在某处为属性 1 启用了顶点数组而忘记禁用它。现在draw call验证它的绑定,发现它不正确并出现GL_INVALID_OPERATION错误。 The spec says 应该只对当前程序中使用的属性执行越界检查,但从外观上看,at least Chromium 只是检查所有启用数组的属性。

UPD。我误解了 Chromium 的代码。正如@gman 所指出的,它确实只检查当前程序使用的属性的越界访问。

【讨论】:

  • 这很棒。谢谢基里尔!我想这需要一些 JS 调试才能查明。感谢您的努力,并将记住该选项以供将来调试。 JS 代码看起来很糟糕,但与 C++ 源代码相似,所以它可能没有看起来那么糟糕。
  • 解决方案:作为记录,我通过在每次绘制调用完成后对每个属性调用 glDisableVertexAttribArray() 来解决此问题。这里的教训是 webgl,或者至少是 emscripten,目前需要这个额外的步骤。
  • @JonathanHeard 您也可以使用vertex array objects 扩展(如果可用)
  • Chromium 不检查未使用的属性。在一致性测试中对此进行了测试。 Example。 WebGL 也确实 NOT 需要禁用未使用的属性。它从来没有
  • 至于顶点数组对象here's a polyfill that just works。当然,在本机不支持顶点数组对象的机器上的任何用户可能也在一台机器上,这对于任何真正需要顶点数组对象的 webgl 来说都太慢了。
【解决方案2】:

问题是您有一个总是使用 2 个属性

的顶点着色器

var gl = document.createElement("canvas").getContext("webgl");
var program = twgl.createProgramFromScripts(gl, ["vs", "fs"]);

log("list of used attributes");
log("-----------------------");

var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var ii = 0; ii < numAttribs; ++ii) {
  var attribInfo = gl.getActiveAttrib(program, ii);
  if (!attribInfo) {
    break;
  }
  log(gl.getAttribLocation(program, attribInfo.name), attribInfo.name);
}

function log(...args) {
   var div = document.createElement("div");
   div.textContent = [...args].join(" ");
   document.body.appendChild(div);
}
<script src="https://twgljs.org/dist/2.x/twgl.min.js"></script>
<script type="foo" id="vs">
uniform mat4 sceneTransform;
uniform mat4 rotationTransform;
uniform vec2 objectPosition;
uniform vec2 objectScale;
attribute vec2 vertexPosition;
attribute vec2 vertexTexCoord;
varying vec2 UVs;
void main()
{
  UVs = vertexTexCoord;
  gl_Position = 
    sceneTransform *
    vec4( vertexPosition * objectScale + objectPosition, 0, 1);
}
</script>
<script type="foo" id="fs">
precision mediump float;

uniform vec3 objectColor;
uniform float objectOpacity;

void main()
{
	gl_FragColor = vec4(objectColor, objectOpacity);
}
</script>

当您调用 drawCircle 时,您将这两个属性都分配给缓冲区,然后在上面的代码中,如果您不对第二个属性做任何事情,它仍然指向前一个缓冲区。该缓冲区对于您的绘图调用来说太小了,您会收到错误。

WebGL 不会抱怨未使用的属性,但会抱怨已使用的属性。您应该始终提供着色器所需的属性。

在您的情况下,您至少有 2 个选项

  1. 改变你的代码,让你的着色器只使用一个属性

    如果我正确阅读了代码,那么您只有一个顶点着色器。对于那些片段着色器不使用纹理坐标的情况,请使用不提供它们的不同顶点着色器。

  2. 禁用属性,使其使用常量值

    gl.disableVertexAttribArray(...)
    

    表示该属性将使用由提供的常量值

    gl.vertexAttribXXX
    

1 可以说比 2 好,因为您的顶点着色器不会浪费时间从属性中读取并将其复制到一个变量中而不是在片段着色器中使用它。

【讨论】:

  • 啊,是的。这很有意义。我将一个顶点着色器用于双属性渲染和单属性渲染。回到单属性渲染时,它保持顶点属性绑定。我会考虑根据情况调整我的代码以使用不同的顶点着色器。
【解决方案3】:

我在尝试重新创建 this 时看到了这个错误并犯了一个错误。教程代码可以在here找到。但是,我得到了这个错误,因为我在位置缓冲区中设置数据之后定义了颜色缓冲区。我通过定义颜色缓冲区来修复它,然后定义位置缓冲区并将数据绑定到缓冲区。那成功了。所以总而言之,如果我们不按顺序定义属性,就会出现这个错误。

【讨论】:

    【解决方案4】:

    我遇到了这个错误,因为我传递给着色器的 vec2 属性不包含每个顶点的数据...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 2014-02-07
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多