图形学数学基础 (到这里为止就够了)

  • 基础数学: 线性代数/微积分/统计学
  • 基础屋里: 光学/力学
  • 其他: 信号处理/数值分析
  • 其他2: 美学???

向量

  • 没有特定的起始点, 有方向和长度
  • Magnitude (length) of vector : $   \vec{a}   $
  • Unit Vector
  • 向量加法
  • 向量乘法
    • 点积: (得到投影长度) (满足交换律, 分配律, 常数的结合率), 直角坐标系下等于各维度相乘后相加
      • 法线相关计算
      • 向量投影
        • 向量分解为2个垂直向量之和
      • 向量相对的向前/向后(cos(x))
    • 叉积:
      • x x y -> +z (右手系)
      • 自己×自己得到0向量
      • a x b = -b x a
      • 分配律&结合率仍然存在
      • 作用
        • 判定左右: a x b得到z是正的, 则b在a的左侧 (左右是根据z轴来定的)
        • 判定内外: 封闭平面所有向量逆时针排列后, 计算相同起点的叉积, 得到所有向量相同侧, 则在封闭平面内 (不在同一侧就在平面外)
          • 得到0向量: 在边上, 自己说了算

矩阵

  • 单位矩阵和矩阵的逆
  • 矩阵转置
  • 乘法: 满足分配律和结合率, 不满足交换律
  • 向量点乘可以等价为矩阵操作 (a点b = a转置乘b)
  • 向量叉乘: 等于a向量的dual matrix x b

后续

  • 齐次坐标

作业0

  • 搭环境

    2.2.2 函数体

  • 请观察输出,并尝试解释这些结果(提示:C++ 三角函数运算使用弧度制)。
    • 就是a
    • a/b
    • 根号2
    • cos(180度) == -1, 所以arccos(-1) = 180度 = pi
    • sin(30度) = 0.5

变换

  • 为什么要学变换
  • 2D变换: 旋转/缩放/shear(切变)
  • 齐次坐标
  • 组合变换
  • 3D变换

为什么学习变换

  • 模型(Modeling)变换
    • Transition (摄像机在3D场景里面的移动)
    • Rotation (机器人关节的旋转)
    • Scaling
  • 视图(Viewing)变换
    • (3D to 2D) 投影 (拍照)

2D变换

矩阵 <–> 变换

  • 缩放变换矩阵
    s_x 0
    0   s_y
    
  • 切变
    // 水平方向切变
    1   a
    0   1
    
  • 旋转
    // a: 逆时针旋转角度
    // 通过取(1, 0)和(0, 1)这样2个特殊的点直接求出旋转矩阵
    cos(a)  -sin(a)
    sin(a)  cos(a)
    
    • 以上三种变换称为线性变换 (都可以写成一个矩阵)

齐次坐标

平移变换不能写成矩阵了! (平移变换不是线性变换)

  • 加一个维度! -> 齐次坐标
2D的点, w = 1; 2D的向量, w = 0;
向量+向量 = 向量
点-点 = 向量
点+向量 = 点
点+点 = 无意义

x             x/w
y 都表示2D的点 y/w, 其中w不等于0
w              1
  • 仿射变换(Affine)矩阵
    a b tx
    c d ty
    0 0 1
    

    (因为最后一行都是0 0 1, 所以存储仿射变换矩阵的时候, 都只需要存前2行) (可以看出, 它是先线性变换, 然后平移的!)

  • 逆变换
    逆变换的变换矩阵就是逆矩阵!
    

组合变换

  • 变换顺序? (矩阵乘法不满足交换律)
    • 矩阵变换的计算, 是右结合的!!!
  • 一系列的矩阵相乘 (可以先把所有矩阵乘一块儿, 然后再跟被变换的点/向量相乘, 提高效率)
  • 复杂变换的decomposing(分解)
    • 把旋转中心移动到原点
    • 旋转
    • 移回去

3D变换

  • 3D的齐次坐标一样, 加一维, 变成4维
  • x,y,z分别除以w, 就得到了一个3D空间里的点

Lecture 4 变换 Cont’d

  • 旋转-a, 对应变换矩阵为原矩阵转置
  • 旋转-a, 也等于原矩阵取逆
  • 因此转转变换矩阵是个正交矩阵

3D变换

  • (Viewing transformation)观测变换
    • Viewing (视图变换)/camera transformation
    • Projection
      • Orthographic Proj
      • Perspective Proj
  • 3D变换顺序: 缩放旋转平移
  • 3D旋转 (通过3个方向的旋转, 可以旋转到任意方向)
    • 欧拉角 <–> roll/pitch/yaw
    • Rodrigues’ Rotation Formula: 通过该公式可以把3D的旋转(绕着某个轴转a)分解为3个轴的旋转
      • 公式里的叉乘形式

View/Camera Transformation

想一下拍照:

  • 先把人物摆好(Modeling)
  • 然后找个好的角度(Viewing)
  • 茄子(Projection)
  • 怎么摆摄像机?
    • 相机的位置
    • 相机看向的方向
    • 因为最后得到的照片永远跟相机和被拍摄物体的相对位置有关, 因此我们约定
      • 相机永远放在原点, 以y为up, 看向-z (方便换算)
      • 计算View矩阵:
        • 先写出平移矩阵T
        • 然后求xyz矩阵旋转到相机所在旋转的旋转矩阵的逆矩阵 (因为旋转矩阵是正交矩阵, 所以直接求转置就行了!)R
        • 那么M = RT
  • 然后投影 (3D->2D)
    • 正交投影(不会有近大远小的效果)
      • 让相机放在原点, 看向-z, up为Y, 然后直接把z坐标扔掉(233)
      • 更好的做法:(将一个cuboid变成canonical cube (中心在原点, 边长为2的cube))
        • 把cuboid移动到原点
        • 然后x对应左右, y对应下上, z对应远近
        • 这个变换的矩阵就是正交投影矩阵
    • 透视投影(近大远小)
      • 透视投影: 先把frustum挤为cuboid, 然后做一次cuboid
        • 先把frustum挤为cuboid:
            1. 近平面永远不变, 远平面z值不变, 远平面中心点不变
              • M persp->ortho
            1. M ortho

Chpt6

傅里叶变换和信号处理

  • 任意一个函数都可以表示成很多个不同频率的正弦和余弦函数的和
  • 采样频率越高,能够识别出的函数里的频率就越高
  • 傅里叶变换可以将函数从“时域”变到“频域”
  • 用傅里叶变换变换一张图,可以发现图片的大部分信息都在低频区
  • 高通滤波:让高频信息剩下,可发现高频信息(信号发生了剧烈的变化)代表了图像中的边界
  • 低通滤波:只让低频信息剩下,得到了一张模糊的图!(边界被去掉了)
  • 留下高频和低频之间的信息,得到了一部分边界
  • 推荐课程:《数字图像处理》

aliases(走样)

  • 同样的采样方式,采样不同频率的函数却得到了相同的结果

Filtering = Convolution(卷积) = Averaging(平均)

  • Convolution Theorem: 时域上两个信号的卷积等于频域上的乘积 (时域上两个信号的乘积等于频域上的卷积)
  • 应用于图像处理:
    • 进行滤波时,可以用一个filter在时域上对图像信号直接进行卷积,也可以把filter和图像信号都用傅里叶变换变到频域上,然后进行乘积,然后再逆傅里叶变换回时域的图像

Box Filter(卷积盒)

  • 归一化: 让图像的亮度保持不变
  • ?: Box Filter在时域上面变大了, 它在频域上面会如何变化? (会变小)

Sampling = 重复频域上的内容

  • 冲击函数跟信号相乘, 得到了原始函数在冲击函数处的值 (时域上的乘积)
  • 信号转换到频域, 冲击函数也转换到频域, 两者进行卷积 (频谱被复制粘贴了很多)

    所以采样就是复制粘贴了原始信号的频谱

Aliasing

  • 时域上采样不够快, 频谱上原始信号重叠, 造成走样

降低Aliasing

  • 增加采样率 (更大的分辨率…)
  • 先做模糊(低通滤波, 让频谱上的原始信号频域范围变小, 不容易重叠), 再做采样
    • 低通滤波? (卷积, 也就是平均, 也就是 box filter)
    • 为什么先采样再模糊是错的? 因为先采样会保留重叠的频谱,之后模糊也无法去掉频谱重叠的部分,因此无法降低aliasing
  • 实际中的操作(MSAA: Antialiasing by supersampling)
    • 模糊(得到每一个像素的覆盖率)
    • 采样(直接取该像素的值, 因为就只有一个像素)
  • Milestones
    • FX(Fast Approximate)AA
      • 先得到一个有锯齿的图, 然后把锯齿弄掉(通过图像匹配找到边界, 替换边界为无锯齿的边界)
    • T(Temporal)AA (Tempo[c:]ral)
      • 复用上一帧的边界感知结果, 在这一帧继续使用
  • Super resolution(超分辨率)
    • 512512 -> 10241024, 但是不想看到锯齿, 怎么办
      • 方案1: DL(Deep Learning)SS

Chpt7

画家算法

  • 对所有三角形进行排序,时间复杂度O(nlogn),但是无法解决环型遮挡的问题

Z-Buffer

  • frame buffer保存颜色信息
  • depth buffer保存深度信息

    本文中,我们认为z一直是正的,z越小越近(即往-z的方向看)

Shading

  • 材质
  • Blinn-Phong Reflection Model
  • Diffuse Relection

Chpt 8

  • Blinn-Phong着色模型
  • 着色频率
  • 图形渲染管线

Blinn-Phong模型

漫反射项 (diffuse) (上一节课)

高光项 (specular): 镜面反射方向和观察方向接近的时候才会出现 (半程向量和法线方向接近)

  • 半程向量: 入射方向和观察方向的角平分线方向 (因为半程向量比反射方向要好算) 另:
  • 高光通常认为是白色的
  • 为什么要给高光项加一个指数? 高光很小, 不用指数的话高光范围太大了, 一般用的是100-200的指数

环境光照项 (ambient)

  • 环境光应该是一个常数

着色频率

  • 每个三角形当成一个平面来着色 (该三角形内部的法线是完全相同的), 就会得到一个全是三角形拼成的球面 (Flat Shading)
  • 每个顶点着色 (Gouraud Shading)
  • 逐像素着色: Pixel (Phong Shading)

方案:

  1. 顶点的法线可以认为是它关联的面的法线的平均
  2. 给平面上的法线进行插值 (重心坐标)

实时渲染 (图形渲染管线: 是一系列不同的操作)

  • 输入: 一堆空间里的点
  • 3D空间里的点处理到屏幕上 -> MVP
  • 屏幕上的点连成三角形
  • 光栅化 (Fragment) -> 采样
  • Shaded Fragments(着色) -> Shading
  • 输出: 三角形拼为图片(pixel)

Shader: 指定一个Vertex或者一个Pixel怎么进行着色 (相当于帮程序员省掉了并行的for循环)

  • 推荐工具: Snail Shader Program
  • Fragment Shader (像素着色器)

现代图形学的发展

  • 超复杂的场景
  • GPUs (独显/集显, 异构, 多核)

Texture Mapping (纹理映射)

  • 不同位置可以映射到相同的纹理上
  • 如果知道三角形的每个顶点的uv, 那么三角形内部的每个像素它应该是什么uv呢?
    • 插值: 重心坐标 (Barycentric Coordinates)

chpt 10 几何

光栅化/几何/光线追踪/动画模拟

纹理的应用

  • texture = memory + range query (filtering: 滤波)
    • 环境贴图 (用一张图把四面八方的光都记录下来) 贴图只记录光的方向信息 (假设光来自无限远)
      • Spherical Map -> 球面展开问题, 会变形
      • Cube Map -> 变形少
    • 凹凸贴图/Normal Map
    • 位移贴图 (Displacement mapping): 真的把顶点进行移动
      • Dynamic Tesselation : 动态曲面细分
    • 3D空间中的噪声 -> 山脉
    • ambient occlusion texture map : 环境光遮蔽, 存储阴影信息
    • 3D纹理和体积渲染

几何

  • 几何形体
  • 零件
  • 布料
  • 水花
  • 城市
  • 归类:
    • 隐式几何
      • 用公式or其他表示一个球
      • f(x, y, z) = 0
      • 坏处: 难以sampling
      • 好处: inside/outside 测试很容易
    • 显式几何
      • 很容易采样: f(u,v) => (x=.., y=.., z=..), 把所有uv都走一遍就知道所有的xyz
      • 难以判断某个点是否在表面内/外
  • 更多implicit表示方法
    • algebraic surface: 数学公式表示 (非常不直观)
    • Constructive Solid Geometry (CSG): 各种建模软件/工程制图
    • 距离函数: 空间中的任何一个点到想要表述的几何体的最小距离 (距离可以是正的或者负的)
      • blend不能获得表示运动过程的中间状态
      • 距离函数进行blend之后可以得到运动过程的中间状态
    • Level Set Methods (水平集)
      • 各种医学图像: CT/MRI等等
      • 物理模拟
    • Fractals (分形)
      • 强烈的走样

Chpt 15

Irradiance: Power(watt) per unit area(m^2) (面与光线垂直)