WebGL编程指南-19 透视投影

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();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值