线性代数
向量的点乘:判断是否为同一方向
点乘大于0则为同一半朝向,小于0则为反朝向
向量的叉乘:判断里外关系
各顶点出发到目标点与同点出发边向量相乘,均大于零或均小于零则为在内 否则在外
变换
缩放图形
反转图形
旋转图形
偏移图形

齐次坐标
原因:平移为非线性变换 不方便

方法:(二维坐标)将点(x, y)记为(x, y, 1), 将向量(x, y)记为(x, y, 0)
好处:

注:点 + 点 可得两点间中点
即可将平移记为
注意:矩阵乘积顺序对结果有影响 齐次坐标前同一矩阵先运用线性变换在运用平移操作
思考:如何不绕原点旋转?

三维同理(x, y, z, 0), (x, y, z ,1)
观测变换(三维
旋转
绕谁谁不变
- 循环对称性质
$$
绕x与z时,\vec{y}\times\vec{z} = \vec{x},\vec{x}\times\vec{y} = \vec{z},属于同一方向旋转(记为逆时针旋转
$$
$$
而绕y旋转时,\overrightarrow{x}\times\overrightarrow{z} = -\overrightarrow{y},故须旋转-\alpha
$$
*
- 罗德里格斯旋转公式(复杂旋转转为xyz旋转
$$
绕旋转轴\overrightarrow{n}旋转\alpha度
$$
视图变换
三步变换(mvp变换
- 模型变换:搭建场景
- 视图变换:找好相机角度
- 投影变换:将三维空间投影到二维平面
相机
- 放在哪(e)
- 往哪看(g)
- 向上方向(t)
因为 相对移动
可假设相机一直在原点,朝向-z方向,y向上
//好处:扔掉z轴,呈现图像就是关于xy的平面图
如何操作?
将g旋转到-z,t旋转到y,(g x t)旋转到x (难求)
故先将将-z旋转到g,y旋转到t,x旋转到(g x t),所需变换即该结果的逆
由于旋转矩阵为正交矩阵,矩阵的逆等于转置
故得

投影变换
正交投影
简单思路:将相机如上摆放后,使所有物体z=0,再将所有物体移到x、y均在-1到1的小方片上 即可将物体投影到xy平面,即正交投影的结果
正式做法:

把任何形状变成标准立方体
- 平移:把中心移到原点
- 缩放:把x、y、z宽度缩放为2(对应-1到1
对应矩阵:

透视投影
引子:齐次坐标性质

思路:
将远平面挤到近平面相同大小
挤压过程中:
- 近平面四个顶点不发生变化
- 原平面z轴不发生变化
- 远平面中心点不发生变化
用正交投影方法将远平面投影到近平面上

需要将矩阵化为
即左乘矩阵

对于给定的深度n(在近平面上):
故可得用待定系数法求第三行(与x、y无关,故前两项为0
对于远平面中心点:

由1、2可得:
$$
\begin{cases}
\begin{aligned}
An + B = n^2\
Af +B=f^2
\end{aligned}
\end{cases}
\Rightarrow
\begin{cases}
\begin{aligned}
A=n+f\
B=-nf
\end{aligned}
\end{cases}
$$
自此第一步把远平面挤压至近平面大小完成最终转化矩阵即此结果所求矩阵右乘正交转化矩阵
其他:经此变换后近平面、远平面的点z值不变,但中间的点z值并非不变(z变大,即变近)
光栅化成像
透视投影的视锥定义方式
- 视图宽高比
- 垂直可视角度(红线所成角度)(红线所连点为长宽中点)
光栅化:把东西画在屏幕上
即将[-1, 1]^2的方块映射到[0, width] * [0, height]的屏幕上
步骤:
缩放:将[-1, 1]拉伸至需求大小
平移:由于坐标计算从左下角开始,需将中心平移至原点
合并1、2可得矩阵:

光栅化:将图形打成像素
三角形:最基础的多边形
采样
概念:把函数离散化的过程
应用:设立函数,当中心在三角形内部时返回1,否则返回0
具体实现:
for(int x = 0; x < xmax; ++x){ for(int y = 0; y < ymax; ++y){ image[x][y] = inside(tri, x + 0.5f, y + 0.5f); } }包围盒:找到顶点x、y的最小与最大值,形成包围盒 只用对其内的像素做光栅化处理
锯齿
- 原因:
- 像素本身大小
- 采样率不够高
- 抗锯齿/反走样
抗锯齿/反走样
现象(artifact)
- 锯齿
- 摩尔纹
- 车轮效应(时间上的采样
原因:信号速度太快 采样速度跟不上
反走样方法:在采样之前进行滤波/模糊
why?
$$
定义\cos2\pi fx, f即频率
$$
前言:傅里叶级数展开
任何一个周期函数可以写成一系列正弦余弦的线性组合加常数的形式
引出:傅里叶变换
定义:给定任意一个函数可以经过一系列变换操作变为另一函数 通过逆变换可以变回原函数
作用:把一个函数从时域变到频域
例子:
右图为变换后图片 中间为低频 四周为高频 亮度表明图片信息主要集中于低频
即 走样:

滤波
意思:把某特定频段删去
例子(高通滤波):用滤波将刚刚的图的低频信号滤去再逆变换为原图得到左图
可得高频主要为图像剧烈变换部分
低通滤波:与上相反 边界模糊了

卷积
概念过程:下面三格窗口向右移动 与对应三数相乘后填回格子中
即对每三个各自做加权平均

卷积定理:时域上的卷积等于频域上的乘积,频域上的卷积也等于时域上的乘积(卷积的对偶性)(互逆)
例:此例中任何一个像素等于周围像素平均 故得模糊图 频域上类似低通滤波
乘1/9使图像整体颜色(亮度)值经过卷积操作后不发生变化(求均值)

卷积区域越大
(9*9 -> 63*63)得到的图像越模糊 频域上白色越小、越接近中心
采样在频域上的意义
冲激函数
只在特定位置上有值,其他位置上无值的函数(函数c)
采样即可表示为一个函数乘以一系列冲激函数后的结果
即
a * c = e对应的频域操作
即在频域上对对应的函数进行卷积操作
b 卷积 d = f
即采样为频谱的重复
得出产生走样现象的原因是采样频率不够快导致复制时采样的频谱出现了混叠

解决办法
增加采样率
受制于物理限制
反走样
先做模糊 再做采样
即先进行低通滤波(去除高频) 再进行采样
例子
用大小为一个像素的低通滤波器对三角形进行卷积操作(取平均)
怎么算??(1)
MSAA(对反走样的近似)
依靠模糊解决走样问题 并没有提高分辨率
将一个像素拆分为几个较小像素(增加采样点) 取每个像素内采样点在三角形内的平均覆盖率 用此值乘以三角形原本颜色
=>
由于采样频率为一个像素,此模糊操作结束后所得图形即反走样图形
代价:增大计算量
FXAA(Fast Approximate AA)
- 得到一副有锯齿的图片
- 找到锯齿边界
- 替换为无锯齿边界
TAA(Temporal AA)
复用上一帧的结果
相当于把MSAA对应的样本分布在时间上
超分辨率
无锯齿放大图片分辨率
DLSS(深度学习)
将细节猜出来
与抗锯齿不同 但本质相同
遮挡(深度)
画家算法
O(nlogn)先画远的 再画近的
弊端:无法定义互相遮挡的深度关系
深度缓存 Z-Buffer
O(n)生成结果图(frame buffer)的同时生成场景中任何一个像素的深度(depth(z) buffer)
注:始终假设相机看向-z 与这里的深度相反
一开始每个像素深度设为无限远 之后一步步记录到最小深度
好处:结果与渲染顺序无关(由于浮点型判断相等十分困难 可假设没有两个图形位于同一深度的情况)
着色
- 定义:对不同物体运用不同材质的过程
- 注:着色不包括阴影
基础着色模型(Blinn-Phong反射模型)
物体表面颜色可分为
- 物体高光
- 漫反射部分
- 间接光照
漫反射
假设物体一截取小段平面必为平面 定义 v为观测方向 l为光照方向 n为法线(均为单位向量) 及物体表面属性
单位面积接收到的能量(光)与${\cos\theta = \vec l \cdot \vec n}$成正比
对于点光源的周围,假设光波传播过程中不消耗能量,则光传播越远光球壳表面积越大,单位面积能量就越小。设单位面积能量为I,则:
单位面积接收到的能量(光)与$r^2$成反比
即:
注:$\vec n \cdot \vec l < 0$时表示从面的一边射到面的另一边,在这里没有实际意义,故取0
系数kd为对漫反射颜色的吸收,可表示成[0, 1]的rgb的向量
注2:漫反射能量与观测角度无关
高光
光滑的物体表面光的方向接近镜面反射,故只有观测角度与高光角度接近时才能看到高光
由于反射向量难以计算 可转化为法线向量与半程向量接近(点乘接近1)
高光一般为白色,故镜面反射系数
ks一般为白色。被吸收的能量(n 点乘 l)被简化
指数p可以提高容忍度(一般为100 到 200)
例子:漫反射与高光结合后的图形

环境光照
由于环境光照过于复杂,假设任何一个点接触到的环境光照永远相同。实际为一个常数。
对所有的点进行此着色模型可得:
着色频率
将着色运用在哪些点上
Flat Shading
对三角形两边做叉积得到法线,并在每个三角形内部进行统一着色Gouraud Shading
对平面的每个顶点周围三角形的法线求平均,进行着色,并在中间进行插值
Phong Shading
求出顶点法线 在三角形内部对法线方向进行插值,得到任意一点的法线方向,对每个像素点进行着色
实时渲染管线
从三维场景到二维图的过程
- 输入顶点
- 生成三角形
- 光栅化
- 着色
- 纹理映射
- 输出
Shader即内置管线处理过程中可自定义修改部分。会自动应用在每个顶点或每个像素(片元)上
其中用到简单的Phong模型光线计算
纹理映射
定义在着色过程中不同位置的不同物体属性(如漫反射系数)实现纹理
三维物体表面的纹理其实是二维的,物体表面上的点与二维图像上点的映射即纹理映射
uv坐标
假设映射关系已知,设纹理图为在uv坐标上的一张图(u、v均在[0, 1])
tileable texture:将纹理复制连接在上下左右后依然连续
重心坐标(插值)
- 作用:做插值,在平面内进行平滑过渡
- 插值什么:颜色、法线…
将三角形上任意一点表示为A B C坐标的线形组合,则重心为系数相加为1的点
即$\begin{cases} (x, y) = \alpha A+ \beta B + \gamma C\\alpha + \beta + \gamma = 1 \end{cases}$ , 可用$(\alpha, \beta, \gamma)$ 表示点(x, y)
仅当$\alpha、\beta、\gamma$均非负时,中心才在三角形内 如不满足$\alpha + \beta + \gamma = 1$则该点不在三角形的平面内
- 由奔驰定理可求得每点的重心坐标


而三角形重心的重心坐标即 $(\frac13, \frac13, \frac13)$
注:转换为投影坐标后不能保证重心坐标不变,故三维坐标下应先算出重心坐标,做完插值再进行投影操作
应用纹理
纹理太小
简单方法:对每个像素点,计算出
uv坐标,将对应的纹理设为该像素点的漫反射系数问题:纹理太小无法完全覆盖所有像素点?(高分辨率下,
uv坐标可能对应小数)解决:坐标四舍五入,使多个像素点映射到同一个纹理点上,导致低分辨率
进一步解决:双线性插值(点查询)
取小数
uv坐标周围四个点,进行水平方向和竖直方向上的插值,即可得到任意点的平滑过渡双三次插值/双立法插值
取周围临近16个点做三次插值
结果对比

纹理太大
现象:严重的摩尔纹与锯齿(走样)
原因:一个像素覆盖的纹理上的区域太大
解决方法:之前学过的超采样 可以解决,但消耗巨大
mipmap
方法2:不进行采样 即mipmap(图像金字塔)(范围查询)
快、近似、正方形
一共$\log_2n$层 存储量只多了$\frac13$
近似方法:四周在
uv坐标下距离差距的最大值LL*L即一个像素在uv坐标下的覆盖范围 这个正方形在Mipmap中第D层一定能取到1*1的大小
结果:

问题:会有分层不连续的结果
解决:三线性插值在上下两层分别进行双线性插值,再对两层的结果分别进行插值
结果:

各向异性过滤
STILL问题:过分模糊

原因:1. 近似 2. 只能查询正方形,在计算长条形区域时加入了不必要的平均
解决:各向异性过滤(
ripmap)
对于这张图,
mipmap只实现对角线上图片,而这张图可以将查询范围从正方形扩大到矩形内存变为原来的三倍
基本只影响显存开销,不增加计算量
still:对于斜向区域无法很好的近似
EWA过滤
基本思路:把一个不规则形状拆成很多圆形,多次查询覆盖原形状
问题:时耗大