WebGL颜色缓冲区问题:[GL_INVALID_OPERATION:glDrawArrays]

时间:2017-09-12 02:59:50

标签: javascript webgl

我正在尝试开始学习WebGL;我的概念证明没有颜色,但是一旦我尝试通过添加

添加颜色
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
), gl.STATIC_DRAW);

ColorAttribute = gl.getAttribLocation(program, 'color');
gl.enableVertexAttribArray(ColorAttribute);
gl.vertexAttribPointer(ColorAttribute, 4, gl.FLOAT, false, 0, 0);

其中

  • gl是WebGLRenderingContext,
  • program是成功编译的程序,附带顶点和片段着色器
  • colorBufferColorAttribute是空变量

在主代码中,并更改

gl_FragColor = vec4(0.2, 0.4, 0.6, 1);

gl_FragColor = vcolor;    
片段着色器源中的

(注释着色器主体不会使错误消失);我收到以下错误:

  

[.Offscreen-For-WebGL-0000000005BB7940] GL错误:GL_INVALID_OPERATION:glDrawArrays:尝试访问属性1中超出范围的顶点

这很奇怪,因为我的颜色缓冲区中有3种颜色,一个用于三角形的每个顶点:

gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
), gl.STATIC_DRAW);

我的顶点缓冲区中有3个顶点:

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    0, 0, 0,
    0, 1, 0,
    1, 1, 0
]), gl.STATIC_DRAW);

我确保在调用vertexAttribPointer时我将颜色缓冲区的项目大小设置为4,顶点缓冲区的项目大小设置为3,所以我不确定什么可能超出范围。

下面是一个有效的代码,其中颜色更改被注释掉,然后是一个无法处理颜色变化的代码。两个示例都通过粘贴到浏览器开发者控制台的任何窗口上工作,但屏幕截图是在“关于:空白”。

两个代码段都是自包含的,但仅在Chrome中进行过测试。

这是工作版本:

(function() {
    "use strict";

    var hWnd;
    var src_vertexShader;
    var src_fragmentShader;
    var canvas;
    var gl;
    var program;
    var vertexShader;
    var fragmentShader;
    var vertexBuffer;
    var colorBuffer;
    var PositionAttribute;
    var ColorAttribute;

    // | canvas container.
    hWnd = document.createElement("div");
    hWnd.style.position = "fixed";
    hWnd.style.top = "0px";
    hWnd.style.left = "0px";
    hWnd.style.border = "1px solid #000000";
    hWnd.addEventListener("click", function() {
        this.outerHTML = '';
    });

    // | vertex shader source.
    src_vertexShader = `
attribute vec3 position;
attribute vec4 color;

varying vec4 vcolor;

void main() {
    gl_Position = vec4(position, 1.0);
    vcolor = color;
}`;

    // | fragment shader source.
    src_fragmentShader = `       
varying lowp vec4 vcolor;

void main() {
    gl_FragColor = vec4(0.2, 0.4, 0.6, 1);

    //gl_FragColor = vcolor;    
}`;

    // | our WebGL canvas.
    canvas = document.createElement('canvas');
    canvas.width = 320;
    canvas.height = 200;       

    // | our WebGLRenderingContext.
    gl = canvas.getContext('webgl', {antialias: false});

    // | setting up our program using a Vertex and a Fragment shader.
    program = gl.createProgram();
    vertexShader = gl.createShader(gl.VERTEX_SHADER);
    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

    gl.shaderSource(vertexShader, src_vertexShader);
    gl.shaderSource(fragmentShader, src_fragmentShader);

    gl.compileShader(vertexShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(vertexShader));    

    gl.compileShader(fragmentShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(fragmentShader));    

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    console.log(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));    

    // | create and attach a vertex buffer with data for one triangle.
    vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0, 0, 0,
        0, 1, 0,
        1, 1, 0
    ]), gl.STATIC_DRAW);

    PositionAttribute = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(PositionAttribute);
    gl.vertexAttribPointer(PositionAttribute, 3, gl.FLOAT, false, 0, 0);

    /*
    // | create and attach a color buffer with color data for our triangle.
    colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

    gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(
        1, 0, 0, 1,
        0, 1, 0, 1,
        0, 0, 1, 1,
    ), gl.STATIC_DRAW);

    ColorAttribute = gl.getAttribLocation(program, 'color');
    gl.enableVertexAttribArray(ColorAttribute);
    gl.vertexAttribPointer(ColorAttribute, 4, gl.FLOAT, false, 0, 0);
    */

    // | clear the screen.
    gl.clearColor(0.93, 0.93, 0.93, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    // | draw the triangle.
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    hWnd.appendChild(canvas)
    document.body.appendChild(hWnd);
})();

enter image description here

这是抱怨的版本:

(function() {
    "use strict";

    var hWnd;
    var src_vertexShader;
    var src_fragmentShader;
    var canvas;
    var gl;
    var program;
    var vertexShader;
    var fragmentShader;
    var vertexBuffer;
    var colorBuffer;
    var PositionAttribute;
    var ColorAttribute;

    // | canvas container.
    hWnd = document.createElement("div");
    hWnd.style.position = "fixed";
    hWnd.style.top = "0px";
    hWnd.style.left = "0px";
    hWnd.style.border = "1px solid #000000";
    hWnd.addEventListener("click", function() {
        this.outerHTML = '';
    });

    // | vertex shader source.
    src_vertexShader = `
attribute vec3 position;
attribute vec4 color;

varying vec4 vcolor;

void main() {
    gl_Position = vec4(position, 1.0);
    vcolor = color;
}`;

    // | fragment shader source.
    src_fragmentShader = `       
varying lowp vec4 vcolor;

void main() {
    gl_FragColor = vcolor;    
}`;

    // | our WebGL canvas.
    canvas = document.createElement('canvas');
    canvas.width = 320;
    canvas.height = 200;       

    // | our WebGLRenderingContext.
    gl = canvas.getContext('webgl', {antialias: false});

    // | setting up our program using a Vertex and a Fragment shader.
    program = gl.createProgram();
    vertexShader = gl.createShader(gl.VERTEX_SHADER);
    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

    gl.shaderSource(vertexShader, src_vertexShader);
    gl.shaderSource(fragmentShader, src_fragmentShader);

    gl.compileShader(vertexShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(vertexShader));    

    gl.compileShader(fragmentShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(fragmentShader));    

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    console.log(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));    

    // | create and attach a vertex buffer with data for one triangle.
    vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0, 0, 0,
        0, 1, 0,
        1, 1, 0
    ]), gl.STATIC_DRAW);

    PositionAttribute = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(PositionAttribute);
    gl.vertexAttribPointer(PositionAttribute, 3, gl.FLOAT, false, 0, 0);

    // | create and attach a color buffer with color data for our triangle.
    colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

    gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(
        1, 0, 0, 1,
        0, 1, 0, 1,
        0, 0, 1, 1,
    ), gl.STATIC_DRAW);

    ColorAttribute = gl.getAttribLocation(program, 'color');
    gl.enableVertexAttribArray(ColorAttribute);
    gl.vertexAttribPointer(ColorAttribute, 4, gl.FLOAT, false, 0, 0);

    // | clear the screen.
    gl.clearColor(0.93, 0.93, 0.93, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    // | draw the triangle.
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    hWnd.appendChild(canvas)
    document.body.appendChild(hWnd);    
})();

enter image description here

enter image description here

提前致谢。

1 个答案:

答案 0 :(得分:1)

问题是在定义颜色时代码缺少方括号

 gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
  ), gl.STATIC_DRAW);

vs this

 gl.bufferData (gl.ARRAY_BUFFER, new Float32Array([
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
 ]), gl.STATIC_DRAW);



(function() {
    "use strict";

    var hWnd;
    var src_vertexShader;
    var src_fragmentShader;
    var canvas;
    var gl;
    var program;
    var vertexShader;
    var fragmentShader;
    var vertexBuffer;
    var colorBuffer;
    var PositionAttribute;
    var ColorAttribute;

    // | canvas container.
    hWnd = document.createElement("div");
    hWnd.style.position = "fixed";
    hWnd.style.top = "0px";
    hWnd.style.left = "0px";
    hWnd.style.border = "1px solid #000000";
    hWnd.addEventListener("click", function() {
        this.outerHTML = '';
    });

    // | vertex shader source.
    src_vertexShader = `
attribute vec3 position;
attribute vec4 color;

varying vec4 vcolor;

void main() {
    gl_Position = vec4(position, 1.0);
    vcolor = color;
}`;

    // | fragment shader source.
    src_fragmentShader = `       
varying lowp vec4 vcolor;

void main() {
    gl_FragColor = vcolor;    
}`;

    // | our WebGL canvas.
    canvas = document.createElement('canvas');
    canvas.width = 320;
    canvas.height = 200;       

    // | our WebGLRenderingContext.
    gl = canvas.getContext('webgl', {antialias: false});

    // | setting up our program using a Vertex and a Fragment shader.
    program = gl.createProgram();
    vertexShader = gl.createShader(gl.VERTEX_SHADER);
    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

    gl.shaderSource(vertexShader, src_vertexShader);
    gl.shaderSource(fragmentShader, src_fragmentShader);

    gl.compileShader(vertexShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(vertexShader));    

    gl.compileShader(fragmentShader);
    console.log('Shader compiled successfully: ' + gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));
    console.log('Shader compiler log: ' + gl.getShaderInfoLog(fragmentShader));    

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    console.log(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS));    

    // | create and attach a vertex buffer with data for one triangle.
    vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0, 0, 0,
        0, 1, 0,
        1, 1, 0
    ]), gl.STATIC_DRAW);

    PositionAttribute = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(PositionAttribute);
    gl.vertexAttribPointer(PositionAttribute, 3, gl.FLOAT, false, 0, 0);

    // | create and attach a color buffer with color data for our triangle.
    colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

    gl.bufferData (gl.ARRAY_BUFFER, new Float32Array([
        1, 0, 0, 1,
        0, 1, 0, 1,
        0, 0, 1, 1,
    ]), gl.STATIC_DRAW);

    ColorAttribute = gl.getAttribLocation(program, 'color');
    gl.enableVertexAttribArray(ColorAttribute);
    gl.vertexAttribPointer(ColorAttribute, 4, gl.FLOAT, false, 0, 0);

    // | clear the screen.
    gl.clearColor(0.93, 0.93, 0.93, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    // | draw the triangle.
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    hWnd.appendChild(canvas)
    document.body.appendChild(hWnd);    
})();