WebGL GL_INVALID_OPERATION超出范围错误

时间:2019-05-04 17:08:07

标签: arrays webgl

全部。我是webgl的新手,但我检查了有关此错误的资源。我试图在我的圆旁边绘制一个正方形。在此之后,我为square和以此为基础来组织drawArrays。但是我收到此错误:

  

GL错误:GL_INVALID_OPERATION:glDrawArrays:尝试访问属性0中超出范围的顶点

也检查了我的界限和索引,但是这里的代码没有问题:

var vPosition,angle=10,j=1,xr=0.2,yr=0.2,rad;
var transformationMatrix, transformationMatrixLoc;

window.onload = function init()
{

canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );

if ( !gl ) { alert( "WebGL isn't available" ); }
gl.viewport( 0, 0, canvas.width, canvas.height );

gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
//  Load shaders and initialize attribute buffers

var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );

vertices = [
   vec2(0,0)
];

for(var i =0 ; i<=360 ; i+=10)
{
   vertices.push(vec2(xr*Math.cos(i*(Math.PI/180)),yr*Math.sin(i* 
   (Math.PI/180))));
}

 vertices.push(vec2(0.20,0));
 vertices.push(vec2(0.25,-0.05));
 vertices.push(vec2(0.3,0));
 vertices.push(vec2(0.25,0.05));

vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

// Associate out shader variables with our data buffer
vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );

transformationMatrixLoc = 
 gl.getUniformLocation(program,"transformationMatrix" );
render();
 }


render(){
gl.clear( gl.COLOR_BUFFER_BIT );
var MStack = [] ;

var transformationMatrix = mat4();
MStack.push(transformationMatrix);
gl.uniformMatrix4fv( transformationMatrixLoc, false, 
flatten(transformationMatrix) );
gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

gl.drawArrays( gl.TRIANGLE_FAN, 0, vertices.length-4 );

transformationMatrix = MStack.pop();
MStack.push(transformationMatrix);
gl.uniformMatrix4fv( transformationMatrixLoc, false, 
flatten(transformationMatrix) );

gl.drawArrays(gl.TRIANGLE_FAN,vertices.length-4,vertices.length);
gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

window.requestAnimFrame(render);
}

希望你们能帮助我。真的谢谢。

2 个答案:

答案 0 :(得分:1)

传递到.bufferData()的数据数组必须是ArrayBuffer

使用Float32Array创建一个由32位浮点数组成的数组。这对应于通用顶点属性数据数组的规范中的gl.FLOAT类型:

gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(flatten(vertices)), gl.STATIC_DRAW );

注意,缓冲区对象数据存储区的大小由数组缓冲区的大小确定。


.drawArrays()的最后一个参数是要渲染的顶点数,而不是最后一个属性的索引:

gl.drawArrays(gl.TRIANGLE_FAN, vertices.length-4, 4); 

答案 1 :(得分:0)

这是一个有效的代码段。下次,请发布一个片段来重现您的问题

我需要在您发布的代码中解决的问题

  1. 该代码未包含着色器

    我猜想一些看起来与代码匹配的着色器

    <script id="vertex-shader" type="x-shader/x-vertex">
    attribute  vec4 vPosition;
    uniform mat4 transformationMatrix;
    void main() 
    {
        gl_Position = transformationMatrix*vPosition;
    } 
    </script>
    
    <script id="fragment-shader" type="x-shader/x-fragment">
    precision highp float;
    uniform vec4 color;
    void
    main()
    {
        gl_FragColor = color;
    }
    </script>
    
  2. 代码未定义画布

    我添加了一个ID与代码匹配的

    <canvas id="gl-canvas" width="200" height="200"></canvas>
    
  3. 该代码未链接到您正在使用的脚本。 JavaScript中使用的vec2flatten之类的内容不属于WebGL。它们是某些库的一部分。没有这些,我们不知道您的代码做什么

    我猜是这些:https://github.com/esangel/WebGL,所以我添加了它们

    <script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
    <script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
    <script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
    
  4. 该代码未定义colorLoc的统一位置,也没有为其查询color

  5. 该代码未定义redgreenblue

假设所有这些都存在于您的实际代码中,那么我猜问题出在这行上

gl.drawArrays(gl.TRIANGLE_FAN,vertices.length-4,vertices.length);

应该是

gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length);

drawArrays的参数是

gl.drawArrays(primitiveType, offset, count);

其中primitiveType是要绘制的图元类型。 offset是要配置的属性中要跳过的顶点数,count是要处理的顶点数。

var vPosition, angle = 10,
  j = 1,
  xr = 0.2,
  yr = 0.2,
  colorLoc,
  rad;
var transformationMatrix, transformationMatrixLoc;

function init() {
  canvas = document.getElementById("gl-canvas");
  gl = WebGLUtils.setupWebGL(canvas);

  if (!gl) {
    alert("WebGL isn't available");
  }
  gl.viewport(0, 0, canvas.width, canvas.height);

  gl.clearColor(1.0, 1.0, 1.0, 1.0);
  //  Load shaders and initialize attribute buffers

  var program = initShaders(gl, "vertex-shader", "fragment-shader");
  gl.useProgram(program);

  vertices = [
    vec2(0, 0)
  ];

  for (var i = 0; i <= 360; i += 10) {
    vertices.push(vec2(xr * Math.cos(i * (Math.PI / 180)), yr * Math.sin(i *
      (Math.PI / 180))));
  }

  vertices.push(vec2(0.20, 0));
  vertices.push(vec2(0.25, -0.05));
  vertices.push(vec2(0.3, 0));
  vertices.push(vec2(0.25, 0.05));

  vBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW);

  // Associate out shader variables with our data buffer
  vPosition = gl.getAttribLocation(program, "vPosition");
  gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(vPosition);

  transformationMatrixLoc =
    gl.getUniformLocation(program, "transformationMatrix");
  colorLoc = gl.getUniformLocation(program, "color");
  render();
}

function render() {
  gl.clear(gl.COLOR_BUFFER_BIT);
  var MStack = [];
  const red = 1;
  const green = 0.5;
  const blue = 0.25;

  var transformationMatrix = mat4();
  MStack.push(transformationMatrix);
  gl.uniformMatrix4fv(transformationMatrixLoc, false,
    flatten(transformationMatrix));
  gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

  gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length - 4);

  transformationMatrix = MStack.pop();
  MStack.push(transformationMatrix);
  gl.uniformMatrix4fv(transformationMatrixLoc, false,
    flatten(transformationMatrix));

  gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length);
  gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

  window.requestAnimFrame(render);
}

init();
canvas { border: 1px solid black; }
<script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
<script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
<script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
<canvas id="gl-canvas" width="200" height="200"></canvas>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute  vec4 vPosition;
uniform mat4 transformationMatrix;
void main() 
{
    gl_Position = transformationMatrix*vPosition;
} 
</script>

<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
uniform vec4 color;
void
main()
{
    gl_FragColor = color;
}
</script>

代码做了另一件事,它使用了过时的方式开始使用

window.onload = function init() { ...

一种更现代的方法是将脚本放在页面底部而不是页面顶部,然后直接调用init。否则请使用window.addEventListener('load', function init() { ...,因为那样会使页面上的多个脚本初始化。

您可能会发现these articles有用。