计算机图形学
图形学¶
渲染管线¶
- cpu 阶段(以应用程序阶段)
- 软件层面上的,视锥剔除,碰撞检测,动画物理模拟等
- gpu 阶段
- 输入三维空间的点
- 投影到二维平面上(顶点变换:mvp 模型观察投影;画面裁剪;平面映射)
- 点构成三角形
- 对三角形进行光栅化
- 对三角形进行着色(像素处理)
辐射度量学¶
坐标变化¶
- 模型:平移旋转缩放
- 视图变换:摄像机坐标、指向、旋转
- 投影变换:正交投影、透视投影
- 常见坐标系:
- 模型坐标系:定义对象的形状和结构
- 世界坐标系:定义对象再游戏世界中的位置和方向
- 视图坐标系:即相机坐标系,从特定观察点看向场景使用的坐标系,世界坐标系中的对象通过视图变换被转换到视图坐标系中
- 裁剪坐标系:在视图坐标系之后,场景会经过投影变换(正交或透视)被转换到裁剪坐标系。这一步涉及到确定哪些部分的场景应该被渲染到屏幕上,哪些部分应该被裁剪掉。投影变换同时也将3D场景转换成了2D图像加上深度信息的形式。
- 规范设备坐标系
- 屏幕坐标系
- 坐标系的转化:
- 模型坐标系 -> 世界坐标系:通过模型变换。
- 世界坐标系 -> 视图坐标系:通过视图变换。
- 视图坐标系 -> 裁剪坐标系:通过投影变换。
- 裁剪坐标系 -> 规范化设备坐标系:通过透视除法。
-
规范化设备坐标系 -> 屏幕坐标系:通过视口变换。
-
mvp 矩阵
- 代表了模型(Model)、视图(View)、投影(Projection)三个变换矩阵的乘积
- 模型矩阵:将对象的局部坐标系(模型空间)转换到世界坐标系(世界空间)。这个变换涉及到物体的位移、旋转和缩放。
- 视图矩阵:将世界坐标系转换到观察者(或摄像机)的坐标系(视图空间)。这个变换通常涉及到将摄像机(视点)移动到原点,并进行必要的旋转,使得观察者面向场景的特定部分。
- 投影矩阵:将视图空间中的坐标转换到裁剪空间,进而通过透视除法转换为归一化设备坐标(NDC)。这个变换定义了一个可视范围,通常是一个锥形体(透视投影)或者一个长方体(正交投影)。
光栅化¶
- 抗锯齿
- 之所以会出现锯齿(走样)是因为出现了频谱混叠(后面有讲)
- 模糊(卷积)可以减少重叠,减少走样(先模糊再采样)计算量太大
- 向像素内部添加更多采样点,根据覆盖采样点的数目决定模糊状态(不透明度)MSAA多采样抗锯齿
- 深度缓冲(深度测试):绘制深度不同具有遮挡关系的不同图像,决定哪些表面应该被渲染到屏幕上
- 深度图-储存每个像素对应的最浅的深度(深度缓冲)
-
结果图-储存最终的结果(根据深度图决定覆盖关系)
- 如果当前片段的深度值小于或等于缓冲区中存储的值(表示当前片段更靠近观察者),则片段的颜色和深度值会被写入颜色缓冲和深度缓冲中,覆盖原有值。
- 如果当前片段的深度值大于缓冲区中的值(表示当前片段被其他物体遮挡),则该片段被丢弃,不会影响最终图像。
-
背面剔除:
- 为了提高渲染效率,可以避免对视野之外的三角形进行渲染(消除从相机视角看是背面的三角形面)
- 使用右手定则计算三角形面方向(即通过顶点的顺序确定)进一步计算得到法向量
- 通过相机 lookat 与面的法向量的点乘即可判断方向从而实现背面剔除
着色¶
- 光照模型:
- 三要素:高光、漫反射、环境光
- 高光:观察方向和镜面反射方向接近时看到高光
- 漫反射:模拟光线均匀地从物体表面反射的效果,取决于光源的方向和表面的法线,与观察者位置无关。
- 环境光:模拟由场景中其他表面反射的间接光对物体的照射,通常是一个常数,使物体即使在没有直接光照的情况下也不会完全黑暗。
- 纹理映射:每个三维的模型上的任意点都能对应在uv坐标上的某个点上。
- 当显示分辨率远高于纹理分辨率时可能存在映射问题,如坐标转化后为小数,可能使得多个坐标映射到相同的纹理位置,造成显示不准确(纹理过小)
- 采用周围4个点的数值进行插值(两次水平一次垂直)
-
mipmap范围查询(纹理过大)近处锯齿、远处摩尔纹
- Mipmap技术通过创建一系列渐进式降低分辨率的纹理图像来工作。这个系列从原始纹理图像开始,每一级的图像分辨率是前一级的一半(宽度和高度都减半)。这些图像被存储在纹理的Mipmap链中。
- 当3D场景被渲染时,图形硬件或图形库会根据物体表面相对于摄像机的距离和角度选择最合适的Mipmap级别进行纹理采样。
- 如果没有合适的可以在不同层上做线性插值:不同层上双线性插值,再在两层之间插值。(三线性插值)
- 纹理的应用
- 环境光照
- 凹凸、法线贴图(通过法线差异模拟高度变化,不会改变几何形体)
- 位移贴图:真实改变模型,会展现出凸起部分的投影
几何¶
- 隐式表示
- 数学表达式:隐式用函数表示
- csg(布尔运算)
-
距离函数(空间中任何一个点到物体表面的最短距离)
-
显示表示:
- 二维三维映射
- 点云表示
- 多边形面
光线追踪¶
- 为什么要使用光线追踪?
-
光栅化难以处理好:软阴影(光源被部分遮挡)、毛玻璃材质反射、间接光照等
-
光线追踪应用了光路可逆性,从眼睛出发直至光源进行追踪。从眼睛向外寻找,到达最近的(可观察物体)然后与光源连线计算着色结果(可见性)
-
优化:使用包围盒,与包围相交再去计算是否和物体相交
-
路径追踪的基本原理是逆向光线追踪。对于场景中的每个像素,算法从观察者的视点发射一条或多条光线,穿过像素进入场景。当这些光线与场景中的对象相交时,不仅计算直接照明(即直接从光源接收的光),而且还随机生成新的光线,模拟反射、折射或散射等效果。这些新光线继续与场景中的对象相交,过程重复,直到达到一定的迭代次数,或者光线强度降低到可以忽略的程度。
-
延迟渲染:延迟渲染主要用于复杂场景中,尤其是当场景中有大量光源时,能够有效地提高渲染效率和性能。分离几何和光照计算
- 几何处理阶段(Geometry Pass):在这个阶段,场景中所有物体的几何信息(如位置、法线和纹理坐标)被渲染到几个不同的2D纹理中,这些纹理统称为G缓冲(G-buffer)。不涉及光照计算。
- 光照处理阶段(Lighting Pass):在几何处理阶段完成后,G 缓冲中存储的数据被用来计算光照和阴影。在这个阶段,场景中的每个光源都被单独处理,根据 G 缓冲中的信息计算光照效果,然后将所有光源的贡献合成最终的图像。
- 正向渲染,先执行着色计算,再执行深度测试;渲染 n 个物体在 m 个光源下的着色,复杂度为 O(n*m),光源数量对计算复杂度影响大;对于正向渲染,我们通常会对一个像素运行多次片段着色器;延迟渲染,先进行深度测试,再执行着色计算;对于延迟渲染,每一个像素只会执行一次片段着色器。
材质与外观¶
相机¶
- 曝光影响因素(进光量*时间)
- 光圈
- 快门速度
- iso(信号增益)
动画¶
物理基础¶
碰撞检测¶
- 边界框
- 轴对齐边界框(AABB):这是最简单的方法之一,通过在每个维度上确定对象的最小和最大坐标来定义一个盒子。AABB易于计算,但不随对象旋转。
- 定向边界框(OBB):OBB相对于AABB更复杂,它允许边界框随对象旋转。OBB更精确地适应对象的形状,但计算成本更高。
- 边界球:边界球是围绕对象的最小球体,任何点到球心的最大距离定义了球的半径。边界球的碰撞检测非常简单,只需比较两个球心之间的距离与它们半径之和。边界球不受对象旋转的影响,但可能无法紧密适应所有对象形状。
杂项¶
- 四叉树:一种树形数据结构,用于高效地管理和查询二维空间中的数据。它通过递归地将二维空间划分为四个象限或子区域来工作。四叉树广泛应用于图形处理、空间索引和碰撞检测等领域。
- 构建四叉树:首先,基于所有点的坐标构建四叉树。这个过程中,我们会逐渐将空间细分,直到每个节点所代表的区域内的点的数量不超过预设阈值或达到最大分裂深度。
- 执行查询:要查询特定区域内的点,我们从根节点开始遍历四叉树。对于每个节点,我们检查该节点代表的区域是否与查询区域相交:
- 如果不相交,我们忽略该节点及其所有子节点。
- 如果相交,我们继续检查该节点的子节点。
- 如果当前节点是叶节点(没有子节点),我们检查它包含的点是否在查询区域内,并处理这些点。