Visibility

绘画算法:从远到近将物体画在屏幕上,近处的物体覆盖远处的对应的图层;

将模型三角光栅化,考虑对三角形按照距离屏幕的深度排序,复杂度为,但是可能存在相互覆盖的环;

引入Z-Buffer(深度缓存):

  • 为每一个像素保存当前的最小深度;
  • 同时维护两个缓存:帧缓存保存颜色值,深度缓存保存深度

算法如下:

1
2
3
4
5
6
7
8
9
Initialize depth buffer to ∞ 
During rasterization:
for (each triangle T)
for (each sample (x,y,z) in T)
if (z < zbuffer[x,y]) // closest sample so far
framebuffer[x,y] = rgb; // update color
zbuffer[x,y] = z; // update depth
else
; // do nothing, this sample is occluded

image-20241209194451115

假设每个三角形平均覆盖常数个像素,则该算法复杂度为;也就是该算法并不是基于排序的,假设每个三角不会在同一个像素用相同的深度,那么这个算法其实和三角形深度无关的;

Z-Buffer算法是目前最重要的可见性算法,已经在所有的GPU在硬件上实现;缺点是处理不了透明物体;

Blinn-Phong Reflectance Model

在绘画上,使用平行光线或者色块,引入图像的明暗和色彩;

在图形学上,着色指对物品应用某一种材质的过程;

最简单的着色模型是Blinn-Phong Reflectance Model;

观察下图有如下要素

  • Specular highlights: 高光,一般光线照射到光滑的地方,发生接近于镜面反射的效应;

  • Diffuse reflection: 漫反射,一般光线照射到粗糙的地方,其所有查看方向的表面颜色都相同

    image-20241209201146308

  • Ambient lighting:环境照明,物体接收到了间接的环境反射光,一般认为是常量;

image-20241209200203752

建立局部着色模型(Shading in Local)的输入:给定物体表面上一点Shading Point,考察光照照射在该点的输出,不考虑阴影(Shadow)

  • Viewer direction: 观察者看到物体的方向
  • Surface normal:物体表面切面法线向量
  • Light direction:光线方向
  • Surface parameters:物体表面属性,比如颜色,亮度

Diffuse Term

物理上来说,在物体单位面积上,考虑接受到光线能量应该正比于;

image-20241209202325421

这是符合直觉的;

  • 物体被光照直射,理应接收更多光;
  • 物体和光照同向就几乎没有光照射上;

对于一种点光源,光线的能量在某一个时刻集中在一个球壳上(波动性);

考虑能量守恒,光线传播越远,能量衰减(light failoff)越多,用光照强度(intensity)定义能量;

由此建立漫反射模型

  • :某方向上的漫反射光diffusely reflected light;
  • :扩散系数diffuse soefficient,该点可能吸收一部分光而存在损耗,可以表示成三通道RGB值,就可以定义该点反射出来的颜色;
  • :不考虑光线从物体下面穿过,不考虑物体透明和折射

对于漫反射来说,不管从任何方向来看看起来都是一样,上式与无关,这说明此模型的合理性;

Specular Term

对于高光项,如果光线照射在比较光滑的物体,那么高光反射的光线应该类似于镜面反射,可以用其半程向量和法线接近描述;

Blinn-Phong模型定义半程向量

类似定义高光项

  • :镜面反射光specularly reflected light
  • :亮度系数specular coefficient,相对于漫反射项来说很小
  • :为解决余弦项容忍度过高的问题,一般取128,提高幂次以符合经验:偏离高光光线一点点就基本看不到了;

image-20241210183253418

Ambient Term

大胆假设环境中任意一点接收到环境光基本为常量,环境光着色不依赖于任何其他事物,真实世界可能未必这样;

添加常量颜色以考虑忽略的照明并填充黑色阴影,保证没有地方是完全黑的;

  • :反射环境光 reflected ambient light
  • :环境光系数 ambient coefficient

模型输出为三项相加

Shading Frequency

对于光栅化的图像,可以按照每个三角形面,顶点,和像素为单位进行着色,它们的着色频率并不相同;

Flat Shading:每一个三角形面对应一个法向量,在光滑面上效果不好;

Gouraud Shading:跨三角形的顶点进行插值着色,每个三角形顶点对应一个法线

Phong Shading:在每个三角形上插值法线向量 ,计算每个像素的完整着色模型

以下是三个方法的对比图

image-20241210185959408

对于光栅化的图形,顶点对应的法线可以用其关联的所有三角形法线平均

image-20241210190324268

Real Time Rendering

Pipline如下

image-20241210190526505

Texture Map

我们希望在物体表面上的不同位置的点定义不同属性,观察到任何三维物体的表面是二维的,反过来我们也可以把一张二维图贴在三维物体的表面,我们把这张二维图称为纹理;

对于纹理图上任意一个点,定义uv坐标系,每一个三角形的顶点对应纹理上的一个坐标;

image-20241210194556777

一个看起来舒服的纹理,应该看起来上下左右无缝衔接,因为纹理可以被物体重复多次,比如tiled texture;

Barycentric Coordinates

在三角形内部进行插值的工具是重心坐标,重心坐标可以表示三角形内部的一个顶点,从而在三角形内部实现平滑过渡,常常用于纹理坐标,颜色,法向量的计算;

对于三角形, 在三角形内部的任意一点,可以表示为三个顶点坐标的线性组合

若点在三角形内,还需满足三个系数非负;若无限制条件,表示点在三角形所在平面内;

image-20241212202923346

进一步,定义有向面积,定义三角形面积

用叉乘可以如下展开

特别的,三角形的重心坐标为;

基于任意一点,可以利用重心坐标,根据顶点的属性值,插值成三角形内部的属性值

image-20241212203915791

但是在投影变换下,重心坐标不保证发生变化,应该在投影之前计算三维空间下的重心坐标,插值之后再做投影变换;

Texture Mapping

基本思路为:对每个光栅化屏幕的采样点(通常为像素的中心),计算对应的纹理的坐标,在纹理上采样,设置样本点的纹理颜色;

像素在纹理上的采样对应的称为纹理元素(texel);

在实际应用时,针对不同场景,往往还要作如下优化:

Bilinear Interpolation

image-20241212205128667

假设像素对应的纹理坐标对应红点,我们考虑周围四个像素进行插值;

定义一维上的线段上的插值

考虑水平偏移和垂直偏移,可以在水平方向和垂直方向各做插值

若取16个纹理格子的方法称作Bicubic,对比如下,解决纹理分辨率过低的问题;

image-20241212205708866

Mipmap

对于纹理分辨率过大的情况,可能出现锯齿和摩尔纹的问题;

image-20241212205906862

假设像素对应灰色的四边形,其中心为蓝点,在分辨率相对过大的情况下,可能像素覆盖了许多纹素,仅靠中心点的纹素难以描述整个像素的纹理信息,需要解决在纹理走样上的问题;

image-20241212210254529

抛弃采样的思路,我们尝试解决一类范围查询问题:给定平面上的一块像素区域,获得覆盖纹素的平均值;

引入Mipmap,快速地解决正方形的近似范围查询;

预处理纹理图像,生成的卷积图像作为下一层,直到得到单个纹素,带来的额外空间开销为原来的;

image-20241212211136030

利用Mipmap我们只需要关注像素对应的区域在Mipmap的哪一层即可,对于任意一个像素块,可以映射到纹理上的某一区域;

image-20241212212116827

考虑像素中心和其邻居中心的距离为一个像素块长度,那么这个区域也近似为一个映射长度的正方形;

image-20241212212234652

image-20241212212336567

映射长度计算如下:

这个近似正方形的纹理平均值所在层数为

在这一层像素对应的区域就近似于该层的一个纹素;

这样的计算代价可能是纹理映射变化不连续,我们考虑下层和上一层,进一步作三线性插值(Trilinear Interpolation);

image-20241212213314450

Anisotropic Filtering

使用Mipmap可能会在远处出现过度模糊的问题,可能是近似成正方形区域带来细节丢失严重的问题;

image-20241212213843252

通过各向异性过滤可以缓解Mipmap的问题;

image-20241212213856884

预计算Ripmaps 和总面积表,可以查找轴对齐的矩形区域 ,但是对角线足迹仍然是一个问题,而且带来的开销是原来的3倍;

image-20241212214340625

EWA filtering

通过多次查询,将不规则区域分成若干圆形;

  • 计算加权平均;
  • 仍然维护Mipmap 层次结构;
  • 可以处理不规则的足迹;

image-20241212214424929

Application

在现代GPU中,纹理可以看作一块内存+内存上的范围查询,可以将数据引入片段计算,这实际上是一些物理模型应用的上层抽象;

  • 环境光Environment lighting
  • 存储微观几何体Store microgeometry
  • 程序纹理Procedural textures
  • 实体建模Solid modeling
  • 体积渲染Volume rendering

Environment Lighting

我们需要将纹理描述环境光时,会生成一种环境贴图的特殊纹理,用于描述不同方向的光照信息;

一般认为环境光线来自无穷远处,也就是说,用环境光描述的环境贴图没有深度意义;

我们可以将环境贴图记录在一个球面上,再将球面展开(类似于地球仪和世界地图),称作Spherical Map;

但是Spherical Map潜在问题是靠近极点的位置可能发生扭曲;

一个改进是利用Cube Map,将光照信息存储在一个立方体上,将立方体展开得到6个图片;

对应关系如下:

image-20241226211043946

Store Height/normal

可以用纹理描述物体表面上的凹凸高度变化,生成凹凸/法线贴图(Bump/Normal mapping),用于虚拟物体的表面几何性质(Fake the detailed geometry);

将设没有贴图时物体表面为黑线,黄色的曲线为凹凸贴图记录的高度信息,我们需要根据两个信息重新计算切线和梯度;

image-20241226211905433

通过旋转坐标系的办法,我们假设没有贴图表面上一点的法向量为;

对于贴图上切线,用某个因子衡量贴图对表面的影响程度,对梯度用如下差分作出近似;

经过贴图修正过后的法线应该是

一个更加现代的方法是位移贴图Displacement mapping,实际改变光栅三角形的顶点位置,对比如下,可以看到在边缘处凹凸贴图的Fake之处,它没有改变几何体的形状;

image-20241226213536647

效果更好带来如下代价:模型需要足够细致,使得光栅采样的频率高于纹理变换的频率;

3D Procedural Noise + Solid Modeling + Volumn Rendering

纹理也可以记录一些三维信息,用噪声描述;

image-20241226214350077