开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情
大家好,我是曹骏。因为本人对计算机图形学、WebGPU等非常感兴趣,因此会陆续发布闫令琪博士的《GAMES101:现代计算机图形学入门》课程译文,希望能帮助到更多的同学理解课程,爱上图形学这一浪漫的学科。
先给出课程的链接:
www.bilibili.com/video/BV1X7…
www.bilibili.com/video/BV1X7…
1 视口变换-从裁剪空间到屏幕空间 Canonical Cube to Screen
1.1 什么是屏幕 What is a screen?
-
在图形学中,抽象的认为屏幕是一个二维数组,数组中每一个元素是一个像素 An array of pixels
-
这个数组的大小:分辨率 Size of the array: resolution
-
一种典型的光栅成像设备 A typical kind of raster display
Raster == screen in German
Rasterize == drawing onto the screen
1.2 像素 Pixel (short for “picture element”)
-
暂时理解为屏幕上显示的最小单位,是一个内部颜色唯一的方块 For now: A pixel is a little square with uniform colo
-
像素的颜色可以由RGB三个值来表示 Color is a mixture of (red, green, blue)
1.3 屏幕空间 Defining the screen space
- 图中蓝色像素坐标/位置为 (2, 1),像素都是以(x, y)的形式表示,其中x、y都是整数 Pixels’ indices are in the form of (x, y), where both x and y are integers
- 图中像素坐标/位置的范围为(0, 0) 到 (3, 2),像素的范围从 (0, 0) 到 (宽度-1, 长度-1) Pixels’ indices are from (0, 0) to (width - 1, height -1)
- 图中蓝色像素的中心为 (2.5, 1.5),像素的中心在 (x+0.5, y+0.5) Pixel (x, y) is centered at (x + 0.5, y + 0.5)
- 图中屏幕的覆盖范围为 (0, 0) 到 (4, 3),屏幕覆盖范围为 (0, 0) 到 (宽, 高)
1.4 视口变换 Viewport transform
-
忽略z轴坐标变换
-
将原本
的平面变换到
Transform in xy plane:
to
-
视口变换矩阵 Viewport transform matrix:
2 光栅化-从屏幕空间的图形到像素 Rasterizing Triangles into Pixels
2.1 不同的光栅显示设备 Different Raster Displays
2.1.1 阴极射线管 Cathode Ray Tube
- 示波器 Oscilloscope
-
- Oscilloscope Art www.youtube.com/watch?v=rtR…
- 早期CRT显示器 Raster Display CRT
-
-
隔行扫描(Interlaced)减少了带宽,现在这种思想也被用于一些视频压缩算法
-
帧缓存器:屏幕所显示画面的存储区域 Frame Buffer: Memory for a Raster Display
2.1.2 平板显示设备 Flat Panel Displays
- LCD/液晶显示器 Liquid Crystal Display
-
- 通过液晶扭曲偏振来阻挡或透射光
- LED/发光二极管阵列 Light emitting diode array
- 电子墨水屏 Electrophoretic (Electronic Ink) Display
-
- 通过控制黑色和白色颗粒上下变化来组成画面,缺点是刷新率低
2.2 三角形-基本形状单元 Triangles - Fundamental Shape Primitives
2.2.1 为什么是三角形 Why triangles?
- 最基础的多边形 Most basic polygon
-
- 所有的多边形都可以拆成三角形 Break up other polygons
- 拥有独特的性质 Unique properties
-
-
除非折成两个三角形,否则永远是一个面 Guaranteed to be planar
-
三角形的内外很明确 Well-defined interior
-
有在三角形顶点处插值的明确方法(重心插值) Well-defined method for interpolating values at vertices over triangle (barycentric interpolation)
-
2.2.2 采样 Sampling
-
在一个函数上求不同位置处对应的值分别是多少,这个过程就是采样 Evaluating a function at a point is sampling.
-
采样是一个将函数离散化的过程 We can discretize a function by sampling.
for (int x = 0; x < xmax; ++x)
output[x] = f(x);
-
采样是图形学中的一个核心概念 Sampling is a core idea in graphics.
2.2.3 inside函数 Define Binary Function: inside(tri, x, y)
-
光栅化即为对一个二维的函数进行采样的过程 Rasterization = Sampling A 2D Indicator Function
-
一个点是否在三角形内可以靠叉乘判断 Inside? Recall: Three Cross Products
-
如果一个点恰巧在三角形的边界,要么不处理,要么特殊处理,图形API中一般有着严格规定
for(int x = xmin; x <= xmax; x++)
{
for(int y = ; y <= ymax; y++)
{
image[x][y] = inside(tri, x + 0.5, y + 0.5);
}
}
2.2.4 包围盒优化 Use a Bounding Box
- AABB包围盒 Axis-aligned bounding box
-
- 这种包围盒对于沿斜对角放置的瘦长型对象优化效果并不好
Incremental Triangle Traversal方法对瘦长且旋转放置的三角形较为合适
2.3 光栅化到真正的显示设备上 Rasterization on Real Displays
2.3.1 真正的LCD像素 Real LCD Screen Pixels (Closeup)
- 不同LCD屏幕排列方式也不同,拜尔阵列(bayer pattern)绿色像素较多是因为人眼对绿色较为敏感
2.3.2 其他的显示方法 Aside: What About Other Display Methods?
- 打印出的颜色是减色系统,为了节省墨水,打印通常使用半调的方式打印
2.4 采样 Sampling
2.4.1 采样在图形学中很常见 Sampling is Ubiquitous in Computer Graphics
-
光栅化 = 采样二维平面上的点 Rasterization = Sample 2D Positions
-
摄影 = 采样感光元件上的信息(将光学信息离散为图像上的像素) Photograph = Sample Image Sensor Plane
-
视频 = 在时间中的采样 Sample Time
2.4.2 采样造成的失真现象 Sampling Artifacts (Errors / Mistakes / Inaccuracies) in Computer Graphics
- 锯齿 Jaggies(Staircase Pattern)-sampling in space
-
- 由于采样率对于信号来说不够高,造成了信号的走样问题,形成了锯齿
- 摩尔纹 Moiré Patterns in Imaging-undersampling images
-
- 左图跳过奇数行和奇数列后得到右图
- 车轮效应 Wagon Wheel Illusion (False Motion)-sampling in time
-
- 对高速旋转的物体采样可能出现视觉上倒转的现象
- 失真的原因
-
-
信号变化太快而采样太慢
-
2.5 抗锯齿/走样的原理分析 Antialiased
2.5.1 时域与频域(补充) Spatial Domain&Time Domain&Frequency Domain
- 时域是真实世界,是惟一实际存在的域。因为我们的经历都是在时域中发展和验证的,已经习惯于事件按时间的先后顺序地发生。例如我们去音乐会听一段音乐,这段音乐会以声波的形式传入我们的耳中,随着时间的流逝,我们才能完整的欣赏这段音乐,这是在时域中发生的事。
- 在频域中,这段音乐只是由特定的音符组成的乐谱而已,这是永恒的,与时间无关。
- 傅里叶变换可以把信号从时域转化到频域,因为从时域或空间域的角度看,该信号是由多种频率不同的正弦波的叠加,而从频域角度看,该信号的频谱却如此的简单,这便于我们的观测和计算。
-
将时域的信号(信号可以是周期与非周期信号)变成频域形式并加以分析的方法称为频谱分析。其目的是把复杂的时域波形,经过某种变换分解为若干单一的谐波分量来研究,以获得信号的频率结构以及各谐波和相位信息。这某种变换可以是傅里叶级数,也可以是傅里叶变换进行变换.这两者目的都一样,都是把时域信号变成频域以便于信号分析。
2.5.2 傅里叶变换 Fourier Transform
- 傅里叶变换可以将函数表示为正弦和余弦的加权和 Represent a function as a weighted sum of sines and cosines
- 空间域/时域和频域可以通过傅里叶变换和逆傅里叶变换相互转换 Fourier Transform Decomposes A Signal Into Frequencies
2.5.3 走样 Aliases
- 采样的频率相较于信号的频率来说过小,还原出的函数就会不准确 High-frequency signal is insufficiently sampled: reconstruction incorrectly appears to be from a low frequency signal
-
在给定的采样率下无法区分两个频率,这种现象成为”走样“ Two frequencies that are indistinguishable at a given sampling rate are called “aliases”
2.5.4 滤波(去掉特定频率的信息) Filtering (Getting rid of certain frequency contents)
- 图像经傅里叶变换后的频谱图(经中心化后) Visualizing Image Frequency Content
-
- 参考:blog.csdn.net/dazhuan0429…
- 信息大多集中在中间(低频),少量分布在四周(高频)
- 高通滤波(得到边界) High-pass filt (Edges)
-
- 只有高频信息可以通过,后将频谱图逆傅里叶变换得到图像
- 低通滤波(得到模糊效果) Low-pass filter (Blur)
-
- 只有低频信息可以通过
- 其他对于频谱图的处理,去除高频和低频信息 Filter Out Low and High Frequencies
2.5.5 卷积 Convolution
理解数学中卷积和图像卷积操作:www.bilibili.com/video/BV1VV…
- 卷积在图形学中简化的理解
-
- 通过某一种滤波器对图像进行一定操作
- 卷积定理
-
- 时域的卷积等于频域的乘积,频域的卷积等于时域的乘积(两者具有对偶关系) Convolution in the spatial domain is equal to multiplication in the frequency domain, and vice versa
- 通过卷积定理实现对图像的处理
-
- 方法一:
-
-
- 在时域空间域中通过卷积过滤 Filter by convolution in the spatial domain
-
-
- 方法二:
-
-
- 通过傅里叶变换将时域转化为频域 Transform to frequency domain (Fourier transform)
- 乘以卷积核的傅里叶变换 Multiply by Fourier transform of convolution kernel
- 通过逆傅里叶变换将频域转化回时域 Transform back to spatial domain (inverse Fourier)
-
- 图像中小的正方体对应低通滤波器,更大的正方体对应只允许更低频率通过的滤波器
2.5.6 采样稀疏造成走样的原因
- 采样就是在重复原始信号频谱内容,即,在时域上进行采样 等价于 在频域上进行周期延拓 Sampling = Repeating Frequency Contents
- 从频率的角度上,采样如果较为稀疏,在该信号的频谱重复时会发生混叠,就会发生走样现象
2.6 反走样 Antialiasing
2.6.1 从原理分析如何减少反走样现象 How Can We Reduce Aliasing Error?
- 方法一:增加采样率 ncrease sampling rate
-
- 本质上增加了采样时频谱中副本之间的距离 Essentially increasing the distance between replicas in the Fourier domain
- 使用更高分辨率的显示器、传感器、更高规格的帧缓冲区 Higher resolution displays, sensors, framebuffers...
- 但是:成本非常高,可能需要非常高的分辨率 But: costly & may need very high resolution
- 方法二:反走样 Antialiasing
-
- 在采样重复频谱前使其中的副本内容”更窄“,即在采样前滤除高频信息 Making Fourier contents “narrower” before repeating, i.e. Filtering out high frequencies before sampling
2.6.2 反走样具体的方法
- 先模糊后采样 Pre-Filtering Before Sampling
-
- 最简单可以使用一个像素大小的低通滤波器用于求该像素内的平均 Antialiasing By Averaging Values in Pixel Area
- 在光栅化一个三角形时,一个像素区域内的平均值等于该三角形在该区域的覆盖率
- 通过超采样测算覆盖率的一种近似方法——MSAA(Multi-Sample Anti-Aliasing)
-
- 通过对一个像素内的多个位置进行采样并对其数值进行平均,实现近似于1像素大小滤波器的效果 Approximate the effect of the 1-pixel box filter by sampling multiple locations within a pixel and averaging their values
- 第一步:在每个像素中取 NxN 个样本 Average the NxN samples “inside” each pixel.
- 第二步:平均每个像素“内部”的 NxN 个样本 Average the NxN samples “inside” each pixel
- 第三步:采样对应信号,得到结果 This is the corresponding signal emitted by the display
2.6.3 其他
- No free lunch!
-
- MSAA会增加性能开销,但是在实际计算会让点的分布会更加有效、一些点还会被周围像素复用,所以并没有成倍增加性能开销
- 其他两个重要的抗锯齿方案 Milestones(personal idea)
-
- FXAA (Fast Approximate AA)——对有锯齿的图像通过图像匹配,将边缘锯齿处替换,速度快
- TAA (Temporal AA)——与时间变化有关,通过检测,上一帧的一些结果会在下一帧得到复用
- 超分辨率/超采样 Super resolution / super sampling
-
-
从低分辨率到高分辨率 From low resolution to high resolution
-
本质上仍然是”样本不足“的问题 Essentially still “not enough samples” problem
-
DLSS(Deep Learning Super Sampling)
-
3 可见度/遮挡 Visibility / occlusion
3.1 画家算法 Painter’s Algorithm
- 由远到近绘制物体,先绘制完远处物体接着再绘制近处的物体覆盖掉之前的物体 nspired by how painters paint, paint from back to front, overwrite in the framebuffer
- 一定程度上可行,排序n个三角形的时间复杂度为
Requires sorting in depth
for n triangles)
- 有互相遮挡关系时,无法定义物体间的深度关系,画家算法无法解决 Can have unresolvable depth order
3.2 深度缓冲 Z-Buffer
3.2.1 深度缓冲的原理
- 存储当前每个采样点(像素)的距离相机最近距离的深度信息 Store current min. z-value for each sample (pixel)
- 每个像素最后输出的颜色信息储存为帧缓冲,深度信息储存为深度缓冲 Frame buffer stores color values, depth buffer (z-buffer) stores depth
3.2.2 深度缓冲的算法 Z-Buffer Algorithm
注意:以下为了简化,深度值z永远是正的,越小表示越近,越大表示越远
IMPORTANT: For simplicity we suppose z is always positive (smaller z -> closer, larger z -> further)
- 将深度缓冲中全部每个像素(采样点)的深度值初始化为无限远,在每个三角形光栅化时,将它的每个像素的深度值和深度缓冲进行比较,如果该像素的深度值小于深度缓冲,则更新深度缓冲,否则舍弃
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
- 排序n个三角形的时间复杂度为
for n triangles (assuming constant coverage)
- 三角形的进入深度缓冲的顺序和结果无关
- 深度缓冲算法是一个最重要的算法,在几乎所有的GPU硬件中都有应用 Most important visibility algorithm, implemented in hardware for all GPUs
- Z-Buffer不能处理透明物体,透明物体需要特殊处理