# 模型、视图、投影矩阵

各种矩阵用途:

  • 模型矩阵:获取原始模型数据,并在3D世界空间移动。
  • 投影矩阵:将世界空间坐标转换为裁剪空间坐标。模拟相机的效果。
  • 视图矩阵:负责移动场景中的对象以模拟相机位置的变化。改变观察者当前能够看到的内容。

# 裁剪空间

这是一个中心点位于 (0, 0, 0),角落范围在 (-1, -1, -1) 到 (1, 1, 1) 之间,2 个单位宽的立方体。该剪裁空间被压缩到一个二维空间并栅格化为图像(可以理解为投影)。

顶点着色器将点转换到裁剪空间的特殊坐标系上。

裁剪空间内的坐标为归一化坐标。只有裁剪空间内的元素才会被渲染。

裁剪空间中z+远离观察者

A 3d graph showing clip space in WebGL.

# 齐次坐标

(x,y,z)增加第四个坐标(x,y,z,w)变为齐次坐标,w作为其他分量的除数。将透视的概念引入坐标系,允许两条平行线在延伸到远方时相交。

# 模型转换

将模型数据和其他坐标转换到裁剪空间。

例如立方体表面颜色和构成单个多边形的顶点位置顺序组成。这些位置和颜色存储在GL缓冲区,分发到着色器分别进行操作。

计算单个模型矩阵。该矩阵表示要在组成模型的每个点上执行转换。

# 除以W

获取立方体模型透视的简单方法,将Z坐标复制到W上,w可以描述透视。

# 简单投影

// 单位阵
var identity = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1,
];

MDN.multiplyPoint(identity, [2, 3, 4, 1]);
//> [2, 3, 4, 1]

// 移动一格
var copyZ = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 1,
  0, 0, 0, 0,
];

MDN.multiplyPoint(copyZ, [2, 3, 4, 1]);
//> [2, 3, 4, 4]

// 缩放因子
var scaleFactor = 0.5;

var simpleProjection = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, scaleFactor,
  0, 0, 0, scaleFactor,
];

MDN.multiplyPoint(simpleProjection, [2, 3, 4, 1]);
//> [2, 3, 4, 2.5]

通过scaleFactor,可以控制投影的远近程度:

// 确保以相反的顺序读取转换矩阵
gl_Position = projection * model * vec4(position, 1.0);

# 透视矩阵(推导下)

OpenGL透视投影 (opens new window)

透视投影将视椎体映射为立方体。

已知信息:

  • 假设相机位置位于原点,t、b、l、r分别位于视椎体近面上下左右四条边的y、y、x、x坐标,n为近面z坐标,f为远面坐标。

  • 标准化设备(NDC)坐标:(-1,-1,-1)到(1,1,1)

是由数学公式推导出来的:

  • 首先,将视椎体的视野坐标Xe,Ye投影到近裁剪面Xp,Yp
  • 由于视野坐标是右手坐标系,NDC为左手坐标系,所以Z要反向,Wc可定义为-Ze,矩阵第四行确定
  • 将投影坐标Xp,Yp线性变换为NDC近平面坐标Xn,Yn
  • 然后得到Xn与Xe,Ze,Yn与Ye,Ze的推算关系,确定矩阵的前两行
  • 计算矩阵第四行
MDN.perspectiveMatrix = function(fieldOfViewInRadians, aspectRatio, near, far) {

  var f = 1.0 / Math.tan(fieldOfViewInRadians / 2);
  var rangeInv = 1 / (near - far);

  return [
    f / aspectRatio, 0,                          0,   0,
    0,               f,                          0,   0,
    0,               0,    (near + far) * rangeInv,  -1,
    0,               0,  near * far * rangeInv * 2,   0
  ];
}

# 视图矩阵

# 核心概念

# 着色器程序

# 顶点着色器

用于处理每个顶点的属性和位置信息。

可以定义顶点的位置、颜色、纹理属性,以及模型矩阵、投影矩阵等等。

# 片段着色器

顶点着色器处理完图形的顶点后,会被将绘制图形的每个像素点调用一次。用于确定像素的颜色。

指定应用到像素的纹理元素,获取纹理元素的颜色,然后将适当的光照应用于颜色。颜色存储在gl_FragColor中。

# uniform变量

类似于JS的全局变量,用于在顶点着色器和片段着色器中传递数据,例如:

  • 变换矩阵
  • 光照属性
  • 纹理对象

# 缓冲区

WebGL中,不同的缓冲区存储不同类型的数据。常用的缓冲区类型如下:

  1. 顶点缓冲区:存储顶点数据,顶点位置、法线、颜色和纹理坐标
  2. 索引缓冲区:也称为元素缓冲区,用于存储顶点索引数据,指定如何连接顶点以形成图元
  3. 像素缓冲区:用于高效读取和写入像素数据,例如离屏渲染、渲染到纹理等等
  4. 帧缓冲区:用于渲染到纹理和离屏渲染

# 纹理

纹理单元:存储纹理对象的容器,每个纹理单元可以绑定一个纹理对象。

纹理采样器:在着色器中用于访问纹理数据的特殊类型。可以根据纹理坐标从纹理对象中获取对应位置的纹理像素值。

# 光照

光源类型:

  • 环境光:均匀地照射物体的每一个面
  • 方向光:是一束从固定方向照射过来的光
  • 点光源:光线从一个点发射,向四面八方发射

法线矩阵将顶点法线从世界坐标系转换到视图坐标系。

法线矩阵计算步骤:

  1. 获取模型视图矩阵:它包括了物体的平移、旋转和缩放
  2. 计算法线矩阵:法线矩阵是模型视图矩阵的逆矩阵的转置
  3. 将法线矩阵传递给着色器

# 动画纹理

用视频帧作为纹理

Last Updated: 12/23/2024, 4:18:13 AM