2012-08-17 961 views
7

我正在学习WebGL,并且在this教程中与照明有关。我是JavaScript新手,所以我不擅长调试它。我不断收到这些错误,任何人都知道我为什么要得到它们以及如何解决它?WebGL - 无效的操作useProgram

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

回答

7

在这种特殊情况下,原因是您在顶点着色器的末尾丢失了一个闭合},但这并不能解答为什么您没有看到关于为什么着色器无法编译的消息。

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

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

+0

谢谢,我真的想知道如何做到这一点。 – cgasser 2012-08-17 03:23:13

+1

我怀疑这是问题,但只是供参考,只要连接失败的无效程序GL不需要在编译时返回失败。 :-( – gman 2012-08-17 20:00:15

4

WebGL是给你用的控制台日志消息一个很大的提示:

的WebGL:INVALID_OPERATION:useProgram:程序不合法 的WebGL:INVALID_OPERATION:getAttribLocation:程序不挂

程序未联系,因此不能使用或者它的状态查询。

您的程序确实似乎在检查着色器是否正确编译并且程序已链接,但事实并非如此。您的错误检查代码可能有问题,隐藏了真正的问题。我一直呼吁新编译着色器这两个功能,最近连接的程序:

getShaderInfoLog

getProgramInfoLog

他们返回字符串,将有助于你得到的根本原因。

+0

谢谢,我会试试看,看看我能否修复它。 – cgasser 2012-08-17 02:31:47

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)。通过重新下载源代码,我能够摆脱错误。