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

WebGL color buffer issue: [GL_INVALID_OPERATION : glDrawArrays]

我正在尝试开始学习 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_FragColor = vec4(0.2, 0.4, 0.6, 1);

gl_FragColor = vcolor;    

在片段着色器源代码中(注释着色器主体不会使错误消失);我收到以下错误:

[.Offscreen-For-WebGL-0000000005BB7940]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 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,所以我不确定什么可能超出范围。

下面是一段有效的代码,颜色变化被注释掉,后面是一段颜色变化无效的代码。这两个示例都可以通过粘贴到任何 window 上的浏览​​器开发人员控制台来工作,但是屏幕截图是在 "about:blank" 中拍摄的。

两个片段都是独立的,但仅在 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);
})();

这是抱怨的版本:

(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);    
})();

提前致谢。

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

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

对比这个

 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);    
})();