该demo
实例是在前面立方体的纹理贴图
的基础上修改的。不过这里用到了一些别人写好的库。库文件都放在我的github
里面,有需要的可以自行下载。所以这里就只列出了跟立方体的纹理贴图demo
不一样的地方。这个demo
中用到了正射投影及矩阵运算。
# 1、顶点着色器代码
在这里是传入一个已经通过矩阵运算后的矩阵proj
。
<script id="vertexShader" type="x-shader/x-vertex">
//浮点数设置为中等精度
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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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();
//顶点着色器源码
const vertexShaderSource = document.getElementById('vertexShader').innerText;
//片元着色器源码
const fragShaderSource = document.getElementById('fragmentShader').innerText;
//初始化着色器
const program = initShader(gl, vertexShaderSource, fragShaderSource);
initBuffer(gl, program);
rotate(gl,canvas);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 鼠标控制旋转的函数
通过监听鼠标的
mousedown,mousemove,mouseup
来不断计算运动后的矩阵。在mousemove
事件中不断渲染GPU
,使的立方体不断的旋转。这里用到了矩阵的四元数
运算。
function rotate(gl, canvas, program) {
let lastQ = new Quaternion();
let currentQ = new Quaternion();
canvas.addEventListener('mousedown', (event) => {
mousedown = true;
const { clientX, clientY } = event;
lastMouseX = clientX;
lastMouseY = clientY;
canvas.addEventListener('mousemove', (event) => {
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);
})
canvas.addEventListener('mouseup', () => {
mousedown = false;
// matrix.cloneMatrix(mvp, lastMatrix);
Object.assign(lastQ, currentQ);
})
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
参考
WebGL零基础入门教程(郭隆邦) (opens new window)
WebGL 入门与实践 (opens new window)
WebGL官方文档 (opens new window)
← 9、立方体的纹理贴图 11、向量运算 →