1.demo效果
如上,通过透视投影矩阵创建了左右两排三角形,呈现在页面中
2.透视投影
上一篇文章中说可视空间分为 正射投影 和 透视投影 ,在正射投影中不管图形与视点的距离是远还是近,图形有多大那么画出来的图形就有多大,但透视投影根据成像原理画出来的图会近大远小,更具有深度感。
如上图,透视投影也会通过near和far设置近裁剪面和远裁剪面。与正射投影不一样的是它有一个fov来定义视角的大小,还通过一个aspect来定义近裁剪面的宽高比。通过这四个参数我们同样可以确定一个棱锥状的空间,这个空间就是透视投影的 可视空间 ,即上图中绿色的空间。同样,在可视空间中的物体才能被观察到。
#3.Matrix4.setPerspective()函数
cuon-matrix.js 提供的 Matrix4.setPerspective() 函数,该函数用来设置 透视投影矩阵
函数功能:根据参数fov、aspect、right、near、far计算透视投影矩阵,将其存储在Matrix4中
-----------------------------------------------------------------------------------
调用示例:Matrix4.setPerspective(fov, aspect, near, far)
-----------------------------------------------------------------------------------
参数
fov 指定垂直视角,即可视空间顶面和底面的夹角,必须大于0
aspect 指定近裁剪面的宽高比
near, far 指定近裁剪面和远裁剪面的位置,即可视空间的近边界和远边界
(near和far必须都大于0)
-----------------------------------------------------------------------------------
返回值 无
3.demo代码
const VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ModelMatrix;
uniform mat4 u_ViewMatrix;
varying vec4 v_Color;
void main() {
gl_Position = u_ModelMatrix *u_ViewMatrix* a_Position;
v_Color = a_Color;
}
`;
const FSHADER_SOURCE = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
const main = () => {
debugger;
//获取绘制dom
const canvas = document.getElementById("webgl");
//获取canvas上下文
const gl = canvas.getContext("webgl");
//初始化着色器
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
return console.log("Failed to initialize shaders.");
}
const initVertexBuffers = (gl) => {
const u_ViewMatrix = gl.getUniformLocation(gl.program, "u_ViewMatrix");
const u_ModelMatrix = gl.getUniformLocation(gl.program, "u_ModelMatrix");
const viewMatrix = new Matrix4();
const modelMatrix = new Matrix4();
modelMatrix.setPerspective(30, canvas.width / canvas.height, 1, 100);
viewMatrix.setLookAt(0.0, 0.0, 5.0, 0, 0, -100, 0, 1, 0);
//类型化数组设置顶点坐标
const vertices = new Float32Array([
0.75, 1.0, -4.0, 0.4, 1.0, 0.4,
0.25, -1.0, -4.0, 0.4, 1.0, 0.4,
1.25,-1.0, -4.0, 1.0, 0.4, 0.4,
0.75, 1.0, -2.0, 1.0, 1.0, 0.4,
0.25, -1.0, -2.0, 1.0, 1.0, 0.4,
1.25, -1.0, -2.0, 1.0, 0.4, 0.4,
0.75, 1.0, 0.0, 0.4, 0.4, 1.0,
0.25, -1.0, 0.0, 0.4, 0.4, 1.0,
1.25,-1.0, 0.0, 1.0, 0.4, 0.4,
-0.75, 1.0, -4.0, 0.4, 1.0, 0.4,
-1.25, -1.0, -4.0, 0.4, 1.0, 0.4,
-0.25, -1.0, -4.0, 0.4, 1.0, 0.4,
-0.75, 1.0, -2.0, 1.0, 1.0, 0.4,
-1.25, -1.0, -2.0, 1.0, 1.0, 0.4,
-0.25,-1.0, -2.0, 1.0, 0.4, 0.4,
-0.75, 1.0, 0.0, 0.4, 0.4, 1.0, -1.25, -1.0, 0.0, 0.4, 0.4, 1.0, -0.25,
-1.0, 0.0, 1.0, 0.4, 0.4,
]);
const n = 18; //点的个数
//创建缓冲区对象
const vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log("Failed to create the buffer object");
return -1;
}
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
//向缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
const a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 4 * 6, 0);
//链接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 4 * 6, 4 * 3);
gl.enableVertexAttribArray(a_Color);
return n;
};
const n = initVertexBuffers(gl);
if (n < 0) {
console.error("n<0");
return;
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//清空canvas
gl.clear(gl.COLOR_BUFFER_BIT);
//绘制一个点
gl.drawArrays(gl.TRIANGLES, 0, n);
};
main();