# 立方体的纹理贴图及鼠标控制运动

demo实例是在前面立方体的纹理贴图的基础上修改的。不过这里用到了一些别人写好的库。库文件都放在我的github里面，有需要的可以自行下载。所以这里就只列出了跟立方体的纹理贴图demo不一样的地方。这个demo中用到了正射投影及矩阵运算。

#### 1、顶点着色器代码

//浮点数设置为中等精度
precision mediump float;
attribute vec3 apos;
uniform mat4 proj;
attribute vec2 inUV;
letying vec2 outUV;
void main() {
//两个旋转矩阵、顶点齐次坐标连乘
gl_Position=proj*vec4(apos, 1);
//插值处理
outUV=inUV;
}
</script>

#### 2、JavaScript代码

• WebGL上下文的获取及全局变量的定义
let mvp = matrix.identity();
let Vector3 = window.lib3d.Vector3;
let Quaternion = window.lib3d.Quaternion;
function init() {
let lastMouseX = 0, lastMouseY = 0;
let offsetX = 0, offsetY = 0;
let mousedown = false;
//通过getElementById()方法获取canvas画布
const canvas = document.getElementById('webgl');
// resizeCanvas(canvas);
//通过方法getContext()获取WebGL上下文
const gl = canvas.getContext('webgl');
const aspect = canvas.width / canvas.height;
const projectionMatrix = matrix.ortho(-aspect * 1, aspect * 1, -1, 1, 500, -500);
let lastMatrix = matrix.identity();
let tempMatrix = matrix.identity();
//顶点着色器源码

//片元着色器源码
//初始化着色器
initBuffer(gl, program);
rotate(gl,canvas);
}

• 鼠标控制旋转的函数 通过监听鼠标的mousedown,mousemove,mouseup来不断计算运动后的矩阵。在mousemove事件中不断渲染GPU,使的立方体不断的旋转。这里用到了矩阵的四元数运算。
function rotate(gl, canvas, program) {
let lastQ = new Quaternion();
let currentQ = new Quaternion();
mousedown = true;
const { clientX, clientY } = event;
lastMouseX = clientX;
lastMouseY = clientY;
if (!mousedown) return;
const { clientX, clientY } = event;
offsetX = (clientX - lastMouseX);
offsetY = (clientY - lastMouseY);
let l = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
if (l == 0) {
return;
}
let tempQ = Quaternion.fromRotation(
{ x: offsetY / l, y: offsetX / l, z: 0 },
l / 2
);
currentQ = Quaternion.multiplyQuaternions(tempQ, lastQ);
mvp = Quaternion.makeRotationFromQuaternion(currentQ);
render(gl, program);
})
mousedown = false;
// matrix.cloneMatrix(mvp, lastMatrix);
Object.assign(lastQ, currentQ);
})
})
}

• WebGL渲染函数 这里多了个矩阵赋值的操作。
function render(gl, program, count = 36) {
const proj = gl.getUniformLocation(program, 'proj');
gl.uniformMatrix4fv(proj, false, mvp);
//设置清屏颜色为黑色。
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, 0);
}