WebGL入门教程(十七)带纹理的立方体

发表于2017-12-13
评论0 2.3k浏览

在给大家讲解纹理映射的时候,有绘制一个平面的带纹理的图形,现在绘制一个立方体,并为每个面指定纹理。

/**
 * 绘制带纹理的立方体
 * xu.lidong@qq.com
 * */
function main() {
    var gl = getGL();
    var vsFile = "./res/shader/mouserotate.vert.glsl";
    var fsFile = "./res/shader/mouserotate.frag.glsl";
    initShaderProgram(gl, vsFile, fsFile, function (shaderProgram) {
        var n = initVertexBuffers(gl, shaderProgram);
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        initTextures(gl, shaderProgram, n);
    });
}
function initTextures(gl, shaderProgram, n) {
    var texture = gl.createTexture();
    var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler');
    var image = new Image();
    image.onload = function () {
        onLoadTexture(gl, shaderProgram, n, texture, u_Sampler, image);
    };
    image.src = "res/image/sky.jpg";
    return true;
}
function onLoadTexture(gl, shaderProgram, n, texture, u_Sampler, image) {
    var u_MvpMatrix = gl.getUniformLocation(shaderProgram, 'u_MvpMatrix');
    var viewMat = lookAt(3.0, 3.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    var projMat = getPerspectiveProjection(30, 16 / 9, 1, 100);
    var mvpMat = multiMatrix44(projMat, viewMat);
    gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMat);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.bindTexture(gl.TEXTURE_2D, texture);// 绑定纹理对象到激活的纹理单元
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);// 纹理放大方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 纹理缩小方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);// 纹理水平填充方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);// 纹理垂直填充方式
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    gl.uniform1i(u_Sampler, 0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BYTE);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}
function initVertexBuffers(gl, shaderProgram) {
    var vertices = new Float32Array([
        1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
        1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
        1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
        -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
        -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
        1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0
    ]);
    var texCoords = new Float32Array([
        1.0, 1.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, 1.0, 1.0,
        1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
        1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.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
    ]);
    var indices = new Uint8Array([
        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
    ]);
    var indexBuffer = gl.createBuffer();
    initArrayBuffer(gl, shaderProgram, vertices, 3, gl.FLOAT, 'a_Position');
    initArrayBuffer(gl, shaderProgram, texCoords, 2, gl.FLOAT, 'a_TexCoord');
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
    return indices.length;
}
function initArrayBuffer(gl, shaderProgram, data, num, type, attribute) {
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    var a_attribute = gl.getAttribLocation(shaderProgram, attribute);
    gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
    gl.enableVertexAttribArray(a_attribute);
}

如图:

鼠标控制旋转
/**
 * 鼠标控制的立方体的旋转
 * xu.lidong@qq.com
 * */
function main() {
    var gl = getGL();
    var vsFile = "./res/shader/mouserotate.vert.glsl";
    var fsFile = "./res/shader/mouserotate.frag.glsl";
    initShaderProgram(gl, vsFile, fsFile, function (shaderProgram) {
        var n = initVertexBuffers(gl, shaderProgram);
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        initTextures(gl, shaderProgram, n);
    });
}
function initTextures(gl, shaderProgram, n) {
    var texture = gl.createTexture();
    var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler');
    var image = new Image();
    image.onload = function () {
        onLoadTexture(gl, shaderProgram, n, texture, u_Sampler, image);
        var tick = function() {
            onLoadTexture(gl, shaderProgram, n, texture, u_Sampler, image);
            requestAnimationFrame(tick);
        };
        tick();
        initEventHandle();
    };
    image.src = "res/image/sky.jpg";
    return true;
}
gl_rads = [0.0, 0.0];
function initEventHandle(){
    var canvas = document.getElementById("container");
    var dragging = false;
    var lastPos = [-1, -1];
    canvas.onmousedown = function (ev) {
        var x = ev.clientX;
        var y = ev.clientY;
        var rect = ev.target.getBoundingClientRect();
        if (x >= rect.left && x <=rect.right && y >= rect.top && y <= rect.bottom) {
            lastPos = [x, y];
            dragging = true;
        }
    };
    canvas.onmouseup = function (ev) {
        dragging = false;
    };
    canvas.onmousemove = function (ev) {
        var x = ev.clientX;
        var y = ev.clientY;
        if (dragging) {
            var factor = (2 * Math.PI) / 1280;
            var dx = factor * (x - lastPos[0]);
            var dy = factor * (lastPos[1] - y);
            gl_rads[0] = gl_rads[0] + dx % (2 * Math.PI);
            gl_rads[1] = gl_rads[1] + dy % (2 * Math.PI);
        }
        lastPos = [x, y];
    };
}
function onLoadTexture(gl, shaderProgram, n, texture, u_Sampler, image) {
    var viewMat = lookAt(3.0, 3.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    var projMat = getPerspectiveProjection(30, 16 / 9, 1, 100);
    var vpMat = multiMatrix44(projMat, viewMat);
    var modelMat = getRotationMatrix(gl_rads[1], 1, 0, 0);
    var mvpMat = multiMatrix44(vpMat, modelMat);
    modelMat = getRotationMatrix(gl_rads[0], 0, 1, 0);
    mvpMat = multiMatrix44(mvpMat, modelMat);
    var u_MvpMatrix = gl.getUniformLocation(shaderProgram, 'u_MvpMatrix');
    gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMat);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.bindTexture(gl.TEXTURE_2D, texture);// 绑定纹理对象到激活的纹理单元
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);// 纹理放大方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 纹理缩小方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);// 纹理水平填充方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);// 纹理垂直填充方式
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    gl.uniform1i(u_Sampler, 0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BYTE);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}
function initVertexBuffers(gl, shaderProgram) {
    var vertices = new Float32Array([
        1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
        1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
        1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
        -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
        -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
        1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0
    ]);
    var texCoords = new Float32Array([
        1.0, 1.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, 1.0, 1.0,
        1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
        1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.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
    ]);
    var indices = new Uint8Array([
        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
    ]);
    var indexBuffer = gl.createBuffer();
    initArrayBuffer(gl, shaderProgram, vertices, 3, gl.FLOAT, 'a_Position');
    initArrayBuffer(gl, shaderProgram, texCoords, 2, gl.FLOAT, 'a_TexCoord');
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
    return indices.length;
}
function initArrayBuffer(gl, shaderProgram, data, num, type, attribute) {
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    var a_attribute = gl.getAttribLocation(shaderProgram, attribute);
    gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
    gl.enableVertexAttribArray(a_attribute);
}

初始图形跟上面的一样,当按下鼠标沿x轴运动时,立方体绕y轴旋转,当沿y轴移动时,立方体绕x轴旋转。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引