在 2 个不同的 WebGL 应用程序中使用相同的 JS 代码,在 1 个应用程序中工作,但在其他应用程序中失败:vertexAttribute 有问题吗?

same JS code in 2 diiferent WebGL applications, works in 1 but fails in other: problem with vertexAttribute?

提问人:dhhepting 提问时间:11/3/2023 最后编辑:dhhepting 更新时间:11/4/2023 访问量:60

问:

我在这里创建了 2 个片段,从 https://interactivecomputergraphics.com/8E/Code/06/shadedCube.html 开始。第一个代码段按预期工作,但第二个代码段没有。当我在浏览器中运行第二个代码片段时,我在 javascript 控制台上收到以下错误:

WebGL: INVALID_VALUE: vertexAttribPointer: index out of range
WebGL: INVALID_VALUE: enableVertexAttribArray: index out of range

这些错误对应于 javascript 中的以下语句:

const normalLoc = gl.getAttribLocation(program, 'aNormal');
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
console.log('normalLoc', normalLoc);

上面第二个代码段的控制台 .log 语句的输出是 .(注意:代码段控制台包含此输出行,但不显示浏览器(chrome、safari)中出现的错误消息。normalLoc -1

从第一个代码段开始,顶点着色器中 aNormal 的声明:

in vec4 aPosition;
in vec3 aNormal;
out vec4 vColor;

从第二个代码段开始在顶点着色器中声明 aNormal:

in vec4 aPosition;
in vec3 aNormal;
out vec3 N, L, V;

我看过 WEBGL: INVALID_VALUE: vertexAttribPointer: index out of range, INVALID_VALUE: enableVertexAttribArray: index out of range,Webgl 的 getAttribLocation 奇怪地返回 -1

我看不出我错过了什么。任何帮助都非常感谢!

第 1 段(有效)

'use strict';

function shadedCube() {
  let gl;
  let program;

  const numPositions = 36;

  const positionsArray = [];
  const normalsArray = [];

  const vertices = [
    vec4(-0.5, -0.5, 0.5, 1.0),
    vec4(-0.5, 0.5, 0.5, 1.0),
    vec4(0.5, 0.5, 0.5, 1.0),
    vec4(0.5, -0.5, 0.5, 1.0),
    vec4(-0.5, -0.5, -0.5, 1.0),
    vec4(-0.5, 0.5, -0.5, 1.0),
    vec4(0.5, 0.5, -0.5, 1.0),
    vec4(0.5, -0.5, -0.5, 1.0)];

  const viewerPosition = vec4(0.0, 0.0, 20.0, 0.0);
  const lightPosition = vec4(0.0, 2.0, 2.0, 0.0);
  const lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
  const lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
  const lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);

  const materialAmbient = vec4(0.0, 0.0, 0.8, 1.0);
  const materialDiffuse = vec4(0.8, 0.8, 0.0, 1.0);
  const materialSpecular = vec4(0.4, 0.4, 0.4, 1.0);
  const materialShininess = 100.0;

  const xAxis = 0;
  const yAxis = 1;
  const zAxis = 2;
  const axis = 0;
  const theta = vec3(0, 0, 0);

  const flag = true;

  function quad(a, b, c, d) {
    const t1 = subtract(vertices[b], vertices[a]);
    const t2 = subtract(vertices[c], vertices[b]);
    let normal = cross(t1, t2);
    normal = vec3(normal);
    console.log('cube face normal', normal[0], normal[1], normal[2]);

    positionsArray.push(vertices[a]);
    normalsArray.push(normal);
    positionsArray.push(vertices[b]);
    normalsArray.push(normal);
    positionsArray.push(vertices[c]);
    normalsArray.push(normal);
    positionsArray.push(vertices[a]);
    normalsArray.push(normal);
    positionsArray.push(vertices[c]);
    normalsArray.push(normal);
    positionsArray.push(vertices[d]);
    normalsArray.push(normal);
  }

  function colorCube() {
    quad(1, 0, 3, 2);
    quad(2, 3, 7, 6);
    quad(3, 0, 4, 7);
    quad(6, 5, 1, 2);
    quad(4, 5, 6, 7);
    quad(5, 4, 0, 1);
  }

  window.onload = function init() {
    const canvas = document.getElementById('gl-canvas');
    gl = canvas.getContext('webgl2');
    if (!gl) {
      alert( 'WebGL 2.0 is not available');
    }
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(0.8, 0.8, 0.8, 1.0);
    gl.enable(gl.DEPTH_TEST);

    //
    //  Load shaders and initialize attribute buffers
    //
    program = initShaders(gl, 'vertex-shader', 'fragment-shader');
    gl.useProgram(program);

    // generate the data needed for the cube
    colorCube();
    console.log('number of normals', normalsArray.length);

    const vBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);
    const positionLoc = gl.getAttribLocation(program, 'aPosition');
    gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionLoc);
    console.log('positionLoc', positionLoc);

    const nBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);
    const normalLoc = gl.getAttribLocation(program, 'aNormal');
    gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalLoc);
    console.log('normalLoc', normalLoc);

    const projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);

    const ambientProduct = mult(lightAmbient, materialAmbient);
    const diffuseProduct = mult(lightDiffuse, materialDiffuse);
    const specularProduct = mult(lightSpecular, materialSpecular);
    /*
    document.getElementById('ButtonX').onclick = function() {
      axis = xAxis;
    };
    document.getElementById('ButtonY').onclick = function() {
      axis = yAxis;
    };
    document.getElementById('ButtonZ').onclick = function() {
      axis = zAxis;
    };
    document.getElementById('ButtonT').onclick = function() {
      flag = !flag;
    }; */

    gl.uniform4fv(
        gl.getUniformLocation(program, 'uAmbientProduct'), ambientProduct);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uDiffuseProduct'), diffuseProduct);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uSpecularProduct'), specularProduct);
    gl.uniform1f(
        gl.getUniformLocation(program, 'uShininess'), materialShininess);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uLightPosition'), lightPosition);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uViewerPosition'), viewerPosition);

    gl.uniformMatrix4fv(
        gl.getUniformLocation(program, 'uProjectionMatrix'),
        false, flatten(projectionMatrix));
    render();
  };
  function render() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    if (flag) {
      theta[axis] += 2.0;
    }
    let modelViewMatrix = mat4();
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[xAxis], vec3(1, 0, 0)));
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[yAxis], vec3(0, 1, 0)));
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[zAxis], vec3(0, 0, 1)));

    gl.uniformMatrix4fv(
        gl.getUniformLocation(program, 'uModelViewMatrix'),
        false, flatten(modelViewMatrix));
    gl.drawArrays(gl.TRIANGLES, 0, numPositions);
    requestAnimationFrame(render);
  };
};

shadedCube();
<!DOCTYPE html>
<html>
    <head>
        <script id="vertex-shader" type="x-shader/x-vertex">
            #version 300 es

            in vec4 aPosition;
            in vec3 aNormal;
            out vec4 vColor;

            uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
            uniform float uShininess;
            uniform mat4 uModelViewMatrix, uProjectionMatrix;
            uniform vec4 uLightPosition, uViewerPosition;
            
            void main()
            {
                vec4 NN = vec4(aNormal, 0);
                vec3 N = normalize((uModelViewMatrix * NN).xyz);
                vec3 pos = (uModelViewMatrix * aPosition).xyz;
                vec3 light = uLightPosition.xyz;
                vec3 L = normalize(light - pos);

                vec3 V = normalize(uViewerPosition).xyz;
                vec3 H = normalize(L + V);

                // Compute terms in the illumination equation
                // ambient 
                vec4 ambient = uAmbientProduct;
                // diffuse
                float Kd = max(dot(L, N), 0.0);
                vec4 diffuse = Kd * uDiffuseProduct;
                // specular
                float Ks = pow(max(dot(N, H), 0.0), uShininess);
                vec4 specular = Ks * uSpecularProduct;

                vColor = ambient + diffuse + specular;
                vColor.a = 1.0;

                gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
            }
        </script>
        <script id="fragment-shader" type="x-shader/x-fragment">
            #version 300 es

            precision mediump float;

            in vec4 vColor;
            out vec4 fColor;

            void
            main()
            {
                fColor = vColor;
            }
        </script>
        <script text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/initShaders.js"></script>
        <script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/MVnew.js"></script>

        <script type="text/javascript" src="shaded-cube.js"></script>
    </head>
    <body>
        <canvas id="gl-canvas" width="512" height="512">
            Your browser does not support the HTML5 canvas element
        </canvas>
    </body>
</html>

第 2 段(失败)

'use strict';

function shadedCube() {
  let gl;
  let program;

  const numPositions = 36;

  const positionsArray = [];
  const normalsArray = [];

  const vertices = [
    vec4(-0.5, -0.5, 0.5, 1.0),
    vec4(-0.5, 0.5, 0.5, 1.0),
    vec4(0.5, 0.5, 0.5, 1.0),
    vec4(0.5, -0.5, 0.5, 1.0),
    vec4(-0.5, -0.5, -0.5, 1.0),
    vec4(-0.5, 0.5, -0.5, 1.0),
    vec4(0.5, 0.5, -0.5, 1.0),
    vec4(0.5, -0.5, -0.5, 1.0)];

  const viewerPosition = vec4(0.0, 0.0, 20.0, 0.0);
  const lightPosition = vec4(0.0, 2.0, 2.0, 0.0);
  const lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
  const lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
  const lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);

  const materialAmbient = vec4(0.0, 0.0, 0.8, 1.0);
  const materialDiffuse = vec4(0.8, 0.8, 0.0, 1.0);
  const materialSpecular = vec4(0.4, 0.4, 0.4, 1.0);
  const materialShininess = 100.0;

  const xAxis = 0;
  const yAxis = 1;
  const zAxis = 2;
  const axis = 0;
  const theta = vec3(0, 0, 0);

  const flag = true;

  function quad(a, b, c, d) {
    const t1 = subtract(vertices[b], vertices[a]);
    const t2 = subtract(vertices[c], vertices[b]);
    let normal = cross(t1, t2);
    normal = vec3(normal);
    console.log('cube face normal', normal[0], normal[1], normal[2]);

    positionsArray.push(vertices[a]);
    normalsArray.push(normal);
    positionsArray.push(vertices[b]);
    normalsArray.push(normal);
    positionsArray.push(vertices[c]);
    normalsArray.push(normal);
    positionsArray.push(vertices[a]);
    normalsArray.push(normal);
    positionsArray.push(vertices[c]);
    normalsArray.push(normal);
    positionsArray.push(vertices[d]);
    normalsArray.push(normal);
  }

  function colorCube() {
    quad(1, 0, 3, 2);
    quad(2, 3, 7, 6);
    quad(3, 0, 4, 7);
    quad(6, 5, 1, 2);
    quad(4, 5, 6, 7);
    quad(5, 4, 0, 1);
  }

  window.onload = function init() {
    const canvas = document.getElementById('gl-canvas');
    gl = canvas.getContext('webgl2');
    if (!gl) {
      alert( 'WebGL 2.0 is not available');
    }
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(0.8, 0.8, 0.8, 1.0);
    gl.enable(gl.DEPTH_TEST);

    //
    //  Load shaders and initialize attribute buffers
    //
    program = initShaders(gl, 'vertex-shader', 'fragment-shader');
    gl.useProgram(program);

    // generate the data needed for the cube
    colorCube();
    console.log('number of normals', normalsArray.length);

    const vBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);
    const positionLoc = gl.getAttribLocation(program, 'aPosition');
    gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionLoc);
    console.log('positionLoc', positionLoc);

    const nBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);
    const normalLoc = gl.getAttribLocation(program, 'aNormal');
    gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalLoc);
    console.log('normalLoc', normalLoc);

    const projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);

    const ambientProduct = mult(lightAmbient, materialAmbient);
    const diffuseProduct = mult(lightDiffuse, materialDiffuse);
    const specularProduct = mult(lightSpecular, materialSpecular);
   
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uAmbientProduct'), ambientProduct);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uDiffuseProduct'), diffuseProduct);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uSpecularProduct'), specularProduct);
    gl.uniform1f(
        gl.getUniformLocation(program, 'uShininess'), materialShininess);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uLightPosition'), lightPosition);
    gl.uniform4fv(
        gl.getUniformLocation(program, 'uViewerPosition'), viewerPosition);

    gl.uniformMatrix4fv(
        gl.getUniformLocation(program, 'uProjectionMatrix'),
        false, flatten(projectionMatrix));
    render();
  };
  function render() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    if (flag) {
      theta[axis] += 2.0;
    }
    let modelViewMatrix = mat4();
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[xAxis], vec3(1, 0, 0)));
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[yAxis], vec3(0, 1, 0)));
    modelViewMatrix = mult(modelViewMatrix,
        rotate(theta[zAxis], vec3(0, 0, 1)));

    gl.uniformMatrix4fv(
        gl.getUniformLocation(program, 'uModelViewMatrix'),
        false, flatten(modelViewMatrix));
    gl.drawArrays(gl.TRIANGLES, 0, numPositions);
    requestAnimationFrame(render);
  };
};

shadedCube();
<!DOCTYPE html>
<html>
    <head>
        <script id="vertex-shader" type="x-shader/x-vertex">
            #version 300 es

            in vec4 aPosition;
            in vec3 aNormal;
            out vec3 N, L, V;

            uniform mat4 uModelViewMatrix, uProjectionMatrix;
            uniform vec4 uLightPosition, uViewerPosition;

            void main()
            {
                vec3 pos = (uModelViewMatrix * aPosition).xyz;
                vec3 light = uLightPosition.xyz;
                vec4 NN = vec4(aNormal,0.0);

                vec3 N = normalize((uModelViewMatrix * NN).xyz);
                vec3 L = normalize(light - pos);
                vec3 V = normalize(uViewerPosition).xyz;

                gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
            }
        </script>
        <script id="fragment-shader" type="x-shader/x-fragment">
            #version 300 es

            precision mediump float;
            
            in vec3 N, L, V;
            out vec4 fColor;

            uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
            uniform float uShininess;

            void main()
            {
                vec3 H = normalize(L + V);
                vec4 ambient = uAmbientProduct;

                float Kd = max( dot(L, N), 0.0 );
                vec4 diffuse = Kd * uDiffuseProduct;

                float Ks = pow(max(dot(N, H), 0.0), uShininess);
                vec4 specular = Ks * uSpecularProduct;

                fColor = ambient + diffuse + specular;
                fColor.a = 1.0;
            }
        </script>
        <script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/initShaders.js"></script>
        <script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/MVnew.js"></script>
        <script type="text/javascript" src="shaded-cube.js"></script>
    </head>
    <body>
        <canvas id="gl-canvas" width="512" height="512">
            Your browser does not support the HTML5 canvas element
        </canvas>
    </body>
</html>

javascript glsl webgl 顶点着色器

评论


答:

1赞 Andy Ray 11/4/2023 #1

它之所以发生,是因为您在以下几行上有一个错别字:

                vec3 N = normalize((uModelViewMatrix * NN).xyz);
                vec3 L = normalize(light - pos);
                vec3 V = normalize(uViewerPosition).xyz;

您不是在设置变量,而是在创建新的局部变量。您需要从所有这些行的开头删除。outvec3

这些局部变量从不使用,因此从不使用,因此从不使用,并且 GLSL 编译器会优化这些变量,因此在调用 时找不到。NNaNormalaNormalgl.vertexAttribPointer

搜索警告/错误显示大多数问题都来自同一个问题:未使用的属性从 GLSL 中删除。

评论

0赞 dhhepting 11/4/2023
谢谢!完全有道理。祝你周末愉快。