WebGL定向照明 - 照亮立方体(照明不能正常工作)

时间:2014-10-06 09:13:04

标签: javascript

我现在已经重写了几次这段代码了,但是出现了与灯光相同的问题......我将这段代码与我几个月前编写的代码进行比较,这些代码执行相同的操作(点亮一个多维数据集)和我似乎没有遗漏任何东西。

立方体的正面和背面都没问题,但是左右两边都表现得很奇怪,而且顶部和底部......看起来像法线一样有问题,但它们没问题......检查它们并重写几次以确定。

示例:http://gamedevelopment.t15.org/WebGL/WebGL%20Examples/Example%207%20-%20Ambient%20And%20Directional%20Light/

着色器:

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

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

        uniform vec3 uAmbientLightColor;

        uniform vec3 uDirectionalLightColor;
        uniform vec3 uLightDirection;

        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 = aVertexNormal * uNMatrix;
                float directionalLightWeighting = max(dot(uLightDirection, transformedNormal), 0.0);
                vLightWeighting = uAmbientLightColor + uDirectionalLightColor * directionalLightWeighting;
            }
        }
    </script>

    <script id="fShader" 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>

代码:

var gl;
function initGL(canvas){
    try{
        gl = canvas.getContext("webgl");
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
    }catch(e){
        console.log("WebGL context was not initialized.");
        return null;
    }
}

function getShader(id, gl){
    var shaderScript = document.getElementById(id);
    if(!shaderScript){
        console.log(id + " - invalid shader id.");
    }

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

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

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

    if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
        console.log(id + " error: " + gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

var shaderProgram;
function initShaders(){
    var vShader = getShader("vShader", gl);
    var fShader = getShader("fShader", gl);

    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vShader);
    gl.attachShader(shaderProgram, fShader);
    gl.linkProgram(shaderProgram);

    if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)){
        console.log("Shader program was not linked.");
        return null;
    }

    gl.useProgram(shaderProgram);

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

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

    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.lightDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightDirection");
    shaderProgram.directionalLightColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalLightColor");
    shaderProgram.ambientLightColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientLightColor");
    shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting");
}

var cubeVertexPositionBuffer, cubeVertexIndexBuffer, cubeVertexTextureCoordBuffer, cubeVertexNormalBuffer;
function initBuffers(){
    // Cube.
    cubeVertexPositionBuffer = gl.createBuffer();
    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,

        // 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,

        // 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,

        // 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
    ]
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    cubeVertexPositionBuffer.itemSize = 3;
    cubeVertexPositionBuffer.rotAngle = 0;

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

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

    cubeVertexIndexBuffer.numItems = 36;

    cubeVertexTextureCoordBuffer = gl.createBuffer();
    textureCoords = [
        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0,

        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0,

        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0,

        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0,

        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0,

        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0,
        0.0, 1.0
    ];
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);

    cubeVertexTextureCoordBuffer.itemSize = 2;

    cubeVertexNormalBuffer = gl.createBuffer();
    var normals = [
        0.0, 0.0, 1.0,
        0.0, 0.0, 1.0,
        0.0, 0.0, 1.0,
        0.0, 0.0, 1.0,

        0.0, 0.0, -1.0,
        0.0, 0.0, -1.0,
        0.0, 0.0, -1.0,
        0.0, 0.0, -1.0,

        -1.0, 0.0, 0.0,
        -1.0, 0.0, 0.0,
        -1.0, 0.0, 0.0,
        -1.0, 0.0, 0.0,

        1.0, 0.0, 0.0,
        1.0, 0.0, 0.0,
        1.0, 0.0, 0.0,
        1.0, 0.0, 0.0,

        0.0, 1.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 1.0, 0.0,

        0.0, -1.0, 0.0,
        0.0, -1.0, 0.0,
        0.0, -1.0, 0.0,
        0.0, -1.0, 0.0,
    ]
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);

    cubeVertexNormalBuffer.itemSize = 3;
}

var pMatrix = mat4.create();
var mvMatrixStack = [];
var mvMatrix = mat4.create();
var nMatrix = mat3.create();
function setMatrixUniforms(){
    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    mat3.normalFromMat4(nMatrix, mvMatrix);
    gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, nMatrix);
}

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

function mvPopMatrix(){
    mvMatrix = mvMatrixStack.pop();
}

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

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

    // Draw cube.
    mvPushMatrix();

    mat4.translate(mvMatrix, mvMatrix, [0.0, 0.0, -7.0]);
    mat4.rotate(mvMatrix, mvMatrix, degToRad(cubeVertexPositionBuffer.rotAngle), [0.0, 1.0, 0.0]);

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

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

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

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
    gl.uniform1i(shaderProgram.samplerUniform, 0);

    // Lighting.
    gl.uniform1i(shaderProgram.useLightingUniform, true);
    gl.uniform3f(shaderProgram.ambientLightColorUniform, 0.2, 0.2, 0.2);
    gl.uniform3f(shaderProgram.directionalLightColorUniform, 0.8, 0.8, 0.8);
    var lightingDirection = [0.0, 0.0, -1.0];
    var adjustedLD = vec3.create();
    vec3.normalize(adjustedLD, lightingDirection);
    vec3.scale(adjustedLD, adjustedLD, -1);
    gl.uniform3fv(shaderProgram.lightDirectionUniform, adjustedLD);

    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;

        if(cubeVertexPositionBuffer.rotAngle > 360) cubeVertexPositionBuffer.rotAngle = 0;
        cubeVertexPositionBuffer.rotAngle += 45 * elapsed / 1000;
    }
    lastTime = timeNow;
}

function tick(){
    animate();
    drawScene();
    requestAnimFrame(tick);
}

function degToRad(degrees){
    return degrees * Math.PI / 180;
}

var cubeTexture;
function initTextures(){
    cubeTexture = gl.createTexture();
    cubeTexture.image = new Image();
    cubeTexture.image.onload = function(){
        handleLoadedTexture(cubeTexture);
    }
    cubeTexture.image.src = "textures/cube.png";
}

function handleLoadedTexture(texture){
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.bindTexture(gl.TEXTURE_2D, null);
}

function webGLStart(){
    initGL(document.getElementById("glCanvas"));
    initShaders();
    initBuffers();
    initTextures();

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

    tick();
}

照明代码是:initShaders()中的引用,initBuffers()中的普通和顶点缓冲区,以及drawScene()中的均匀变量,还在setMatrixUniforms()中创建normalMatrix。

如果有人花时间看看它并告诉我出了什么问题,我将感激不尽。

1 个答案:

答案 0 :(得分:0)

好吧..再次生气并重写代码,然后一点一点地用一些工作示例中的代码替换代码......伙计们告诉我!问题出在顶点着色器中,请告诉我

之间的区别
vec3 transformedNormal = uNMatrix * aVertexNormal;

vec3 transformedNormal = aVertexNormal * uNMatrix;

......第二个创建了这个bug,但没有任何意义......我的乘法顺序有多重要。