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

问题描述 投票:0回答:1

我在这里创建了 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);

上面第二个片段的 console.log 语句的输出是

normalLoc -1
。 (注意:代码片段控制台包含此行输出,但不显示浏览器(chrome、safari)中出现的错误消息。)

第一个片段中顶点着色器中的法线声明:

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

第二个片段中顶点着色器中的法线声明:

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

我查看了WEBGL:INVALID_VALUE:vertexAttribPointer:索引超出范围,INVALID_VALUE:enableVertexAttribArray:索引超出范围Webgl的getAttribLocation奇怪地返回-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>

第二个片段(失败)

'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 fragment-shader vertex-shader
1个回答
0
投票

发生这种情况是因为您在这些行上有错字:

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

您不是设置为

out
变量,而是创建新的局部变量。您需要从所有这些行的开头删除
vec3

这些局部变量永远不会被使用,所以

NN
永远不会被使用,所以
aNormal
也永远不会被使用,并且 GLSL 编译器优化掉这些变量,所以当你调用
aNormal
时找不到
gl.vertexAttribPointer

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

© www.soinside.com 2019 - 2024. All rights reserved.