Lecture 13 Real-time Ray Tracing 2

news/2024/11/16 7:42:54/文章来源:https://www.cnblogs.com/Tellulu/p/18391229

Lecture 13 Real-Time Ray Tracing 2

Implementing a spatial filter

这里想做的是低通滤波

  • 移除高频信号
    • 会不会丢失高频中的信息?
    • 噪声不一定只在高频中
  • 集中在频域
  • 这些filtering可以应用在PCSS、SSR上的降噪

用$$\widetilde C$$表示有noise的图像

\[K$$表示滤波核kernel,比如box filter、gaussian filter等等,滤波器在做什么由滤波核定义用$$\overline C$$ 表示滤波完输出的图像这里一般用Gaussian filter![](https://img2024.cnblogs.com/blog/3247192/202409/3247192-20240901141200714-90974078.png)- 对于任何一个像素都取其周围一定范围,中心像素称为$$i$$,周围像素称为$$j\]

  • \[j$$肯定会对$$i$$有贡献,贡献多少根据$$i$$和$$j$$之间的距离在gauss上的值\]

    For each pixel i
    sum_of_weights = sum_of_weighted_values = 0.0
    //gauss在3sigma之后几乎没有值,但理论上gauss不管离多远都有值
    //这里只取大概3sigma的范围
    //这里的around包括i自己
    For each pixel j around i
    //贡献由i与j的距离和高斯决定,sigma是标准差,决定高斯的大小
    Calculate the weight w_ij = G(|i-j|, sigma)
    //input是输入图像
    sum_of_weighted_values += w_ui * C^{input}[j]
    sum_of_weights += w_ij
    //这一步是做归一化
    //滤波核不一定是归一化的,可以是任意倍gauss,只用在滤波的过程中归一化
    //保证能量守恒
    C^{output}[i] = sum_of_weighted_value / sum_of_weighted
    
    - ``sum_of_weights``用于归一化
    - 用gauss得到的``sum_of_weights``不等于0,但是其他滤波核不一定,要注意判0- 如果权和为0,那么就按0处理
    - value可以是一个多通道的数

Cross / joint bilateral filtering 联合双边滤波

高斯滤波的问题

  • 高斯滤波模糊了边界
  • 而通常我们希望边界是锐利的(我们希望保留高频的边界)

所以要引入双边滤波

Bilateral filtering 双边滤波

双边滤波基于的观察

  • 边界$$\leftrightarrow$$颜色剧烈变化的地方

Idea

  • 如何保留边界

  • 看像素$$j$$和像素$$i$$的差异是否很大

    • 如果相差不大,说明不是边界,正常按高斯滤波
    • 如果相差很大,就希望$$j$$到$$i$$的贡献变少
  • 简单给kernel加一个控制

    • \[w(i,j,k,l)=exp(-\frac{(i-k)^2+(j-l)^2}{2\sigma_d^2} - \frac{\lVert I(i,j) - I(k,l)\rVert^2}{2\sigma_r^2}) \]

    • 这里将坐标拆开了,(i, j) 和 (k, l)是两个点

    • 左边的分式是距离,增加的是右边的分式,右式也是一个高斯,右式的分子是颜色差异

      相当于给原先的高斯乘上一个$$e^{-右式}$$(exp是e的x次方),让贡献变小

但是这种做法有个问题,它分不清噪声和边界的区别(因为我们认为噪声和边界等价了)

Joint bilateral filtering 联合双边滤波

  • Gaussian filtering:提出用像素之间的绝对距离来判断贡献是多少

  • Bilateral filtering :提出用像素之间的绝对距离和颜色距离来判断贡献是多少

  • Joint bilateral filtering:可以使用更多的标准,具体用什么标准不是固定的

    • 这种思想就叫做Cross / Joint Bilateral Filtering 联合双边滤波

    • 联合双边滤波特别适合用于解决(蒙特卡洛)path tracing结果的denoising问题

    • 不一定非得选择Gauss,这里只需要定义一种函数,随着距离有衰减,符合要求即可

      并且用Gaussian也不一定非得按一般Gaussian的写法,比如前面的\(\frac{1}{\sqrt{2\pi\sigma}}\)可以不要,指数内部也可以不写成\(\frac{x^2}{2\sigma^2}\),一倍\(\sigma^2\)也可以

      • Gaussian
      • 指数函数(的绝对值)
      • Cosine
      • ect.
    • 没什么缺点

在渲染时有很多额外信息是可以免费得到的,G-buffer!

  • Position
  • Normal
  • Albedo
  • Depth
  • object ID
  • etc.

G-buffer是完全没有noise的,并且也与多次bounce无关

Example

假设有以下信息

  • Depth
  • Normal
  • Color

  • A和B:深度也可以描述成一种高斯,将深度差异也考虑进去
  • B和C:考虑法线差异,B和C在法线标准下离得很远
  • D和E:考虑颜色差异,保证阴影不被糊掉
    • 在有noise的情况下用颜色不是很稳妥,但毕竟用颜色还是可以保证不糊掉阴影的边界

每个信息的Gauss都有一个参数\(\sigma\)来控制它,这几个贡献都是乘起来的(见双边滤波给的公式),而谁的贡献大谁的贡献小由各自的\(\sigma\)决定

如何调节\(\sigma\)?控制的标准很多,所以每一项都可以不那么严格,那么每一项一开始都可以取一个巨大的滤波核(一个很大的\(\sigma\))

Implementing large filters

对于任何一个像素,都要考虑其周围\(N\times N\)个像素

  • 对于小滤波核,直接做没问题(e.g.\(7\times7\))
  • 对于大滤波核,可能太耗性能了(e.g.\(64\times64\))
    • 可以做FFT,图像与滤波核相乘,再做IFFT
    • 但是FFT在GPU上优化得并不好,还是比较慢
    • FFT在CPU上快

两种解法

Solution 1: Separate Passes
  • 考虑一个2D Gaussian filter

    • 拆分成功一个水平通道(\(1\times N\))和竖直通道(\(N\times 1\))
    • \(N^2\rightarrow N+N\)
  • 为什么一个2D Gaussian filter可以拆分成两个1D Gaussian filter

    • 因为2D高斯本身就是拆开定义的

      \(G_{2D}(x,y)=G_{1D}(x)\cdot G_{1D}(y)\)

    • filtering == convolution

    • 将2D Gaussian拆成两个1D Gaussian相乘,\(x\)\(y\)没关系,所以可以将\(y\)提出去

    先对\(x\)卷积,再对\(y\)卷积

    \(\iint F(x_0,y_0)G_{2D}(x_0-x,y_0-y)\mathrm{d}x\mathrm{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\)

    • 理论上>复杂一点的卷积核可能就不能拆分了

      实际上对于小的滤波核看起来差异不大(e.g.$ \le 32\times32$)

      比如双边滤波是两个高斯相乘,就不能拆分了

solution 2: Progressively Growing Sizes

Idea: 用逐步增大的filter做多趟的过滤

  • 一个具体的例子, a-tous wavelet transform(不要和小波联系起来)

    • 多趟,每趟都是\(5\times5\)大小的filter

    • 不同趟数下,\(5\times5\)filter有不同间隔

      图中只是以一个点的filter为例,并不是说整个图像只有黑点需要filter,所有像素都需要filter

      第一趟时间隔为1,第二趟时间隔为2,第三趟时间隔为4

      \(i\)\(0\)开始,在做第\(i\)趟时,间隔为\(2^i\)

      \(i=4\)时,间隔为\(2^4=16\),共有\(5\)个样本,则5个样本间有4个间隔,占据\(64\)个格子,总共是\(64\times64\)

      现在将\(64^2=4096\)转变成了\(5^2\times5=125\)

  • A deep understanding

    • 为什么要用一个逐步增大的filter

      • 用一个更大的filter == 去除更低的频率
    • 为什么可以跳着采样

      • Sampling == repeating the spectrum 采样是在频域上搬移频谱

        • 采样得密集说明搬移的频谱和频谱之间距离大
        • 采样得稀疏说明搬移的频谱之间距离小,可能会发生混叠

        • 第一个Pass去掉蓝色部分的频率,第二个Pass去掉黄色部分的频率

        不断变化的filter size是为了逐步去除更低的频率

        进行分段考虑,每一段可以针对性地处理

        • 为什么更高的Pass上可以间隔得更开

          相当于对一个更大的filter做了一个采样

          比如覆盖了\(9\times9\)的范围,并没有做filter,而是采样留下了\(5\times5\)

          这个采样过程对信号往不同方向进行了搬移,搬的间隔正好是两倍的上一趟Pass留下的最高频率(正好把sample的间隔乘了2,图中蓝色部分搬移到黄色部分),正好不会出现aliasing

          而如果一开始就直接做高层的pass,会因为没有将更高频的频谱去除而混叠

        • 实际上这么做可能还会出现一些问题

          • 这个filter不是类似高斯严格意义将高频去除的filter

            尤其是考虑了联合双边滤波,很多高频信息会有选择地留下来,导致搬移的时候会出现问题

            就常常会出现一些格子状的artifacts

Outlie Removal (and temporal clamping)

平常用蒙特卡洛方法渲染时可能会出现一些超级亮的点(outlier, rendering领域也叫firefly)

  • Filtering并不是全能的
    • 有时filter后的结果还是noisy甚至blocky的
      • 比如说可能会将一个很亮的点扩散成一个更大的区域
      • 并且虽然颜色降下来了,但可能还是超过1
  • Idea
    • 在做滤波之前去掉outliers
      • 这样能量就不守恒了
      • 如果想得到完全准确的结果,就不应该做outlier removal,而是等更多的sample
    • 如何处理?

Outlier Detection and Clamping

  • Outlier detection

    • 对于每个像素,取周围如\(7\times7\)(工业界常用的大小)的范围

    • 计算均值(也有用中位数的)和方差

      • 复杂的话可以参考Variance shadow mapping (VSM)

      • 简单的话直接将这些点都扫一边就知道了

      • 绝大多数像素颜色应该集中在均值\(\pm\)若干个方差之间

        均值记为\(\mu\),方差记作\(\sigma\)\(k\)一般取\(1\sim3\)

        outside\([\mu-k\sigma,\mu+k\sigma]\rightarrow\)outlier

    • 可能会把光源干掉了

      • 那就先渲染没有光源的场景
      • 在玩Outlier Removal再将光源装进去
    • 跨场景中几何的边缘可能会找错分布

      • 如果找的点正好是某两个物体交界处,那么就有错误
      • 特殊处理
  • Outlier removal

    其实并不是移除了,而是clamp了

    将outlier Clamp到\([\mu-k\sigma,\mu+\sigma]\),大于的取最大值,小于的取最小值

    • 工业界的做法会更复杂,可能会在某个颜色空间上进行,而且范围也不一定如此简单,会在3D颜色空间上用一个高斯来描述
    • TAA的具体实现

Temporal Clamping

找到像素在上一帧对应颜色,与当前帧blending,如果两帧颜色相差过大,则将上一帧的结果往当前帧结果拉一点,思想类似Outlier removal

\(C^{(i)}=\alpha\overline C^{(i)}+(1-\alpha)C^{(i-1)}\Rightarrow C^{(i)}=\alpha\overline C^{(i)}+(1-\alpha)clamp(C^{(i-1)},\mu-k\sigma,\mu+k\sigma)\)

  • clamp重新引入了noise,这是在noise和lagging之间的一个tradeoff
    • 一般更倾向于没有lagging
    • 就算无法接受带来noise,做一个更大的filter就好了,将noise转化成over blur
  • 是将前一帧拉向当前帧,不能做反了

Specific filtering approaches for RTRT

Spatiotemporal Variance-Guided Filtering (SVGF)

三个因素

SVGF考虑了三个因素

  • Depth

    \(w_z=exp(-\frac{\lvert z(p)-z(q\rvert)}{\sigma_z\lvert\nabla z(p)\cdot (p-q)\rvert + \epsilon})\)

    • 分子表示深度差异
    • 分母表示深度的梯度,\(\epsilon\)是一个微小的值,防止分母为0
    • 如果深度差异大,梯度也大,二者相除,也就认为差异不大了
    • 因此,一般不会直接比较两个点之间的深度差异,而是比较它们沿着面法线投影后的深度差异(或者说是其切平面上的深度差异)

    只需有一定衰减形状即可,不一定是高斯,比如这里就不是高斯,只是一个指数衰减函数(防止分母为0,加上一个微小的值\(\epsilon\)

    • 这里A跟B处于同一个面上,颜色也相近,应该要相互贡献,可二者在深度上却差异较大(因为处在的面的侧向的),公式中的梯度\(\nabla\)就算为了计算二者在法线方向上的深度差异,而二者处于同一平面,法线上的深度差异几乎没有,那么就认为其深度差异并不是很大
    • 深度的梯度表示往某一方向上的变化率,再给一个距离就知道该方向上的深度变化量
  • Normal

    \(w_n=max(0, n(p)\cdot n(q))^{\sigma_n}\)

    同样也不需要这是一个高斯,只需衰减即可

    这里先做了一个clamp,防止法线点乘为负,\(\sigma_n\)控制指数衰减的快慢,也就是判定法线差异是否严格(类似Blinn-Phong中控制Specular)

    • 注意,如果应用了法线贴图或者凹凸贴图,这里比较的是macro normals(没有法线贴图前的normal),否则法线处处不相同就不合理了
  • Luminance (颜色灰度值)

    SVGF用Luminance是因为HDR的原因,用RGB的话简单平均一下也可以,或者直接在RGB空间上算两个点的距离也可以,但是输入的图一定得是HDR的,不能先截断到1,否则denoise后的图就变暗了

    先将RGB颜色值转化成灰度值Luminance,颜色差异大就不应该混合起来了

    \(w_l=exp(-\frac{\lvert l_i(p)-l_i(q)\rvert}{\sigma_1\sqrt{g_{3\times3}(Var(l_i(p)))}+\epsilon})\)

    这里的Var是Variance 方差,根号后的结果是标准差

    通过除以一个标准差,如果标准差过大,则说明不应该过多相信颜色差异

    \(\epsilon\)防止除以0,\(\sigma_l\)控制衰减速率

    • 有一个问题

      如图中B点在阴影中,但是可能由于噪声会导致B非常亮,而A在阴影外也比较亮,A就贡献到B,产生了错误

      那么考虑B点周围的方差,如果方差比较大,就不应该过多地相信这两点之间的颜色差异

    • 分母中的\(g_{3\times3}Var\)

      • 计算周围\(7\times7\)区域的Variance
      • 也可以在时间上通过motion vector累积起来,得到一个相对平滑的Variance
      • 再在B点周围取了一个\(3\times3\)的小区域,在这个小区域再求了一次平均方差
      • 颜色本身带有噪声,通过Var将噪声的影响去除了

Failure Cases

  • 阴影滞后

    光源移动,motion vector为0,那么物体阴影会沿用上一帧,导致残影

Recurrent AutoEncoder (RAE)

Basic Idea

用Recurrent AutoEncoder这样一种结构(神经网络相关),对路径追踪得到的图像做Reconstruction,也就是做滤波,是一种后处理

  • 用后处理神经网络做denoising
  • 使用G-buffer
  • 神经网络自动累计temporal信息
  • 输入noisy的图, 得到denoising后的图

关键结构设计

  • AutoEncoder (or U-Net) 结构

  • Reurrent convolutional block

    每一层神经网络不仅连向下一层,还连回自己,那么跑完当前帧后,下一帧就可以用到上一帧的信息

    这里不是用motion vector,而是靠神经网络学习得到的

优点和缺点

  • 优点

    • 在不同SPP的情况下Performance一样

      Nvdia Optix中带的denoiser就是神经网络的denoiser,在高SPP下性能好

      但是是denoise单张图片而不是图片序列

    • tensor code能解决性能问题

      10ms左右,还是比较慢

  • 缺点

    • 有大量overblur

    • 上一帧的几何边缘位置在当前帧可能会留下残影

    • 亮度高时会有更多artifact

SVGF和RAE对比

Quality Artifact Performance Explanability Where did the paper go
SVGF Clean Ghosting Fast Yes HPG
RAE Overblur Ghosting Slow No SIGGRAPH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/790535.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lecture 10 11 Real-time Physically-based Materials (surface model)

Lecture 10 Real-time Physically-based Materials (surface models and cont.) PBR and PBR MaterialsPhysically-Based Rendering (PBR) 基于物理的渲染渲染内的任何事都应该是PBR的材质、光照、相机、光线传播等等不限于材质,但常常指材质PBR materials in RTR实时渲染中材…

[笔记]Tarjan

Tarjan求强连通分量 定义 DFS树相关 我们对一个有向联通图进行DFS遍历,会得到一棵DFS树。 DFS树的形态是根据我们DFS的顺序来决定的,因此对一个有向联通图来说,它的DFS树可能有多个。我们把这棵树的边称作树边。 其他边我们分为\(3\)类:前向边:从\(u\)到它dfs树上的祖先的…

Lecture 12 Real-time Ray Tracing

Lecture 12 Real-Time Ray Tracing Basic ideasample per pixel PPS 1 SPP path tracing = $$\downarrow$$camera出发打到求出第一个交点(像素上看到的点),这一步是primary ray(工业上实际用rasterization)工业上这一步有一个技巧 将这一步改为光栅化 因为每个像素都要从c…

gcc/g++编译ZR

编译工具链我们写程序的时候用的都是集成开发环境 (IDE: Integrated Development Environment),集成开发环境可以极大地方便我们程序员编写程序,但是配置起来也相对麻烦。在 Linux 环境下,我们用的是编译工具链,又叫软件开发工具包(SDK:Software Development Kit)。Linux 环…

一种优雅的方式整合限流、幂等、防盗刷

大家在工作中肯定遇到过接口被人狂刷的经历,就算没有经历过,在接口开发的过程中,我们也需要对那些容易被刷的接口或者和会消耗公司金钱相关的接口增加防盗刷功能。例如,发送短信接口以及发送邮件等接口,我看了国内很多产品的短信登录接口,基本上都是做了防盗刷,如果不做…

Lecture 06 Real-time Environment Mapping (Precomputed Radiance Transfer)

Lecture 06 Real-time Environment Mapping (Precomputed Radiance Transfer) Shadow from environment lighting通常情况下要实时渲染非常困难 在不同观察方向上As a many-light problem: Cost of Shadow Map is linearly to #light As a sampling problem: Visibility项V会变…

Lecture 07 Real-time Global Illumination (in 3D)

Lecture 07 Real-time Global Illumination (in 3D) 实时渲染中全局光照一般只bounce两次(直接光照bounce一次,间接光照bounce两次)primary light source 真正的光源secondary light source 次级光源: 一切被直接光照照到的物体都会继续将自己作为光源想要用间接光照照亮\(…

Lecture 04 Real-time Shadows 2

Lecture 04 Real-time Shadows 2 PCF and PCSS PCF背后的数学知识 Filter / convolution: 如果对某个函数\(f\)做卷积,可以用\([\omega * f](p)=\underset{q \in \Nu (p)}{\sum}w(p,q)f(q)\)比如PCSS中对某一点q周围区域做卷积求visibility \(V(x)=\underset{q\in \Nu(p)}{\su…

Lecture 05 Real-time Environment Mapping

Lecture 05 Real-time Environment Mapping Recap: Environment Lighting一张表示了来自四面八方的无穷远处光(distance lighting)的图片 Spherical map vs. cube mapShading from environment lighing 非正式地命名为Image-Based Lighting (IBL) \[L_o(p,\omega_o)=\int_{\Ome…

Lecture 02 Recap of CG Basics

Lecture 02 Recap of CG Basics Graphics Pipeline光栅化、深度测试、Blinn-Phong模型、纹理映射&插值 OpenGL 总结:每一个pass定义物体、相机、MVP 定义帧缓冲区、输入输出纹理 定义Vertex Shader / Fragment Shader 渲染其他的多趟pass 如ShadowMapShading Languages Sh…

VulNyx - System

扫描发现 2121是ftp端口 8000 http的一个端口 6379redis端口爆破redis的密码爆破出来时bonjour猜测ftp的密码和redis的密码是一样的 尝试用密码去爆出ftp的用户名报出来用户名是ben那么根据现有的条件 我们可以利用ftp上传文件 可以用redis module load 加载文件那么我们可以用…

Lecture 03 Real-time Shadows 1

Real-time Shadows 1 Recap: shadow mapping Shadow Mapping2-Pass AlgorithmThe light pass generates the shadow map the camera pass uses the shadow mapAn image-space algorithm好处:无需场景中的几何信息 坏处:导致自遮挡和走样问题PassPass 1: Render from light从光…