在建立觀察矩陣方面,glMatrix 的 mat4
提供了 lookAt
函式,第一個參數是輸出矩陣,也會是函式的傳回值,之後的參數分別為 eye
、center
與 up
,分別為觀察者位置、看向的中心、頭頂方向的向量,因此,要建立一個新的觀察矩陣可以如下:
let lookTrans = mat4.lookAt(
mat4.create(),
[0, viewy, 0],
[0, 0, 1],
[0, 1, 0]
);
例如,可以很快地將〈觀察矩陣〉中的範例改寫為使用 glMatrix,與矩陣操作相關的部份如下:
let viewy = 0.5;
let lookTrans = mat4.lookAt(mat4.create(), [0, viewy, 0], [0, 0, 1], [0, 1, 0]);
canvas.addEventListener('mousedown', () => {
viewy *= -1;
mat4.identity(lookTrans);
mat4.lookAt(lookTrans, [0, viewy, 0], [0, 0, 1], [0, 1, 0]);
});
let transformation = mat4.create();
let i = 0;
function drawCube() {
i++;
mat4.identity(transformation);
mat4.rotateZ(transformation, lookTrans, 0.025 * i);
mat4.translate(transformation, transformation, [0.25, 0, 0]);
mat4.rotateX(transformation, transformation, 0.5);
mat4.rotateY(transformation, transformation, 0.5);
renderer.uniformMatrix4fv('transformation', transformation);
renderer.clear();
renderer.bindBuffer(GL.ARRAY_BUFFER, vertBuffer);
renderer.bufferSubData(GL.ARRAY_BUFFER, 0, geometry.verteices);
renderer.render(cube);
requestAnimationFrame(drawCube);
}
drawCube();
可以點一下完整的範例網頁來看看結果。
若要建立正交投影矩陣,可以使用 mat4
的 ortho
,第一個參數是輸出矩陣,也會是函式的傳回值,之後的參數分別為 left
、right
、bottom
、top
、near
、far
,小心別設錯就是了,例如,將〈正交投影矩陣〉中的範例,改寫使用 glMatrix,與矩陣操作相關的部份如下:
renderer.uniformMatrix4fv('projection',
mat4.ortho(
mat4.create(),
-canvas.clientWidth / 2, // 左邊界
canvas.clientWidth / 2, // 右邊界
-canvas.clientHeight / 2, // 下邊界
canvas.clientHeight / 2, // 上邊界
0.1, // 近面
canvas.clientWidth // 遠面
)
);
let zRotation = mat4.create();
let transformation = mat4.create();
function drawCube() {
mat4.rotateZ(zRotation, zRotation, 0.025);
mat4.identity(transformation);
mat4.translate(transformation, zRotation, [canvas.clientWidth / 8, 0, -canvas.clientWidth / 2]);
mat4.rotateX(transformation, transformation, 0.5);
mat4.rotateY(transformation, transformation, 0.5);
renderer.uniformMatrix4fv('transformation',
transformation
);
renderer.clear();
renderer.bindBuffer(GL.ARRAY_BUFFER, vertBuffer);
renderer.bufferSubData(GL.ARRAY_BUFFER, 0, geometry.verteices);
renderer.render(cube);
requestAnimationFrame(drawCube);
}
drawCube();
可以點一下完整的範例網頁來看看結果。
類似地,若要建立透視投影矩陣,可以使用 perspective
,第一個參數是輸出矩陣,也會是函式的傳回值,之後的參數分別為 fovy
、aspect
、near
、far
,例如,例如,將〈透視投影矩陣〉中的範例,改寫使用 glMatrix,與矩陣操作相關的部份如下:
const perspective = mat4.perspective(
mat4.create(),
Math.PI / 4, // fovy
canvas.clientWidth / canvas.clientHeight, // 寬高比
0.1, // 近面
canvas.clientWidth // 遠面
);
const ortho = mat4.ortho(
mat4.create(),
-canvas.clientWidth / 2, // 左邊界
canvas.clientWidth / 2, // 右邊界
-canvas.clientHeight / 2, // 下邊界
canvas.clientHeight / 2, // 上邊界
0.1, // 近面
canvas.clientWidth // 遠面
);
let projection = perspective;
renderer.uniformMatrix4fv('projection', projection);
let changeProjection = false;
canvas.addEventListener('mousedown', () => {
changeProjection = true;
});
let transformation = mat4.create();
let i = 0;
function drawCube() {
if(changeProjection) {
projection = projection === perspective ? ortho : perspective;
renderer.uniformMatrix4fv('projection', projection);
changeProjection = false;
}
i++;
mat4.identity(transformation);
mat4.translate(transformation, transformation, [0, 0, -canvas.clientWidth / 2]);
mat4.rotateY(transformation, transformation, 0.025 * i);
mat4.translate(transformation, transformation, [canvas.clientWidth / 4, 0, 0]);
mat4.rotateX(transformation, transformation, -0.25);
mat4.rotateZ(transformation, transformation, 0.25);
renderer.uniformMatrix4fv('transformation', transformation);
renderer.clear();
renderer.bindBuffer(GL.ARRAY_BUFFER, vertBuffer);
renderer.bufferSubData(GL.ARRAY_BUFFER, 0, geometry.verteices);
renderer.render(cube);
requestAnimationFrame(drawCube);
}
drawCube();
可以點一下完整的範例網頁來看看結果。