WebGL - 无效操作useProgram

时间:2012-08-17 01:44:36

标签: javascript webgl

我正在学习WebGL并参与this教程,该教程与光照有关。我是JavaScript的新手,所以我还不太擅长调试它。我一直在收到这些错误,有人知道为什么我会得到它们以及如何解决它?

WebGL: INVALID_OPERATION: useProgram: program not valid http://insanergamer.zxq.net/:1
WebGL: INVALID_OPERATION: getAttribLocation: program not linked http://insanergamer.zxq.net/:1
WebGL: INVALID_OPERATION: getUniformLocation: program not linked http://insanergamer.zxq.net/:1
WebGL: too many errors, no more errors will be reported to the console for this context. 

的index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf 8" />
    <link rel="stylesheet" href="main.css">
    <script type="text/javascript" language="javascript" src="gl-matrix.js"></script>
    <script type="text/javascript" language="javascript" src="webgl-utils.js"></script>
    <script type="text/javascript" language="javascript" src="first.js"></script>

        <script id="shader-fs" type="x-shader/x-fragment">
               precision mediump float;

                varying vec2 vTextureCoord;
                varying vec3 vLightWeighting;

                uniform sampler2D uSampler;

                void main(void) {
                    vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
                    gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
                }

        </script>

        <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 aVertexPosition;
            attribute vec3 aVertexNormal;
            attribute vec2 aTextureCoord;

            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix;
            uniform mat3 uNMatrix;

            uniform vec3 uAmbientColor;

            uniform vec3 uLightingDirection;
            uniform vec3 uDirectionalColor;

            uniform bool uUseLighting;

            varying vec2 vTextureCoord;
            varying vec3 vLightWeighting;

            void main(void) {
                gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
                vTextureCoord = aTextureCoord;

                if (!uUseLighting) {
                    vLightWeighting = vec3(1.0, 1.0, 1.0);
                } else {
                    vec3 transformedNormal = uNMatrix * aVertexNormal;
                    float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
                    vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
                }
        </script>
</head>
<body onLoad="webGLStart()">
    <header>
    </header>
    <nav>
    </nav>
    <section>
        <h3><a href="todo.html">Link to the TODO page.</a></h3>

        <form>
            <input type="checkbox" id="lighting"></input>Lighting On/Off<br />
            Ambient Lighting Color: Red:<input type="text" id="ambientR"></input> Green:<input type="text" id="ambientG"></input> Blue:<input type="text" id="ambientB"></input> <br />
            Light Direction: X:<input type="text" id="lightDirectionX"></input> Y:<input type="text" id="lightDirectionY"></input> Z:<input type="text" id="lightDirectionZ"></input> <br />
            Direction Lighting Color: Red:<input type="text" id="directionalR"></input> Green:<input type="text" id="directionalG"></input> Blue:<input type="text" id="directionalB"></input> <br />
        </form>

        <p>Press 'F' to change Texture quality.</p>
        <p>Use Arrow Keys to rotate cube.</p>
        <p>Page Up and Page down to zoom in and out.</p>
        <canvas canvasProperties="prop" id="canvas1" style="border: none;" width="1280" height="720"></canvas>
        <article>
            <header>
            </header>
            <footer>
            </footer>
        </article>
    </section>
    <aside>
    </aside>
    <footer>
    </footer>
</body>

first.js

    var gl;
function initGL(canvas) {
    try {
        gl = canvas.getContext("experimental-webgl");
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
    } catch (e) {
    }
    if (!gl) {
        alert("Could not initialise WebGL, sorry :-(");
    }
}


function getShader(gl, id) {
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
        return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
        if (k.nodeType == 3) {
            str += k.textContent;
        }
        k = k.nextSibling;
    }

    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }

    gl.shaderSource(shader, str);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}


var shaderProgram;

function initShaders() {
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");

    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }

    gl.useProgram(shaderProgram);

    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

    shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
    gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);

    shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
    gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);

    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
    shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting");
    shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor");
    shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection");
    shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor");
}

var cubeTextures = Array();
function initTexture()
{
    var cubeImage = new Image();

    for(var i=0;i < 3; i++)
    {
        var texture = gl.createTexture();
        texture.image = cubeImage;
        cubeTextures.push(texture);
    }

    cubeImage.onload = function()
    {
        handleLoadedTexture(cubeTextures);
    }
    cubeImage.src = "cube.png";
}

function handleLoadedTexture(texture)
{
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

    gl.bindTexture(gl.TEXTURE_2D,texture[0]);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture[0].image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);

    gl.bindTexture(gl.TEXTURE_2D, texture[1]);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture[1].image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    gl.bindTexture(gl.TEXTURE_2D, texture[2]);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture[2].image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.generateMipmap(gl.TEXTURE_2D);

    gl.bindTexture(gl.TEXTURE_2D, null);
}

var mvMatrix = mat4.create();
var mvMatrixStack = []
var pMatrix = mat4.create();

function mvPushMatrix()
{
    var copy = mat4.create();
    mat4.set(mvMatrix, copy);
    mvMatrixStack.push(copy);
}

function mvPopMatrix()
{
    if(mvMatrixStack.length == 0)
    {
        throw "No Matrix to Pop!";
    }
    mvMatrix = mvMatrixStack.pop();
}

function degToRad(degrees)
{
    return degrees * Math.PI / 180;
}
function setMatrixUniforms() {
    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);

    var normalMatrix = mat3.create();
    mat4.toInverseMat3(mvMatrix, normalMatrix);
    mat3.transpose(normalMatrix);
    gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
}

var cubeVertexPositionBuffer;
var cubeVertexTextureCoordBuffer;
var cubeVertexIndexBuffer;

function initBuffers() {

    cubeVertexPositionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    vertices = [
       // Front face
      -1.0, -1.0,  1.0,
       1.0, -1.0,  1.0,
       1.0,  1.0,  1.0,
      -1.0,  1.0,  1.0,

      // Back face
      -1.0, -1.0, -1.0,
      -1.0,  1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0, -1.0, -1.0,

      // Top face
      -1.0,  1.0, -1.0,
      -1.0,  1.0,  1.0,
       1.0,  1.0,  1.0,
       1.0,  1.0, -1.0,

      // Bottom face
      -1.0, -1.0, -1.0,
       1.0, -1.0, -1.0,
       1.0, -1.0,  1.0,
      -1.0, -1.0,  1.0,

      // Right face
       1.0, -1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0,  1.0,  1.0,
       1.0, -1.0,  1.0,

      // Left face
      -1.0, -1.0, -1.0,
      -1.0, -1.0,  1.0,
      -1.0,  1.0,  1.0,
      -1.0,  1.0, -1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    cubeVertexPositionBuffer.itemSize = 3;
    cubeVertexPositionBuffer.numItems = 24;

     cubeVertexNormalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
    var vertexNormals = [
        // Front face
         0.0,  0.0,  1.0,
         0.0,  0.0,  1.0,
         0.0,  0.0,  1.0,
         0.0,  0.0,  1.0,

        // Back face
         0.0,  0.0, -1.0,
         0.0,  0.0, -1.0,
         0.0,  0.0, -1.0,
         0.0,  0.0, -1.0,

        // Top face
         0.0,  1.0,  0.0,
         0.0,  1.0,  0.0,
         0.0,  1.0,  0.0,
         0.0,  1.0,  0.0,

        // Bottom face
         0.0, -1.0,  0.0,
         0.0, -1.0,  0.0,
         0.0, -1.0,  0.0,
         0.0, -1.0,  0.0,

        // Right face
         1.0,  0.0,  0.0,
         1.0,  0.0,  0.0,
         1.0,  0.0,  0.0,
         1.0,  0.0,  0.0,

        // Left face
        -1.0,  0.0,  0.0,
        -1.0,  0.0,  0.0,
        -1.0,  0.0,  0.0,
        -1.0,  0.0,  0.0
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals), gl.STATIC_DRAW);
    cubeVertexNormalBuffer.itemSize = 3;
    cubeVertexNormalBuffer.numItems = 24;

    cubeVertexTextureCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
    var textureCoords = [
         // Front face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,

          // Back face
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,

          // Top face
          0.0, 1.0,
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,

          // Bottom face
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,
          1.0, 0.0,

          // Right face
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,

          // Left face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
    cubeVertexTextureCoordBuffer.itemSize = 2;
    cubeVertexTextureCoordBuffer.numItems = 24;

    cubeVertexIndexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
    var cubeVertexIndices = [
      0, 1, 2,      0, 2, 3,    // Front face
      4, 5, 6,      4, 6, 7,    // Back face
      8, 9, 10,     8, 10, 11,  // Top face
      12, 13, 14,   12, 14, 15, // Bottom face
      16, 17, 18,   16, 18, 19, // Right face
      20, 21, 22,   20, 22, 23  // Left face
    ]

    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
    cubeVertexIndexBuffer.itemSize = 1;
    cubeVertexIndexBuffer.numItems = 36;
}

var rCubeX = 0;
var SpeedX = 0;

var rCubeY = 0;
var SpeedY = 0;

var z = -5.0;

var filter = 0;

function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

    mat4.identity(mvMatrix);

    mat4.translate(mvMatrix, [0.0, 0.0, z]);

    mvPushMatrix();
    mat4.rotate(mvMatrix, degToRad(rCubeX), [1, 0, 0]);
    mat4.rotate(mvMatrix, degToRad(rCubeY), [0, 1, 0]);

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, cubeVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, cubeTextures[filter]);
    gl.uniform1i(shaderProgram.samplerUniform, 0);
    var lighting = document.getElementById("lighting").checked;
    gl.uniform1i(shaderProgram.useLightingUniform, lighting);
    if(lighting)
    {
        gl.uniform3f(
            shaderProgram.ambientColorUniform,
            parseFloat(document.getElementById("ambientR").value),
            parseFloat(document.getElementById("ambientG").value),
            parseFloat(document.getElementById("ambientB").value)
        );
    }

    var lightingDirection = [
        parseFloat(document.getElementById("lightDirectionX").value),
        parseFloat(document.getElementById("lightDirectionY").value),
        parseFloat(document.getElementById("lightDirectionZ").value)
    ];
    var adjustedLD = vec3.create();
    vec3.normalize(lightingDirection, adjustedLD);
    vec3.scale(adjustedLD, -1);
    gl.uniform3fv(shaderProgram.lightingDirectionUniform, adjustedLD);
    gl.uniform3f(
        shaderProgram.directionalColorUniform,
        parseFloat(document.getElementById("directionalR").value),
        parseFloat(document.getElementById("directionalG").value),
        parseFloat(document.getElementById("directionalB").value)   
    );

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
    setMatrixUniforms();
    gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    mvPopMatrix();
}

var lastTime = 0;
function animate()
{
    var timeNow = new Date().getTime();
    if(lastTime != 0)
    {
        var elapsed = timeNow - lastTime;

        rCubeX += (SpeedX * elapsed) / 1000.0;
        rCubeY += (SpeedY * elapsed) / 1000.0;
    }
    lastTime = timeNow;
}

 var currentlyPressedKeys = {};

 function handleKeyDown(event){
    currentlyPressedKeys[event.keyCode] = true;
    if(String.fromCharCode(event.keyCode) == "F"){
        filter += 1;
        if(filter == 3){
            filter = 0;
        }
    }
 }

 function handleKeyUp(event){
    currentlyPressedKeys[event.keyCode] = false;

 }
function handleKeys()
{
    if(currentlyPressedKeys[33])
    {
     z -= 0.05;
    }

    if(currentlyPressedKeys[34])
    {
        z += 0.05;
    }

    if(currentlyPressedKeys[37])
    {
        SpeedY --;
    } else if (SpeedY < 0){
        SpeedY ++;
    }

    if(currentlyPressedKeys[39])
    {
        SpeedY ++;
    }else if(SpeedY > 0){
        SpeedY --;
    }

     if (currentlyPressedKeys[38]) {
         SpeedX --;
    } else if(SpeedX < 0){
         SpeedX ++;
    }

    if (currentlyPressedKeys[40]) {
         SpeedX ++;
    } else if(SpeedX > 0){
         SpeedX--;
    }
}

function update()
{
    requestAnimFrame(update);
    handleKeys();
    drawScene();
    animate();
}


function webGLStart() {
    var canvas = document.getElementById("canvas1");
    initGL(canvas);
    initShaders();
    initBuffers();
    initTexture();

    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.enable(gl.DEPTH_TEST);

    document.onkeydown = handleKeyDown;
    document.onkeyup = handleKeyUp;

    update();
}

4 个答案:

答案 0 :(得分:7)

在这种特殊情况下的原因是你在顶点着色器的末尾错过了一个结束},但这并没有回答为什么你没有看到有关你的着色器无法编译的原因的消息。< / p>

getShader中的错误检查代码实际上看起来应该可以正常工作,并且实际上检查并警告Clutch在编译和链接失败时提到的错误日志。

当我复制你的代码并逐字运行时,它正确地给了我一个错误(“意外的EOF”),所以也许你关闭了javascript警报?您可以考虑使用console.log而不是警告并在您喜欢的浏览器中了解Javascript控制台。

答案 1 :(得分:4)

WebGL正在为您提供控制台日志消息的大提示:

WebGL:INVALID_OPERATION:useProgram:程序无效 WebGL:INVALID_OPERATION:getAttribLocation:程序未链接

程序未链接,因此无法使用或查询状态。

您的程序似乎确实检查着色器编译正确并且程序已链接,但事实并非如此。您的错误检查代码可能有问题,隐藏了真正的问题。我总是在新编译的着色器和最近链接的程序上调用这两个函数:

getShaderInfoLog

getProgramInfoLog

他们都返回字符串并帮助你找到根本原因。

答案 2 :(得分:3)

我也遇到了这些奇怪的错误,但只在Chrome中而不是在Firefox中:

WebGL: INVALID_OPERATION: getAttribLocation: program not linked
WebGL: INVALID_OPERATION: getUniformLocation: program not linked 
WebGL: INVALID_OPERATION: useProgram: program not valid 
WebGL: INVALID_OPERATION: getAttribLocation: program not linked 
WebGL: INVALID_OPERATION: getUniformLocation: program not linked

我还注意到http://threejs.org/上的大部分示例都将错误抛出(仅限于chrome)。任何通过重新加载源代码,我都能摆脱错误。

答案 3 :(得分:-1)

使用three.js的更新版本,例如来自CDN http://cdnjs.com/libraries/three.js。较旧的版本会在有效代码上抛出上述错误。