目录
Real-Time Ray Tracing(RTRT)
- RTRT实现的效果
- Shadows
- Reflections & Specular
- Ambient Occlusion
- Global Illumination
- 硬件
- Tensor Core
- Volta架构
- 每秒处理500万亿的张量运算
- RT Core
- Turing架构
- 加速处理光线在三维环境中的传播
- 使用专用流水线(ASIC)来计算射线和三角形求交,可以访问BVH
- 10 Giga rays per second(每秒10千兆)
- 在RTR实际应用中 ,允许一个像素使用一个样本来采样
- 1 sample per pixel(SPP)
- 1 SPP path tracing 概念
- 1 primary ray (rasterization)
- 从相机到着色点传播的光线
- 由于该光线与渲染光栅化操作相同。因此,可以使用光栅化结果作为 1 primary ray
- 1 primary visibility ray
- 着色点需要判断遮挡情况,因此需要tracing一条着色点到光源的光线
- 1 secondary bounce ray
- 光线打到着色点后,反射出的光线
- 1 secondary visibility ray
- 反射光线打到着色点判断遮挡使用的,着色点到光源的光线
- 1 primary ray (rasterization)
- 一条完整的光路至少有上述4条光线组成
- 1 SPP path tracing 概念
- 1 sample per pixel(SPP)
- 硬件架构的理解和求交底层实现逻辑需要去深入研究。暂时略(毕竟自己现阶段没有优化需求)
- Tensor Core
- RTRT
- 通过硬件加速,已经允许我们做1SPP的path tracing,但是1SPP的结果噪声非常严重(path tracing 使用的是蒙特卡罗积分方法,结果受样本数量的影响)。因此,RTRT最关键的技术是降噪(Denoisiong)
- 目标:在使用1SPP的情况下
- 提高质量(no overblur, no artifacts, keep all details…)
- 保证渲染速度(一帧降噪小于2毫秒)
- 已有的降噪方法很难满足上述目标的实现
- 切变滤波方法(Sheared filtering Series):SF, AAF, FSF, MAAF, …
- 离线滤波方法:PP, BM3D, APR, …
- 深度学习方法 :CNN, Autoencoder, …
- 工业解决方案
- 思想:Temporal,时间上的滤波
- 方法
- 假设前一帧是已经进行降噪处理的结果(Denoised)
- 假设场景运动是连续的
- 使用motion vectors寻找着色点在两帧中的位置(很像光流)
- 时间上的复用,使用当前着色点前一帧的结果来增加本帧的SPP
- G-Buffers
- 略(都用烂了)
- Back Projection(求两帧着色点的对应关系)
- 如果使用G-buffer,可直接获得当前像素对应着色点世界坐标
- 如果没有G-buffer,可以使用逆变换得到
- s = M − 1 V − 1 P − 1 E − 1 x s = M^{-1}V^{-1}P^{-1}E^{-1}x s=M−1V−1P−1E−1x
- 上一帧的世界坐标获得
- Motion Vector已知。与光流不同,渲染时两帧之间的变化是已知的
- 因此,着色点上一帧世界坐标为: s ′ = T − 1 s s' = T^{-1}s s′=T−1s
- 上一帧的屏幕坐标获得
- x ′ = E ′ V ′ P ′ M ′ s ′ x' = E'V'P'M's' x′=E′V′P′M′s′
- 上一帧的MVP矩阵需要保存
- 利用Back Projection获取到两帧间滤波所需的值后,混合这两帧渲染结果(线性Blending)
- 定义
- ~:未进行滤波
- -: 滤波后的值
- 当前帧为
i
i
i时,当前帧降噪(空间上滤波),有
- C ˉ ( i ) = F i l t e r [ C ~ ( i ) ] \bar{C}^{(i)} = Filter[\tilde{C}^{(i)}] Cˉ(i)=Filter[C~(i)]
- C ˉ ( i ) \bar{C}^{(i)} Cˉ(i)为滤波后的渲染结果
- 当前帧降噪(时间上滤波),混合前一帧渲染结果
- C ˉ ( i ) = α C ˉ ( i ) + ( 1 − α ) C ˉ ( i − 1 ) \bar{C}^{(i)} = \alpha\bar{C}^{(i)} + (1-\alpha)\bar{C}^{(i-1)} Cˉ(i)=αCˉ(i)+(1−α)Cˉ(i−1)
- α ∈ [ 0.1 , 0.2 ] \alpha \ \in [0.1,0.2] α ∈[0.1,0.2]
- 定义
- 缺陷
- burn-in period
- 时间滤波需要已知前一帧信息,而下面的这些操作进行渲染,没有第一帧信息。因此,会有磨合期
- 切换场景,第一帧的处理
- 突变光源
- 切换镜头
- 时间滤波需要已知前一帧信息,而下面的这些操作进行渲染,没有第一帧信息。因此,会有磨合期
- screen space issue
- 前一帧信息都是SS空间上的,如果进行时间滤波时,当前帧有前一帧没有的信息,也会出问题
- 倒退着走
- 前一帧信息都是SS空间上的,如果进行时间滤波时,当前帧有前一帧没有的信息,也会出问题
- disocclusion
- 同样,SS空间中存储的是当前帧能看到的信息,如果有物体被遮挡,下一帧又出现,这种情况也会出问题
- 突然出现在背景中
- 同样,SS空间中存储的是当前帧能看到的信息,如果有物体被遮挡,下一帧又出现,这种情况也会出问题
- burn-in period
- 可尝试的解决方法
- 忽略上述缺陷,进行渲染
- 会出现残影
- Clamping
- 将前一帧的渲染结果,拉近到与当前帧足够接近时,再进行混合
- 拉近的距离不能太近
- 太近使用前一帧的意义(时间滤波)就没有意义了
- 拉近的距离不能太近
- 将前一帧的渲染结果,拉近到与当前帧足够接近时,再进行混合
- Detection
- 思路是,获取两帧的着色点的世界坐标,判定是否是同一着色点,或物体。
- 当不同时,调整混合的 α \alpha α调和(二值(0,1)或连续), 尽量不利用上一帧的着色值
- 思路是,获取两帧的着色点的世界坐标,判定是否是同一着色点,或物体。
- 忽略上述缺陷,进行渲染
- 问题
- 重新引入了噪音
- 在渲染过程中会出现的问题(shading)
- 主要是当 Motion Vector为0时出现的问题(两帧中着色点没有发生变化)
- 当场景种物体没有动,但是光源在动,这时Motion Vector是0向量。而这时场景中阴影却发生变化。因此,阴影会产生拖尾现象。
- detached/lagging shadows
- 当地板比较光滑时,会反射场景中物体。当物体移动,地板不动时会产生滞后现象。
- Temporal 的灵感来源于时间抗锯齿(Temporal Anti-Aliasing TAA)
- 两者非常相似
- 论文
- 《Temporally Reliable Motion Vectors for Real-time Ray Tracing》
Implementation of Filtering
- 滤波的目的
- 去除噪声
- 关注空间域(spatial domain)
- 高斯滤波
- 略。玩烂了
Bilateral Filtering
- 其实也玩烂了
- 目的
- 滤波时保留边界
- 边界的定义
- 颜色发生急剧变化的地方
- 边界的定义
- 滤波时保留边界
- 思路
- 如何保留边界
- 判断两个像素颜色差异是不是很大
- 不大,就使用高斯滤波进行处理,计算目标像素对当前像素的贡献
- 大,则认为是边界,减少目标像素对当前像素的贡献
w ( i , j , k , l ) = exp ( − ( i − k ) 2 + ( j − l ) 2 2 σ d 2 − ∣ ∣ I ( i , j ) − I ( k , l ) ∣ ∣ 2 2 σ r 2 ) (1) \tag{1} w(i,j,k,l) = \exp(- \cfrac{(i-k)^2+(j-l)^2}{2 \sigma_d^2} - \cfrac{||I(i,j)-I(k,l)||^2}{2\sigma_r^2 }) w(i,j,k,l)=exp(−2σd2(i−k)2+(j−l)2−2σr2∣∣I(i,j)−I(k,l)∣∣2)(1)
其中,- i , j i,j i,j代表当前像素
- k , l k,l k,l代表目标像素
-
−
(
i
−
k
)
2
+
(
j
−
l
)
2
2
σ
d
2
- \cfrac{(i-k)^2+(j-l)^2}{2 \sigma_d^2}
−2σd2(i−k)2+(j−l)2
- 为高斯滤波的指数部分
-
−
∣
∣
I
(
i
,
j
)
−
I
(
k
,
l
)
∣
∣
2
2
σ
r
2
- \cfrac{||I(i,j)-I(k,l)||^2}{2\sigma_r^2 }
−2σr2∣∣I(i,j)−I(k,l)∣∣2
- 为双边滤波使用颜色距离作为权重,控制边界像素的贡献
- 判断两个像素颜色差异是不是很大
- 如何保留边界
Joint Bilateral Filtering
- 联合双边滤波 (Cross / Joint Bilateral Filtering)
- 思想
- 高斯滤波:使用像素距离进行滤波
- 双边滤波:使用像素距离和颜色距离进行滤波
- 联合双边滤波:使用更多项进行约束,以达到更好的滤波效果
- 由于在RTRT中可以获得当前帧很多无噪声的信息(G-Buffer),可以使用这些信息进行滤波。
- 注意
- 约束项使用的信息本身不必归一化
- 因为滤波过程中已经有归一化操作
- 高斯核不是唯一选择
- 任何随“距离”衰减的函数都可以作为滤波核
- Exponential (absolute): 指数函数绝对值
- Cosine (clamped):余弦函数
- 任何随“距离”衰减的函数都可以作为滤波核
- 约束项使用的信息本身不必归一化
- RTRT联合双边滤波可使用的,判断边界的方法
- 两个像素的深度
- 两个像素的法线夹角
- 两个像素的颜色差异
Implementing Large Filters
- 使用高斯滤波,当滤波核很大时(64*64),如何提升滤波效率
- 解决方法
- Separate Passes:将核为(NXN)的滤波拆分滤波为两步
- 水平模糊:对原图进行水平上滤波 (1XN)
- 竖直模糊:对水平滤波后的图进行竖直方向上的滤波(NX1)
- 经过水平和竖直上的滤波,即可得到滤波结果
- 这种优化方式可将查询纹理的次数从 N 2 → 2 N N^2 \to 2N N2→2N, 大大提升效率
- 原理:
- 由于2D的高斯滤波核是可分离的
- G 2 D ( x , y ) = G 1 D ( x ) ⋅ G 1 D ( y ) G_{2D}(x,y) = G_{1D}(x)\cdot G_{1D}(y) G2D(x,y)=G1D(x)⋅G1D(y)
- 用卷积的方式进行表达
- ∫ ∫ F ( x 0 , y 0 ) G 2 D ( x 0 − x , y 0 − y ) d x d y \int\int F(x_0,y_0)G_{2D}(x_0-x,y_0-y)\mathrm{d}x\mathrm{d}y ∫∫F(x0,y0)G2D(x0−x,y0−y)dxdy
- = ∫ ( ∫ F ( x 0 , y 0 ) G 1 D ( x 0 − x ) d x ) G 1 D ( y 0 − y ) d y = \int(\int F(x_0,y_0)G_{1D}(x_0-x)\mathrm{d}x)G_{1D}(y_0-y)\mathrm{d}y =∫(∫F(x0,y0)G1D(x0−x)dx)G1D(y0−y)dy
- 由于一个二维的高斯函数可以用两个一维高斯函数的乘积表示,所以可以将滤波改写成两次在单方向上的滤波(卷积)
- 理论上讲,双边滤波、联合双边滤波,由于很难拆成两个一维函数。因此,不能用Separate Passes进行优化。但实际上,都这么用。
- 由于2D的高斯滤波核是可分离的
- Progressively Growing Sizes (逐步增大的核)
- a-trous wavelet 方法
- 多pass进行滤波,每次使用5X5的核进行滤波
- 每增加一个Pass,采样的像素位置不同
- 采样距离为 2 i , i = 0 , 1 , . . . 2^i, i=0,1,... 2i,i=0,1,...
- 因此,如 6 4 2 64^2 642滤波,需查询 6 4 2 64^2 642,该方法只需查询 5 2 × 5 5^2\times5 52×5次
- 由于无法完全过滤掉所有高频信息,在实际应用中会出现格子形状的噪声。
- a-trous wavelet 方法
- Separate Passes:将核为(NXN)的滤波拆分滤波为两步
- 解决方法
Outlier Removal
- 引入Outlier Removal原因
- 有时滤波的结果依然有噪声
- 重点解决,图像中有非常亮的像素点(噪声),这样的像素称为Outliers。如何去掉Outliers。
- 思路
- 如何判断哪个像素是outliers
- 在进行滤波前将outliers删除掉
- Outlier Detection and Clamping
- Outlier Detection
- 每个像素,取其周围7X7的像素点
- 求这些像素点的均值和方差
- 如当前像素的值不在
[
μ
−
k
σ
,
μ
+
k
σ
]
[\mu-k\sigma, \mu+k\sigma]
[μ−kσ,μ+kσ]之间就为outlier
- μ \mu μ 为均值
- σ \sigma σ为方差
- k k k为自定义的权重,1-3 or more
- Outlier removal
- 将不在 [ μ − k σ , μ + k σ ] [\mu-k\sigma, \mu+k\sigma] [μ−kσ,μ+kσ]之间的值Clamp到该区间
- Outlier Detection
Spatiotemporal Variance-Guided Filtering (SVGF)
- SVGF使用3个要素作为指导进行滤波
- 深度(Depth)
-
w z = exp ( − ∣ z ( p ) − z ( q ) ∣ σ z ∣ ∇ z ( p ) ⋅ ( p − q ) ∣ + ϵ ) w_z = \exp\Bigg(-\cfrac{|z(p)-z(q)|}{\sigma_z|\nabla z(p) \cdot (p-q)| + \epsilon}\Bigg) wz=exp(−σz∣∇z(p)⋅(p−q)∣+ϵ∣z(p)−z(q)∣)
-
其中, z ( p ) z(p) z(p) 和 z ( q ) z(q) z(q)为核内像素的深度值。 z ( p ) z(p) z(p) 和 z ( q ) z(q) z(q) 距离越大, exp函数值越小。即,核内像素点滤波贡献也就越小。
- 衰减函数任意
- ϵ \epsilon ϵ为一个极小值,如1e-6. 防止分母为零
- σ z \sigma_z σz控制函数衰减的程度(用户定义)
- ∇ z ( p ) \nabla z(p) ∇z(p) 深度的梯度值
-
- 法线 (Normal)
- w n = m a x ( 0 , n ( p ) ⋅ n ( q ) ) σ n w_n = max(0, n(p) \cdot n(q)) ^{\sigma_n} wn=max(0,n(p)⋅n(q))σn
- 其中, n ( p ) n(p) n(p)和 n ( q ) n(q) n(q)为模型的宏观法线。(模型法线,非贴图法线)
- 颜色差异 (grayscale color value)
-
w
l
=
exp
(
−
∣
l
i
(
p
)
−
l
i
(
q
)
∣
σ
l
g
3
×
3
(
V
a
r
(
l
i
(
p
)
)
)
+
ϵ
)
w_l = \exp\Bigg(-\cfrac{|l_i(p)-l_i(q)|}{\sigma_l\sqrt{g_{3\times3}(Var(l_i(p)))}+ \epsilon}\Bigg)
wl=exp(−σlg3×3(Var(li(p)))+ϵ∣li(p)−li(q)∣)
- 其中, l i ( p ) l_i(p) li(p)和 l i ( q ) l_i(q) li(q)为两个点颜色
- ϵ \epsilon ϵ为一个极小值,如1e-6. 防止分母为零
- σ l \sigma_l σl控制函数衰减的程度(用户定义)
-
g
3
×
3
(
V
a
r
(
l
i
(
p
)
)
)
g_{3\times3}(Var(l_i(p)))
g3×3(Var(li(p)))
- V a r ( l i ( p ) ) Var(l_i(p)) Var(li(p)) 为 p p p点颜色值的方差
- 方差获取 (
g
3
×
3
(
V
a
r
(
l
i
(
p
)
)
)
g_{3\times3}(Var(l_i(p)))
g3×3(Var(li(p))))
- 找该像素7X7区域像素颜色值计算方差
- 使用motion vector 获取上一帧对应方差值做平均
- 在上述基础上,再做3X3区域的方差计算
- g 3 × 3 ( V a r ( l i ( p ) ) ) \sqrt{g_{3\times3}(Var(l_i(p)))} g3×3(Var(li(p))) 为标准差
-
w
l
=
exp
(
−
∣
l
i
(
p
)
−
l
i
(
q
)
∣
σ
l
g
3
×
3
(
V
a
r
(
l
i
(
p
)
)
)
+
ϵ
)
w_l = \exp\Bigg(-\cfrac{|l_i(p)-l_i(q)|}{\sigma_l\sqrt{g_{3\times3}(Var(l_i(p)))}+ \epsilon}\Bigg)
wl=exp(−σlg3×3(Var(li(p)))+ϵ∣li(p)−li(q)∣)
- 深度(Depth)
- 缺点
- 由于使用了方差。因此,其在噪声和过度模糊的抉择中。更倾向于选择过度模糊。
RAE — Architecture
- 略(本人倾向于挖掘人脑的极限,而不是人工智能的极限#109)
小结
本节主要讲RTRT中的降噪方法。现在降噪方法很多。但是个人觉得,降噪不是未来。精准采样才是王道!