webgl旋转立方体表面上的纹理不会绕自身旋转

时间:2017-02-25 09:05:06

标签: javascript webgl gl-matrix

我需要有关webgl的帮助。

我绘制一个简单的立方体并在立方体的每个面上应用纹理,我在立方体的每个面上旋转纹理,但问题是:

纹理不会围绕自身旋转它围绕左下角的立方体旋转

这是我的相对于轮换的代码:

在顶点着色器中:

    vTextureCoord = ((uTMatrix) * vec4(aTextureCoord, 0.0 , 1.0)).xy;
脚本中的

    mat4.identity(TMatrix);

    mat4.rotate(TMatrix,xRot3, [0.0, 0.0, 1.0]);

1 个答案:

答案 0 :(得分:0)

请参阅this articlethis one

旋转总是在0,0左右所以如果你想围绕其他点旋转你需要先将东西移动到0,0然后在你的情况下你需要将它移回去

// moves texcoords back since they're we moved from where they need to be
mat4.translate(TMatrix, [.5, .5, 0]);

// rotates around 0,0
mat4.rotate(TMatrix,degToRad(xRot3), [0.0, 0.0, 1.0]);

// moves texcoords so they're centered around 0,0
mat4.translate(TMatrix, [-.5, -.5, 0]);  



    var gl;

    function initGL(canvas) {
        try {
            gl = canvas.getContext("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.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
        shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        shaderProgram.TMatrixUniform = gl.getUniformLocation(shaderProgram, "uTMatrix");
        shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    }

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


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

    function mvPopMatrix() {
        if (mvMatrixStack.length == 0) {
            throw "Invalid popMatrix!";
        }
        mvMatrix = mvMatrixStack.pop();
    }


    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
        gl.uniformMatrix4fv(shaderProgram.TMatrixUniform, false, TMatrix);
    }


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

    var xRot1 = 0;
    var xSpeed1 = 0;

    var xRot2 = 0;
    var xSpeed2 = 0;

    var xRot3 = 0;
    var xSpeed3 = 0;

    var z = -5.0;

    var filter = 0;

    var depth = 0;

    var currentlyPressedKeys = {};

    var rot_flag = 0;

    var text_rot_flag = 0;


///////////////////////////////////////// keyboard ///////////////////////////////////////////

    function handleKeyDown(event) {
        currentlyPressedKeys[event.keyCode] = true;

        if (String.fromCharCode(event.keyCode) == "F") {
            filter += 1;
            if (filter == 3) {
                filter = 0;
            }
        }
        
        if(String.fromCharCode(event.keyCode) == "R"){
            if (rot_flag == 0){
                rot_flag = 1;
                xSpeed1 = 20;
                xSpeed2 = 30;
            }
            else{
                rot_flag = 0;
                xSpeed1 = 0;
                xSpeed2 = 0;
            }
        }

        if(String.fromCharCode(event.keyCode) == "O"){
            depth = depth - 1;
        }

        if(String.fromCharCode(event.keyCode) == "I"){
            depth = depth + 1;
        }

        if(String.fromCharCode(event.keyCode) == "T"){
            if(text_rot_flag == 0){
                text_rot_flag = 1;
                xSpeed3 = 15;

            }
            else{
                text_rot_flag = 0;
                xSpeed3 = 0;
            }
        }

    }

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

///////////////////////////////////////// Texture ///////////////////////////////////////////

    function handleLoadedTexture(textures) {

        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

        gl.bindTexture(gl.TEXTURE_2D, textures[0]);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textures[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, textures[1]);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textures[1].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 crateTextures = Array();

    var crateTextures1 = Array();

    function initTexture() {

        var crateImage = document.createElement("canvas");
        crateImage.width = 64;
        crateImage.height = 64;
        var ctx = crateImage.getContext("2d");
        ctx.translate(32, 32);
        ctx.rotate(Math.PI * .25);
        ctx.fillRect(-24, -24, 48, 48);

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

        handleLoadedTexture(crateTextures)


        var crateImage1 = document.createElement("canvas");
        crateImage1.width = 64;
        crateImage1.height = 64;
        var ctx = crateImage1.getContext("2d");
        ctx.fillStyle="red";
        ctx.translate(32, 32);
        ctx.rotate(Math.PI * .25);
        ctx.fillRect(-24, -24, 48, 48);

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

        handleLoadedTexture(crateTextures1)
    }   

    var cubeVertexPositionBuffer;
    var cubeVertexTextureCoordBuffer;
    var cubeVertexIndexBuffer;

    function initBuffers() {

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

            // Back face
            -2.00, -2.00, -2.00,
            -2.00,  2.00, -2.00,
             2.00,  2.00, -2.00,
             2.00, -2.00, -2.00,

            // Top face
            -2.00,  2.00, -2.00,
            -2.00,  2.00,  2.00,
             2.00,  2.00,  2.00,
             2.00,  2.00, -2.00,

            // Bottom face
            -2.00, -2.00, -2.00,
             2.00, -2.00, -2.00,
             2.00, -2.00,  2.00,
            -2.00, -2.00,  2.00,

            // Right face
             2.00, -2.00, -2.00,
             2.00,  2.00, -2.00,
             2.00,  2.00,  2.00,
             2.00, -2.00,  2.00,

            // Left face
            -2.00, -2.00, -2.00,
            -2.00, -2.00,  2.00,
            -2.00,  2.00,  2.00,
            -2.00,  2.00, -2.00,
        ];

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        cubeVertexPositionBuffer.itemSize = 3;
        cubeVertexPositionBuffer.numItems = 24;

//////////////////////////////////////////////////// cube1 //////////////////////////////////////////////////////

        cubeVertexTextureCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);

            var textureCoords = [
                // Front face
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,
                1.000, 0.0,

                // Back face
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,

                // Top face
                0.0, 1.000,
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,

                // Bottom face
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,

                // Right face
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,

                // Left face
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
            ];

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
        cubeVertexTextureCoordBuffer.itemSize = 2;
        cubeVertexTextureCoordBuffer.numItems = 24;

/////////////////////////////////////////////////////// cube2 /////////////////////////////////////////////////////

        cubeVertexTextureCoordBuffer1 = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer1);

            var textureCoords1 = [
                // Front face
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,
                1.000, 0.0,

                // Back face
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,

                // Top face
                0.0, 1.000,
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,

                // Bottom face
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,

                // Right face
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
                0.0, 0.0,

                // Left face
                0.0, 0.0,
                1.000, 0.0,
                1.000, 1.000,
                0.0, 1.000,
            ];

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords1), gl.STATIC_DRAW);
        cubeVertexTextureCoordBuffer1.itemSize = 2;


/////////////////////////////////////////////// vertex ////////////////////////////////////////////////

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


    function drawScene() {

        gl.viewport(0, 0, canvas.width, canvas.height);

        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        mat4.perspective((-50+depth) , canvas.width/canvas.height , 0.1 , 100.0 , pMatrix );

        //////////////////////////////////////////////////////// cube1 /////////////////////////////////////////////

        mat4.identity(mvMatrix);

        mat4.translate(mvMatrix, [4.0, 0.0, -10.0]);

        mat4.scale(mvMatrix, [1, 1, 1]);

        mat4.rotate(mvMatrix, degToRad(xRot1), [0, 1, 0]);


        mat4.identity(TMatrix);

        mat4.scale(TMatrix, [2.0, 2.0, 2.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, 2, gl.FLOAT, false, 0, 0);

        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, crateTextures[1]);

        gl.uniform1i(shaderProgram.samplerUniform, 0);

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

        /////////////////////////////////////////////// cube2 ///////////////////////////////////////////////

        mat4.identity(mvMatrix);

        mat4.translate(mvMatrix, [-4.0, 0.0, -10.0]);

        mat4.scale(mvMatrix, [1, 1, 1]);

        mat4.rotate(mvMatrix, degToRad(xRot2), [1, 0, 0]);

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

        mat4.identity(TMatrix);
        
        if(text_rot_flag){

            mat4.translate(TMatrix,[.5, .5, 0]);
            mat4.rotate(TMatrix,degToRad(xRot3), [0.0, 0.0, 1.0]);
            mat4.translate(TMatrix,[-.5, -.5, 0]);

        }

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer1);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0.0, 0.0);


        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, crateTextures1[0]);
        gl.uniform1i(shaderProgram.samplerUniform, 0);

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

    }

    var lastTime = 0;

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

            xRot1 += (xSpeed1 * elapsed);
            xRot2 += (xSpeed2 * elapsed);
            xRot3 += (xSpeed3 * elapsed);

        }
        lastTime = timeNow;
    }

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

    function webGLStart() {

        var canvas = document.getElementById("canvas");
        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;

        render();
    }
    
    webGLStart();
    
&#13;
<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec2 aTextureCoord;
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;
    varying vec2 vTextureCoord;
    uniform mat4 uTMatrix;

    void main(void) {

        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);

        vTextureCoord = ((uTMatrix) * vec4(aTextureCoord, 0.0 , 1.0)).xy;

        // vTextureCoord = aTextureCoord;
    }

</script>

<script id="shader-fs" type="x-shader/x-fragment">

    precision mediump float;
    varying vec2 vTextureCoord;
    uniform sampler2D uSampler;

    void main(void) {

        gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));

    }

</script>

<canvas id="canvas"></canvas>
<script src="http://stabriz.bol.ucla.edu/hw3/gl-matrix.js"></script>
<script src="http://stabriz.bol.ucla.edu/hw3/webgl-utils.js"></script>
&#13;
&#13;
&#13;

注意,我总是向后看矩阵。我从立方体的顶点开始,然后考虑应用每个矩阵。但是,大多数矩阵数学库使得应用的最后一个矩阵是应用于顶点的第一个矩阵。

换句话说,对我来说这3行

mat4.translate(TMatrix, [.5, .5, 0]);
mat4.rotate(TMatrix,degToRad(xRot3), [0.0, 0.0, 1.0]);
mat4.translate(TMatrix, [-.5, -.5, 0]);  

平均

first translate the vertices by [-.5, -.5, 0]
then rotate around the origin by xRot
then translate the vertices by [.5, .5, 0]

请注意,这与代码的顺序相反,但它实际上会发生什么。

其他人将矩阵视为&#34;改变空间&#34;在这种情况下,它可以按顺序解释

move the origin to [.5, .5, 0]
rotate the origin by xRot
move the origin by [-.5, -.5, 0]