【问题标题】:WebGL GL_INVALID_OPERATION out of range errorWebGL GL_INVALID_OPERATION 超出范围错误
【发布时间】:2020-10-10 12:17:15
【问题描述】:

所有。我是 webgl 的新手,但我检查了有关此错误的资源。我正在尝试在我的圆圈旁边画一个正方形。之后我画了一个圆圈,我为正方形添加了 4 个索引和基于此组织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);
}

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

【问题讨论】:

    标签: arrays webgl


    【解决方案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); 
    

    【讨论】:

    • 我使用了 Float32Array 但得到了同样的错误。
    • AFAICT 这个学生的大部分问题使用的库是this one,其中flatten 返回一个Float32Array
    【解决方案2】:

    这是一个有效的 sn-p。下次请发snippet 重现您的问题

    我需要在您发布的代码中修复的问题

    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. 代码没有为color统一位置定义或查找colorLoc

    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 很有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 2016-09-08
      • 1970-01-01
      相关资源
      最近更新 更多