跳转至

GAMES101 Computer Graphics

  • https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
  • https://www.bilibili.com/video/BV1X7411F744

Overview of Computer Graphics (L1)

Review of Linear Algebra (L2)

Transformation - 2D (L3)

逆时针旋转 θ\theta

Rθ=[cosθsinθsinθcosθ]R_\theta = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}

Rθ=Rθ=RθTR_\theta = R_{-\theta} = R_\theta^T

Homogenous Coordinates

  • 2D point (xy1)\begin{pmatrix} x \\ y \\ 1 \end{pmatrix}
  • 2D vector (xy0)\begin{pmatrix} x \\ y \\ 0 \end{pmatrix}
  • (xy1)=(abtxcdty001)(xy1)\begin{pmatrix} x' \\ y' \\ 1 \end{pmatrix} = \begin{pmatrix} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x \\ y \\ 1 \end{pmatrix}
  • (xyw)=(x/wy/w1)\begin{pmatrix} x \\ y \\ w \end{pmatrix} = \begin{pmatrix} x/w \\ y/w \\ 1 \end{pmatrix} 表示一个二维点
  • 两点相加得到中点

变换叠加

M(xy1)=AnA2A1(xy1)M \begin{pmatrix} x \\ y \\ 1 \end{pmatrix} = A_n \cdots A_2 A_1 \begin{pmatrix} x \\ y \\ 1 \end{pmatrix}

Transformation - 3D (L4)

三维旋转

Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ)R_{xyz}(\alpha,\beta,\gamma) = R_x(\alpha) R_y(\beta) R_z(\gamma)

头:上下看 pitch 左右转 yaw 向日葵歪头 roll

Rodrigues’ Rotation Formula

绕轴 n\vec{n} 旋转 α\alphaR(n,α)=cosαI+(1cosα)nnT+sinα(0nznynz0nxnynx0)R(\vec{n}, \alpha) = \cos \alpha \cdot I + (1 - \cos\alpha) \cdot \vec{n} \vec{n}^T+\sin \alpha \cdot \begin{pmatrix} 0 & -n_{z} & n_{y} \\ n_{z} & 0 & -n_{x} \\ -n_{y} & n_{x} & 0 \end{pmatrix}

四元数:为了解决旋转矩阵的插值问题

MVP

model view projection

相机

相机:位置 e\vec{e} 正对的方向 g^\hat{g} 朝上的方向 t^\hat{t}

把相机放到 (0,0,0)(0,0,0) 正对 z-z 方向 头顶为 yy 方向

M=RTM = R \cdot T 表示先将相机放到原点 然后把相机的方向旋转到上述方向

M=RT=(R1)1T=[xg^×t^xtxg0yg^×t^ytyg0zg^×t^ztzg00001]T[100xe010ye001ze0001]M = R \cdot T = (R^{-1})^{-1} \cdot T = \begin{bmatrix} x_{\hat{g}\times \hat{t}} & x_t & x_{-g} & 0 \\ y_{\hat{g}\times \hat{t}} & y_t & y_{-g} & 0 \\ z_{\hat{g}\times \hat{t}} & z_t & z_{-g} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}^T \cdot \begin{bmatrix} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{bmatrix}

正交投影

将原空间放到原点 再在三个轴上缩放到 [1,1][-1, 1]

top/bottom n(靠前的面 成像位置)/f(靠后的面 实际位置) left/right

M=[2rl00002tb00002nf00001][100r+l2010t+b2001n+f20001]M=\begin{bmatrix} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{bmatrix}

透视投影

先将平面缩放到与期望的画布同大小 类似相似三角形 然后zz对应的矩阵行用待定系数法确定 M=[n0000n0000n+fnf0010]M = \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & 1 & 0 \end{bmatrix}

做完这一步之后再使用正交投影将ff处的画面拉到nn处即可

Rasterization - Triangles (L5)

MVP做完之后我们会得到一个 [1,1]3[-1,1]^3 的规范立方体

首先将这个立方体变换到 [0,width],[0,height],[1,1][0,width],[0,height],[-1,1]

M=[w/200w/20h/20h/200100001]M = \begin{bmatrix} w/2 & 0 & 0 & w/2 \\ 0 & h/2 & 0 & h/2 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

然后要将三角形变到像素(这里暂时不考虑深度)

Text Only
1
2
3
for pixel in image {
    pixel.toRasterize = isInside(triangle, pixel.centerX, pixel.centerY)
}

isInside()的实现:判断三角形三边与要判断的点的关系

AP×AB,BP×BC,CP×CA\overrightarrow{AP} \times \overrightarrow{AB},\overrightarrow{BP} \times \overrightarrow{BC},\overrightarrow{CP} \times \overrightarrow{CA} 的结果同向

加速光栅化:不对所有的像素遍历 只遍历可能的像素

Rasterization - Antialiasing (L6)

走样 - alias:以同一种频率采样两种不同频率的信号得到相同的结果

不希望看到的结果 - artifacts

aliasing artifacts 采样的速度跟不上信号变化的速度

解决方案

  • 提高屏幕分辨率
  • 先对三角形做模糊将高频分量抑制 然后再采样(回忆时域卷积-频率相乘)
  • MSAA(multi-sample) 将像素分割为小像素然后计算出颜色比例
  • FXAA(fast-approximate) 对有锯齿的图形作后期处理
  • TAA(temporal) 利用两帧之间的运动信息

其他:超分辨率 用深度学习模型来猜缺失的采样点

Rasterization - Z-Buffer (L7)

画家算法

  • 先画远处的东西 将近处的东西依次覆盖其上
  • 对于三角形不适用

Z-Buffer

  • 并行处理所有的三角形 光栅化后得到像素和深度
  • 得到一个像素的深度后 和depth buffer存储的现有最小深度作比较 如果近的话 就将像素的颜色覆盖到frame buffer

Shading - Illumination (L7 L8)

  • shading - 着色/上色 主要考虑的是一个小三角形面的材质对光线的反射 是局部的
    • shading point 小面的中心点
    • n^\hat{n} 小面的法向量 注意面有厚度/有里外
    • l^\hat{l} 光线入射的方向
    • v^\hat{v} camera的方向
  • shadow - 阴影 考虑的是物体间的遮挡关系

shading Blinn-Phong

  • L=Ls+Ld+LaL = L_s + L_d + L_a
  • specular highlights - 高光 反射
    • 经验判断:出射光和观察方向差不多 也即入射光和观察方向的平均与法向差不多
    • Ls=ksIr2max(0,n^h^)L_s = k_s \frac{I}{r^2} \max (0,\hat{n}\cdot\hat{h})
      • LsL_s 高光反射的光强度
      • ksk_s 高光系数
      • h^=v^+l^2\hat{h} = \frac{\hat{v}+\hat{l}}{2} 半程向量
      • pp p越大 高光越明显 光点越小 一般取64/128
  • diffuse reflection - 漫反射 光线入射后从半球均匀射出
    • Ld=kdIr2max(0,n^l^)L_d = k_d \frac{I}{r^2} \max(0,\hat{n}\cdot\hat{l})
      • LdL_d 漫反射的光强度
      • kdk_d 漫反射系数 越大表示漫反射越强 也就是越亮
      • Ir2\frac{I}{r^2} 点光源发出的光强平方衰减
      • cosθ=n^l^\cos\theta = \hat{n}\cdot\hat{l} 入射光线越倾斜 小面得到光强就越小
      • max(0,n^l^)\max(0,\hat{n}\cdot\hat{l}) 考虑光线从物体后方入射 这时没有反射
  • ambient lighting - 环境光 假定是常数
    • La=kaIaL_a = k_a I_a

Shading - Frequencies (L8)

  • Flat shading - shade each triangle
    • 选取三角形的法向
  • Gouraud shading - shade each vertex
    • 用顶点周围的三角形面的法向做平均得到方向
  • Phong shading - shade each pixel
    • 用重心坐标差值得到

Shading - Graphics (Real-time Rendering) Pipeline (L8)

  • Application
  • Vertex Processing (Programmable: for each vertex)
  • Triancle Processing
  • Rasterization
  • Fragment Processing (Programmable: for each pixel/fragment)
  • Framebuffer Operations
  • Display

在线编写shader https://www.shadertoy.com

Shading - Texture Mapping (L8 L9)

  • 目的:将屏幕上的一个像素着色
  • 过程:
    • 找到屏幕上的像素中心对应的三维三角形 (xsysxyzx_sy_s \to xyz)
    • 找到这个像素中心在三角形的重心坐标系中的位置 (xyzαβγxyz \to \alpha\beta\gamma)
    • 用材质上面的像素点的颜色去插值得到需要显示的颜色 (αβγuv\alpha\beta\gamma \to uv) 如果材质的三角形顶点上有属性 也可以插值得到屏幕上那一点的属性
      • 颜色插值方法
        • Nearest 点在材质的那个像素里面 就用这个像素的颜色
        • Bilinear 点所在位置四周的像素的颜色做一个位置平均(先上下 再左右)

遇到的问题

  • 采样走样:远处的像素看不出纹理
    • 发生原因:远处屏幕上一个像素应该用纹理的一个很大的区域来平均 而不是直接取一个点附近的四个像素平均 这样不足以代表这个像素
    • 解决方案:使用Mipmap
      • 提前对纹理进行正方形区域的平均值计算 存储多占用33% 但是查询非常快
      • 在查询时可以查询两层之间的值 只要做插值就行
  • Mipmap斜的"像素"看起来很奇怪
    • 原因:Mipmap只支持正方形查询
    • 解决方案:各向异性过滤 Anisotropic Filtering
      • 在纹理的存储图中存储矩形 存储量增大
      • EWA filtering 使用椭圆切线处的纹理采样

Barycentric Coordinates

点在三角形内部的话 0<α,β,γ<10 < \alpha,\beta,\gamma < 1

α=(xxB)(yCyB)+(yyB)(xCxB)(xAxB)(yCyB)+(yAyB)(xCxB)β=(xxC)(yAyC)+(yyC)(xAxC)(xBxC)(yAyC)+(yByC)(xAxC)γ=1αβ\begin{aligned} \alpha &=\frac{-\left(x-x_{B}\right)\left(y_{C}-y_{B}\right)+\left(y-y_{B}\right)\left(x_{C}-x_{B}\right)}{-\left(x_{A}-x_{B}\right)\left(y_{C}-y_{B}\right)+\left(y_{A}-y_{B}\right)\left(x_{C}-x_{B}\right)} \\ \beta &=\frac{-\left(x-x_{C}\right)\left(y_{A}-y_{C}\right)+\left(y-y_{C}\right)\left(x_{A}-x_{C}\right)}{-\left(x_{B}-x_{C}\right)\left(y_{A}-y_{C}\right)+\left(y_{B}-y_{C}\right)\left(x_{A}-x_{C}\right)} \\ \gamma &=1-\alpha-\beta \end{aligned}

Application of Textures

将环境光记录在球面上