Webgl vertexAttribPointer:索引超出范围

Webgl vertexAttribPointer: index out of range

我正在尝试传递 uv 缓冲区以及 webgl 中的普通缓冲区。但由于某种原因,我在传递值时收到此警告 vertexAttribPointer: index out of range 。我不明白我做错了什么,因为 uv 阵列看起来不错,法线也一样。

似乎错误只发生在法线和 uv 上,而不是位置。

enableVertexAttribArray: index out of range

vertexAttribPointer: index out of range

let canvas = document.querySelector("canvas");
let gl = canvas.getContext("webgl");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

const vsSource = `
    attribute vec4 position;
    attribute vec2 uv;
    attribute vec3 normal;
    uniform mat4 modelViewMatrix;
    varying vec4 vColor;
    void main(void) {
      gl_Position = position;
    }
  `;

const fsSource = `  
    precision mediump float;
    varying vec4 vColor;
    void main(void) {
      gl_FragColor = vec4(1.0,0.0,1.0,1.0);
    }
  `;

// Shader setup

let vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);

if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    var log = gl.getShaderInfoLog(vertexShader);
    throw "Shader compilation failed\n\n" + log + "\n\n";
}

var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);

if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
    var log = gl.getShaderInfoLog(fragmentShader);
    throw "Shader compilation failed\n\n" + log + "\n\n";
}

let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);

gl.linkProgram(program);
gl.validateProgram(program);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    var log = gl.getProgramInfoLog(program);
    throw "Program link failed\n\n" + log;
}

gl.useProgram(program);

let modelViewMatrix = gl.getUniformLocation(program, "modelViewMatrix");

let model = mat4.create();

gl.uniformMatrix4fv(modelViewMatrix, false, model);

var vertices = new Float32Array([
    0.5,
    0.5,
    0.5,
    0.5,
    0.5,
    -0.5,
    0.5,
    -0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    -0.5,
    0.5,
    -0.5,
    -0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    -0.5,
    -0.5,
    -0.5,
    0.5,
    -0.5,
    0.5,
    -0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    0.5,
    0.5,
    0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    0.5,
    0.5,
    -0.5,
    0.5,
    -0.5,
    -0.5,
    -0.5,
    0.5,
    -0.5,
    -0.5,
    -0.5,
    0.5,
    0.5,
    0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    0.5,
    0.5,
    -0.5,
    0.5,
    0.5,
    0.5,
    -0.5,
    -0.5,
    0.5,
    -0.5,
    0.5,
    -0.5,
    -0.5,
    -0.5,
    -0.5,
    -0.5
]);

var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

let position = gl.getAttribLocation(program, "position");

gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(position);

var uvBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        1,
        0
    ]),
    gl.STATIC_DRAW
);

let uv = gl.getAttribLocation(program, "uv");

gl.vertexAttribPointer(uv, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(uv);

var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1
    ]),
    gl.STATIC_DRAW
);

let normal = gl.getAttribLocation(program, "normal");

gl.vertexAttribPointer(normal, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normal);

var indices = new Uint16Array([
    0,
    2,
    1,
    2,
    3,
    1,
    4,
    6,
    5,
    6,
    7,
    5,
    8,
    10,
    9,
    10,
    11,
    9,
    12,
    14,
    13,
    14,
    15,
    13,
    16,
    18,
    17,
    18,
    19,
    17,
    20,
    22,
    21,
    22,
    23,
    21
]);

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
<canvas></canvas>

您的着色器未使用 uvnormal,因此您的驱动程序正在优化这些属性。在这种情况下,gl.getAttribLocation returns -1 表示位置(-1 = 此名称的属性不存在)。 -1 超出范围。有效值为 0 到 gl.getParameter(gl.MAX_VERTEX_ATTRIBS) - 1

换句话说,你需要检查你的属性的位置,如果它们不存在,就不要设置它们。

这就是 write some helper functions for WebGL 为您处理这些问题的好处之一,这样当您修改着色器时,您的代码就不会中断。