计算机图形学

矩阵与向量

点乘与叉乘

点乘 dot(A,B)

  1. 两单位向量的点乘 = 两单位向量夹角的cos值 a · b = abcosθ = cosθ
  2. 分量相乘后相加;a=vec(x1,y1),b=vec(x2,y2),则a dot b = x1x2 + y1y2,a dot b =|a||b|cosθ
  3. a dot b 为b在a上的投影长度与b模长的乘积

$$
\vec{a} \cdot \vec{b} =
\begin{pmatrix}
x_a & y_a & z_a
\end{pmatrix}
\begin{pmatrix}
x_b \\
y_b \\
z_b
\end{pmatrix}
$$

意义:

  1. 两单位向量点乘的值范围在[-1,1],描述两单位向量的“接近程度”,垂直or同向or反向
  2. 找投影:某世界坐标与某单位向量点乘,结果为该世界坐标在该向量上的投影点的坐标

叉乘 A cross B

A X B = ABsinφ,右手先穿过A再穿过B,大拇指方向为叉乘方向

$$ \vec{a} \times \vec{b} = \begin{pmatrix} y_a z_b – y_b z_a \\ z_a x_b – x_a z_b \\ x_a y_b – y_a x_b \end{pmatrix} $$

$$
\vec{a} \times \vec{b} = A^* \vec{b} =
\begin{pmatrix}
0 & -z_a & y_a \\
z_a & 0 & -x_a \\
-y_a & x_a & 0
\end{pmatrix}
\begin{pmatrix}
x_b \\
y_b \\
z_b
\end{pmatrix}
$$

意义:
1.同一个平面内确定方向(正负),是左还是右(比如b在a的逆时针方向)
2.判断一个点是否在图形内部 。如下图,通过CA,CP可以判断P在AC逆时针方向,同理判断三个,都是一个方向的话就在内部,可以得到P的位置关系

矩阵

矩阵乘法

什么时候可以乘? (M x N)(N x P) = (M x P),中间相同即可。计算就是找对应的向量点乘出结果

  • 无交换率,有结合分配率
  • (AB)C=A(BC)
  • A(B+C)=AB+AC
  • (A+B)C=AC+BC
  • (AB)T=BTAT

作用:图形变换

变换基础

线性变换



$$
\begin{pmatrix} x’ \\ y’ \end{pmatrix} = \begin{pmatrix} s_x & 0 \\ 0 & s_y \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix}
$$
其中Sx和Sy为缩放比例


$$
\begin{pmatrix} x’ \\ y’ \end{pmatrix} = \begin{pmatrix} 1 & a \\ 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix}
$$
x=x + ay y=y 转换结果如上
$$
R_θ = \begin{pmatrix} cosθ & -sinθ \\ sinθ & cosθ \end{pmatrix}
$$
即:
$\begin{pmatrix} x’ \\ y’ \end{pmatrix} = \begin{pmatrix} cosθ & -sinθ \\ sinθ & cosθ \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix}$

对于旋转,如果旋转-θ,带入后发现$ R_{-θ} = \begin{pmatrix} cosθ & sinθ \\ -sinθ & cosθ \end{pmatrix} = R_θ^T = R_θ^{-1}(逆相当于逆变换)$

问题,没有办法表示平移变化,平移不属于线性变换。这样导致形式不统一,为了解决引入了齐次变换



$\begin{pmatrix} x’ \\ y’ \end{pmatrix} = \begin{pmatrix} A & B \\ C & D \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} + \begin{pmatrix} t_x \\ t_y \end{pmatrix}$

此时,对应的变换如下,没有只用一个矩阵表示平移变换
x’ = x + tx
y’ = y + ty

齐次变换

添加一个新的第三坐标 (w-coordinate)
其中 2D 点 表示为 $\begin{pmatrix} x & y & 1 \end{pmatrix}^T$,如下方有1之后就可以表示平移变换了
2D 向量 表示为$\begin{pmatrix} x & y & 0 \end{pmatrix}^T$,因为向量经过平移变换不变,用0保护

$
\begin{pmatrix} x’ \\ y’ \\ 1 \end{pmatrix} =
\begin{pmatrix}
1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{pmatrix}
\cdot \begin{pmatrix} x \\ y \\ 1 \end{pmatrix} =
\begin{pmatrix} x + t_x \\ y + t_y \\ 1 \end{pmatrix}
$

此时也有规律了,看新加的1,此时向量+向量 = 向量,点-点 = 向量 ,点+向量=点 完美符合

对于点+点,扩充定义为中点,根据定义$ \begin{pmatrix} x \\ y \\ w \end{pmatrix} = \begin{pmatrix} x/w \\ y/w \\ 1 \end{pmatrix}$,w≠0

好处:统一了格式,代价:增加了一点存储(但几乎可以忽略不计)

仿射变换

定义:线性变换+位移的一个变换。表示方法就有上面两种了

线性变换+位移变换

$\begin{pmatrix} x’ \\ y’ \end{pmatrix} = \begin{pmatrix} A & B \\ C & D \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} + \begin{pmatrix} t_x \\ t_y \end{pmatrix}$

齐次变换

$
\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}
$

对于齐次变换变换细节,把左上4个小块动作线性变换的4个块使用理解即可

逆变换

表示一个相反变换。比如说我旋转θ,那么逆矩阵就是旋转-θ,位移之类变换同理。

合成变换

可以把很多小的变换组合成为一个大的变换,这样简洁高效。

$A_n(\cdots A_2(A_1(x))) = A_n \cdots A_2 \cdot A_1 \cdot \begin{pmatrix} x \\ y \\ 1 \end{pmatrix}$

分解变换

旋转一般都是默认以原点为中心,那么怎么做到以图形特定端点旋转呢?可以先把端点移动到原点再旋转在变回去

变换高级

三维变换

类似的,3D的点和向量可以用如下方式表示

3D 点 表示为 $\begin{pmatrix} x & y & z & 1 \end{pmatrix}^T$
3D 向量 表示为$\begin{pmatrix} x & y & z & 0 \end{pmatrix}^T$

那么,此时3D的仿射变换也可以类似的表示如下,最后一行就还是空的

$\begin{pmatrix} x’ \\ y’ \\ z’ \\ 1 \end{pmatrix} = \begin{pmatrix} a & b & c & t_x \\ d & e & f & t_y \\ g & h & i & t_z \\ 0 & 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix}$

对于旋转,绕 x ,y , z轴 旋转 结果如下,旋转方向通过右手定则判断(大拇指于轴正方向平行),注意y的角度是反的(右手法则推导得到的)

$ R_x(\alpha) =
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos\alpha & -\sin\alpha & 0 \\
0 & \sin\alpha & \cos\alpha & 0 \\
0 & 0 & 0 & 1
\end{pmatrix} \ $

$ R_y(\alpha) =
\begin{pmatrix}
\cos\alpha & 0 & \sin\alpha & 0 \\
0 & 1 & 0 & 0 \\
-\sin\alpha & 0 & \cos\alpha & 0 \\
0 & 0 & 0 & 1
\end{pmatrix} \ $

$ R_z(\alpha) =
\begin{pmatrix}
\cos\alpha & -\sin\alpha & 0 & 0 \\
\sin\alpha & \cos\alpha & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1
\end{pmatrix} $

此时对于任意的旋转,就可以转化为三个方向上的旋转,这三个角也被叫为欧拉角

$ R_{xyz}(α,β,γ) = R_{x}(α)R_{y}(β)R_{z}(γ) $

Rodrigues 旋转公式

对此,可以被转化为如下公式,表示对特定的轴旋转,即Rodrigues 旋转公式。推导原理也是先旋转平移到特定轴然后用上面公式旋转完后再变回去。

$
\mathbf{R}(\mathbf{n}, \alpha) = \cos(\alpha) \mathbf{I} + (1 – \cos(\alpha)) \mathbf{nn}^T + \sin(\alpha)
\begin{pmatrix}
0 & -n_z & n_y \\
n_z & 0 & -n_x \\
-n_y & n_x & 0
\end{pmatrix}
$

  1. R(n,α): 表示绕单位向量n=(nx​,ny​,nz​) 旋转角度 α 的旋转矩阵。
  2. I:3×3 单位矩阵。
  3. nnTn 与其转置的外积。
四元数

对于上面旋转矩阵,不方便表示差值。两个矩阵显然不可以直接减之类的,四元数就方便的提供了角度差值计算。原理是一个旋转轴和旋转角度,只不过旋转轴用虚数ijk表示。但此时不可以表示平移和缩放了

q=w+xi+yj+zk

视图/相机变换

理解:给三维物体拍张照的变换。

步骤需要三步:MVP。模型变换Model(把模型坐标系转化为世界坐标系),视图变换View(把世界坐标系转化为相机坐标系),投影变换Projection(相机坐标系转化为裁剪坐标系,便于最后投影到二维平面)

怎么定义一个照相机?

位置向量(e ,相机的位置),朝向(g , 相机的朝向),上方向(t ,相机头顶朝向,可以想象手机旋转拍照,需要定义一个上方向保证一致)

有一个显而易见的性质,即相机和物体同样的位移,拍出来的照片是一样的。因此利用这一点,我们可以就默认相机的位置就是原点,其它物体移动过去,同时相机默认的朝向就是-z方向,那也响应的把其他物体旋转。

那我们要怎么做呢?具体来说是以相机的坐标轴修正世界坐标系。把世界坐标原点移动到相机上,再把方向和相机对齐,就得到了我们需要的。

$$
T_{view} =
\begin{bmatrix}
1 & 0 & 0 & -x_e \\
0 & 1 & 0 & -y_e \\
0 & 0 & 1 & -z_e \\
0 & 0 & 0 & 1
\end{bmatrix}
$$

旋转矩阵时候,先算逆变换,因为从(1,0,0)之类变换过来方便,再逆变换回去

其中g是相机视线方向(对齐 -Z 轴),t是相机上方向(对齐Y 轴),g x t是相机的右方向(对齐 X 轴)

$$
R_{view}^{-1} =
\begin{bmatrix}
x_{g \times t} & x_t & x_{-g} & 0 \\
y_{g \times t} & y_t & y_{-g} & 0 \\
z_{g \times t} & z_t & z_{-g} & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
$$

$$
R_{view} =
\begin{bmatrix}
x_{g \times t} & y_{g \times t} & z_{g \times t} & 0 \\
x_t & y_t & z_t & 0 \\
x_{-g} & y_{-g} & z_{-g} & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
$$

最终视图变换二者结合,得到了相机视图

$$ M_{view} = R_{view} \cdot T_{view} $$

视图

正交投影

正交投影:直接平移到投影平面即可,类似于三视图。但区别是需要归一化(因此可能有一点点形变)

我们希望把一个[l,r] x [b,t] x[f,n]的长方体归一化到[-1,1]3的正方体上,那需要的就是先位移后改变大小。注意这是一个左乘矩阵,因此先做位移变换的放在右边。

$$
M_{ortho} =
\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}
$$

透视投影

近大远小,和人肉眼类似。你可以把远平面按比例挤到长方体的,再做一次正交变换。要保持近平面远平面上的点不变

按照数学关系来说,就是除以距离相机距离的z,这样得到一个变换关系

利用齐次坐标等价的性质,就可以得到缩放后的位置。

$ \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \begin{pmatrix} \frac{nx}{z} \\ \frac{ny}{z} \\ \text{unknown} \\ 1 \end{pmatrix} = \begin{pmatrix} nx \\ ny \\ \text{unknown} \\ z \end{pmatrix} $

那我们目前的透视->正交的矩阵,上面几行其实都确定了,现在难确定z的这一行变换。这个就不是简单的乘比例,对应到图上其实是位置n的屏幕,那z = n的点z坐标自然不变,其它的要怎么变化呢?

$ M_{persp->ortho}^{4×4} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & A & B \\ 0 & 0 & 1 & 0 \end{pmatrix} $

找几个特殊点带进去,首先n处的点变换完还是n,远平面f变换完还是f,那么最后可以得到推导式

An + B = n2
Af + B = f2

=>

A = n + f
B = -nf

得到最终透视->正交的矩阵

$ M_{persp->ortho}^{4×4} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & -nf \\ 0 & 0 & 1 & 0 \end{pmatrix} $

此时,如果我们带入一般的点,比如说任一点n,则计算出来的新z为 (n+f)z – nf 和原先的差值就是(n+f – 1)z – nf。

光栅化

定义:3D场景投屏到2D屏幕上。

视野纵向角度:$ tan \frac{fovY}{2} = \frac{t}{|n|} $,这样横向以及其他角度也可以算出来l,r左右边界bt下上边界,n离平面距离,aspect纵横比

现在需要把立方体重新投影到屏幕上即从[-1,1]转化为[0,width] x [0,height]

解决方法用上面的变换,先尺寸变换(宽度x变成width ,高度y变成height),再移动{移动到0中心}

$ M_{viewport} = \begin{pmatrix} \frac{width}{2} & 0 & 0 & \frac{width}{2} \\ 0 & \frac{height}{2} & 0 & \frac{height}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} $

不同显示器简介

电子射线管(CRT):顺序扫描,后续有小优化,每次画一半(比如这一次红,下一次蓝的),即隔行扫描技术

现代显示设备:原理:从内存的帧缓冲区,读出每一个像素的RGB信息

LCD:液晶显示器,液晶分子在电场作用下改变光线的透过方式,通过背光源和滤光片组合

LED:发光二极管

墨水瓶:通过控制电压,改变黑白像素位置。问题刷新率低,转换慢

光栅显示

基本图形:三角形

原因:最基础多边形,可以表示任意多边形,一定是在平面,且很容易定义内外,很容易插值

采样

利用像素中心对像素采样,判断是否在三角形内。通过 inside(tri , x ,y )函数

最基础的方法:对每一个点都inside判断
优化方法:设置一个包围盒,因为最大三个坐标也不会超过三个顶点,只找内部的。
再优化:每一行都是包围盒,一般适合窄长的三角形

但这样有很严重的走样问题,即上面采样后锯齿非常严重

inside函数

运用之前提到的叉积,保证顺序的情况下,算出来都是一个符号就是在内部,反之不是。

如果在边界呢?处不处理都行,自己定义一个标准统一起来就行。opengl就有自己的规定

采样的问题

1.锯齿 2.摩尔纹 3.车轮效应(车轮倒转)

解决方法:预过滤一下,即对原图像预处理一下再采用

走样出现原因:采样频率过低,恢复不了原波形

滤波:把特定频率去掉

高通滤波(只保留高频)如下,可见保留了边界(即变化巨大的地方)

低通滤波器,只保留低频

卷积:相当于低通滤波效果,在图形学简化定义为加权求和。卷积盒越大,保留的高频信息越少

对于采样不同的间隔,频谱就会有不同的分析,那么最后取样点就不一样就会有问题,即为走样

如何解决走样?

  1. 提高采样率
  2. 反走样:先模糊(先低通滤波,即卷积 )再采样

超采样(MSAA):对于一个像素点,多计算很多点,最后加权平均出一个值决定亮度。这样会增加计算量对屏幕没影响。

其它抗锯齿方法:

FXAA快速近似抗锯齿):先渲染完成后找到锯齿点,再回去把锯齿的修改。好处性能高,对边缘处理高效。坏处是效果可能比较差,导致细节丢失
TAA(时间性抗锯齿):利用多个帧信息平滑处理,结合过去未来帧采样结果。好处平滑闪烁少,坏处是需要额外处理前后多个帧数据,以及可能导致拖影效果

一个类似概念:超分,一般DLSS,即对于一个小图猜出其中的细节填充成一个高分辨率大图

可见性(visibility)

问题:哪些物体是可见的,哪些是不可见的,即如何处理正确的遮挡关系,要怎么解决呢?

油画算法:先画远处,再画近处,这样远处就会被覆盖。
对应过来,就是之前的方块,从后往前渲染。这样对所有物体优先级排序即可,nlogn
问题:如下三角形不存在绝的的遮罩关系(无法拓扑排序)

Z-buffer

处理每一个像素,只记录每一个像素最前面的即可。复杂度on,几乎适用于全部的GPU

for (each triangle T)
    for (each sample(x,y,z) in T)
         if(z < zbuffer[x,y])         //比最近的近,就渲染
              framebuffer[x,y] = rgb;
              zbuffer[x,y] = z;
         else ; // 干其他事

Shading(着色)

对一个物体应用材质。

对于一个着色点,我们定义如下东西

  • v 观测方向
  • n 法线方向
  • l 光照方向
  • 表面参数

着色只考虑物体上这个点产生的效果,不考虑其它的(比如阴影产生)

漫反射(Diffuse Reflecion)

对于实际的反射强度,则看与光线的角度。实际强度 = I cosθ,同时漫反射光能量向四面八方 二次方衰减。

即:Ld = kd( I / r2) max (0 , n · l )

n · l即为角度cosθ

镜面反射

高光:即光线的反射方向和人的观察方向很接近

如何判断呢?一是可以直接看反射向量和观察向量,而是通过半程向量(即观察方向向量v 和 入社方向向量 I 的中间向量) $ h_{(半程向量)} = \frac{ v + 1}{|| v + l || } $ ,这样计算比较好算。公式如下图所示,那为什么需要p次方呢?便于快速收敛,只有小角度的高光。ks为镜面反射系数

Ls(镜面反射光) = ks( I / r2) max (0 , cos α )p = ks( I / r2) max (0 , n · h )p

最终效果如图所示,镜面反射系数越大越亮,p越大高光越小

环境反射

假设环境光来自四面八方强度相同,因此 La = ka Ia

综上,全部加入后

L = La + Ld + Ls= ka Ia + kd( I / r2) max (0 , n · l )+ ks( I / r2) max (0 , n · h )p

不过模型假设较为简单,存在一些问题。

着色频率

  1. Flat shadding
    • 一个面一种颜色,对于光滑面不太好
  2. Gouraud shading
    • 对每一个顶点着色,内部平滑过渡(认为是多个周围面向量的平均值或加权平均 )
  3. phong shading
    • 对每一个像素一次着色

图形渲染流水线

此时可以对整个渲染流程有了清晰认知

  • Vertex Processing(顶点处理)
    • 输入三维空间的点,输出经过模型变换、视图变换和投影变换得到的平面图形
  • Triangle Processing(三角形处理)
    • 按规则连接这些点,形成三角形
  • Rasterization(光栅化)
    • 对每一个点采样,深度测试,得到哪些点在三角形内需要处理。
  • Fragment Processing(片段处理)
    • 着色处理,得到每个片段(or像素点)颜色
  •  Framebuffer Operations(帧缓冲操作)
    • 得到最终显示在屏幕上的图像

纹理映射

对于三维物体模型表面仍然为二维,因此可以一张平面图表示纹理。通过某种映射方式(UV)在可以放入或者还原。UV默认一般0~1

纹理过小

为什么需要平滑过渡?因为纹理太小了,相当于很多像素没有定义。此时图形渲染通常只是在顶点处定义关键值,我们需要整个图形内有一个平滑的过渡。我们需要差值纹理坐标,颜色,法线,深度等

对于三角形内部任意一个点,可以用(x,y) = αA + βB + γC表示,其中( α + β+ γ = 1 且αβγ均大于0)
此时,这一处的值V = αVA + βVB + γVC。注意要在三维空间中计算插值(因为透视关系可能变化,同时画面也有可能失真)

最近差值(Nearest)

直接和最近的点保持一致,问题会导致图形看起来很方格。

双线性插值(Bilinear)

找到周围4个点,先两次水平插值求平均,再数值两个求平均,最后综合得到了答案。这样每一个点都可以得到了

双三次差值(Bicubic)

找到周围16个点,然后运算得到答案。这样在一阶导数上是连续的,所以看起来抗锯齿效果更好,但是计算量也会非常的大。

纹理过大

同样也不是一件容易的事情,你不清楚要丢弃哪些信息,可能导致摩尔纹(高频信息),锯齿(低频信息)之类的问题。

此时核心思想是避免直接的采样,需要对比方周围多个点处理后得到平均结果后返回过来。

Mipmap

存储一系列图,所需要额外占用空间位1/3

mipmap会自动选择最匹配的 Mipmap 级别,从而提高渲染质量并优化性能

可是问题又来了,此时得到的只是若干离散的图层,如果在两个图层之间,怎么办呢?答案就是再插值一次,计算两个图层之间的,即三线性插值(Trilinear Interpolation),这样非整数图层也可以有平滑的过度了

新的问题:纹理在屏幕上出现倾斜或拉伸时,会导致模糊或失真的问题

各向异性过滤

此时存储更多细节,可以应对横向,纵向拉伸。此时会占用四倍的信息。可以处理一些拉伸问题了,但是对于斜向的其实还是没有办法

游戏里你就可以开多少X,开的越多越精确,但是导致占用显存

EWA 过滤

通过椭圆形覆盖区域进行多次纹理查询(采样),然后对查询结果进行加权平均。
加权值由覆盖区域的几何形状决定,通常与椭圆形的中心和边界有关。

纹理应用

环境光照

记录下来一个物体来自四面八方的光,得到了环境贴图。但这里相当于是记录下来了特定角度的光照,不同位置理论上要有不同的图案

如何得到环境光?用一个镜面球,反射出来的就是环境光,因此可以把环境信息存储在一个球上。但可能导致一定的扭曲,因此可以用一个正方体,稍微怎加了些计算量。

凹凸贴图

之前我们用纹理是为了替换Blinn-Phong模型里的参数Kd,除此之外,纹理还可以定义任何属性。比如可以定义一个相对高度,这样法线也会接着变化。在看到明暗相间时候就可以产生了质感。具体计算就是先切线然后再法线

位移贴图

真的将顶点做移动,这样和真实的差不多了。相比于前面的凹凸贴图就可能在边缘处露馅,边缘质感可能表现不出来。但位移贴图对模型三角形数量有要求,要求三角形足够多,才能完成采样。

三维纹理:定义空间中某一点是怎样的。

对于复杂的模型,你实时渲染阴影可能不大行,那你就通过纹理,提前做好再贴回来。不过还是感觉禁不起细挑(比如说光源换位置)

几何

集合的表示方法:隐式几何(Implicit geometry)显式几何(Explicit geometry),实际都是根据需要去选择,没有绝对的优劣。

隐式表示:

  1. 整一堆数学表达式(函数),比如说用x2+y2+z2=1,定义一个球几何。因此,很容易判断一个点在不在上面,但很难判断一个东西是什么。
  2. Constructive Solid Geometry(Implicit):通过基础模型的线性组合。但感觉本质还是数学表达式?
  3. Distance Functions(Implicit):通过定义空间中任意点到形状表面的距离,提供了一种灵活且高效的方式来描述几何形状。定义多个点就可以插值变换,定义出渐变效果。
    那怎么做到这样的呢?原理是定义的距离是到表面最近的距离,有正也有负,是有向距离
  4. Level Set Methods(Implicit):类似于等高线
  5. Fractals(implicit):分型,自相似。

总结一下:好处:描述容易,便于存储,有利于查询,利于光线交互,对于简单的图像可以严格描述无误差,容易控制拓扑变化。坏处是难以描述复杂的几何形体。

显示表示:

  1. 点云:最简单!不考虑表面,全部表示成点。表示方式就很简单,直接(x,y,z)就足够了,点足够密就看不出来区别。通常三维空间的扫描就是点云。但问题是,很难变成三角形面。
  2. 多边形面,一般是三角形或者四边形。如何表示呢?对于一个图形,你先告诉所有的顶点v,对于纹理上用vt,也是通过几个点确认唯一的面然后上纹理。对于每个面的朝向,定义法线vn,最后对于面,也是通过顶点确定,描述一组顶点完成。

曲线和曲面

曲线

作用:相机模型的运动路径,定义特殊字体(矢量表达式,不会失帧)

如何绘制曲线?

贝塞尔曲线:用一系列的控制点去定义一条曲线。下面以二次贝塞尔曲线为例,即只有三个点。

b0决定开始,b1决定向哪一个方向弯曲,b2决定了最后的终点。

具体怎么做呢,就是每一时刻都找到每一段的t等分点(假设全部为1),连起来之后,在连起来的线段上也找到t等分点,这个点就是t时刻对应的点。然后把所有时刻的点都连起来,就是最后的二次贝塞尔曲线

那对于n次贝塞尔曲线呢?那就是一直找t等分点,找到最后一个点为止

这样对于每个店其实就可以数学公式归纳了,归纳到最后其实就是二项式分布

因此也具有了一些性质:
1. 规定了起点和终点
2. 仿射变换下,如果对一条贝塞尔曲线仿射变换只需要对所有控制点仿射变换再重新绘制出来即可,不需要把曲线上每一个点位置都记录下来(原理是仿射变换和贝塞尔变换本质都是线性变换)。而投影变换就不可以(因为非线性)。
3. 凸包性质。凸包:能够包围一系列给定顶点的最小的凸多边形。而贝塞尔曲线的任何点都在这个最小的凸多边形内。

逐段的贝塞尔曲线(Piecewise Bezier Curves)

为什么需要?当点很多的时候,就很难去控制了,这时候一段一段的去控制方便准确。这样可以表达变换剧烈的曲线。

此时可以看到曲线有些连接的好连接的不好,要怎么形容?

C0连续:第一段第二段起点相同,只要俩曲线连接上就是
C1连续:交点左右两个控制点与交点共线距离相同

样条曲线:一组控制点生成的连续曲线,在保证一定数学条件(连续性,光滑性)的同时,也能够灵活的调整形状。例如用很多钉子固定树枝,树枝会形成平滑的曲线。

B样条曲线:样条曲线的特殊形式,是对贝塞尔曲线的扩展。贝塞尔曲线任意一个控制点改变都会影响整个曲线,局部调整很难。B样条就是很多段定义(但是也是足够连续的),这样对于局部修改好。

曲面

如何从贝塞尔曲线得到贝塞尔曲面呢?可以理解成一个平面施加一个向上的力拖拽得到结果

具体实现就是两个方向上分别运用贝塞尔曲线。水平平面奥赛尔曲线的垂直平面奥赛尔曲线,然后两个再结合起来,最终得到的图像。

Mesh(网格)

描述面一般还是用网格(mesh),即上面说提到的多边形描述。对于一些网格的操作,如Subdivision (用更多的三角形来得到更光滑的模型),Simplification(减少网格面,以节省存储量,但如何保持基本链接是个问题),Regularization(使三角形都接近于正三角形,便于渲染)。

https://www.jianshu.com/p/b8a52f658ca6

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇