======Mantra Concepts======
//How to render images and animation from the 3D scene.//\\
//本页所有图片来源:SideFX Docs//
----
Mantra 是 Houdini 内部集成的渲染器。该渲染器的设计风格为**多范式**(//multi-paradigm//)(也就是可以使用不同的编程范式来进行编程,比如 C++)。Mantra 可以使用 scanline / Raytracing / PBR 方式来进行渲染。官方推荐的是使用 PBR 作为默认的渲染方式。
\\
\\
Mantra 对 packed primitives / volume 的渲染上很有效率。我们可以使用 VOP / VEX 进行 Mantra 进行自定义的 shader 开发。
====Mantra 的基本使用====
===Preview rendering===
Mantra 支持 IPR(//Interactive Photo-realistic Render//)。在 Houdini 的 Render view 中我们可以对渲染的变动进行即时的浏览。有两种主要的浏览方式:
* 通过 Preview 粗略的对渲染结果进行浏览。
* 通过渲染指定的区域(''Shift + Drag'')来查看指定区域的效果。
===控制渲染结果===
Mantra 可以通过在几何体上设置 mask 来控制是否应用具体的效果到该几何体上,包括:
* ''Renderable'' 控制几何体是否可渲染
* ''Phantom'' 控制几何体不可见,但产生阴影
* Mask 可以控制是否输出其他层
===其他小技巧===
* Houdini 可以使用 deep camera map 来生成 depth(景深) 贴图,可以用于 //3D// 合成。
* 可以使用 ''Switch'' 控制 Camera 的选择。
* Mantra 节点上的 Control 键可以临时改变一些选项。 需要改变 Frame Range 里的 Output Overrides。
====Sampling and noise====
当渲染的时候,Mantra 必须确定每一个像素的颜色值。Mantra 会通过检查整个 image plane 上的每一个像素来决定颜色值。具体的决定过程就是一个 “光线追踪” 的过程。也就是说,Houdini 会以摄像机为原点发出不同数量的射线。当这些射线“撞击” 到场景中的几何体时,这些射线会带回一些关于几何体的信息(比如颜色等等)。这种带回信息的过程,被称为**采样**(//Sampling//)。
{{ :vfx:houdini:rendering:simplenoaa.gif |}}
然而,在采样的过程中,假设我们的射线并没有“撞击”到几何体的所有位置,那么射线带回来的信息必然会有所缺失。我们将这种缺失称为 //Aliasing//(也就是通常意义的**混叠**,以较少数据表现较多数据产生的信息缺失的情况)。比如对于采样不足的几何体,射线带回来的颜色很可能就不能完整的表示几何体原有的颜色。一种处理该问题的方法就是提高每个像素的**采样次数**。
{{ :vfx:houdini:rendering:complexaa.gif |}}
//动图来源:SideFX documentaton// \\
\\
上述的“采样次数”在 Houdini 中被描述为 //Primary Ray//,也就是所谓的 //Pixel Sample//。该属性决定了被渲染图片的整体质量,特别是几何体的形状。
\\
\\
对于图片中其他的信息,比如灯光、反射、折射,Houdini 也需要 //Primary Ray// 来携带这些信息。而在 Houdini 中,每一条 //Primary Ray// 都会伴随着至少一条的 //Second Ray//。这额外的射线又分为直接 / 间接(Direct / Indirect)两种。
===Direct and indirect rays===
==Direct Rays==
Direct Rays 可以被描述为**与光源有关射线**;换句话说,按照光线追踪的概念,这些射线就是冲着光源去的。而如果射线在朝着光源的过程中周到了几何体的遮挡,那么该“撞击”的位置就不会再携带来自该光源的任何颜色信息了。可以看出来,Direct Rays 用于判断几何体的表面是否处于阴影中,并根据判断的结果来决定射线是否需要携带光源的信息(也就是撞击点是否着色)。
{{ :vfx:houdini:rendering:directsamplingdiagram.jpg?400 |}}
Direct Rays 也同样存在采样混叠的问题,采样不足会导致渲染图像的噪点非常高。这个问题在渲染软阴影的边缘(一般来说是使用 area light产生的)的时候非常明显。一般的处理办法是增加更多的 Direct Rays 。而添加更多的 Direct Rays 以后,又会出现另外一个问题;噪点自身会叠加,因此想将两个源的噪点分开是非常难的。Mantra 中可以通过添加 ''Direct Lighting (per component)'' 选项来查看每个源各自的贡献。比如下图的红色球,就可以分别查看 Direct Diffuse / Direct Reflection 的贡献。这个也就是我们常说的 AOV(passes):
{{ :vfx:houdini:rendering:directpasses.jpg?400 |}}
同时我们也可以通过 Image plane 中的 ''Direct sample'' 来查看当前场景中射线数量。射线的书香会被显示为强度:
{{ :vfx:houdini:rendering:directsamples.jpg?200 |}}
==Indirect Rays==
Indirect Rays 主要用于处理几何体以及其表面的属性。通常来说,Indirect Ray 的方向是由 对应几何体上的 shader 决定的(比如折射率 / 反射率 / Roughness);比如 Refraction Ray 会“穿过”几何体,Reflection Ray 会反弹,而 Diffuse Ray 会随机散布在表面上(遵循半球分布(//hemispherical distribution//))。
{{ :vfx:houdini:rendering:indirectsampling.jpg?400 |}}
比起 Direct Rays, Indirect Rays 的混叠问题更大;而 Indirect Rays 通常会在渲染中产生更多的噪点。总的来说,又小又亮的事物会产生绝大部分 Indirect Rays 的噪点(比如高光的柔反射)。增加 Ray 的数量也可以解决这个问题。而同样的,在增加 Indirect Rays 的数量后,我们也可以使用 ''Indirect Lighting (per component)'' 来生成 passes,并可以用 ''Indirect Samples'' 来查看 Indirect Rays 的数量。
===Volumes===
与采样 surface 不同的是,采样 volume 需要另外一种方法。该方法同样需要 Direct Rays / Indirect Rays,但需要更多次数的采样。该采样的次数被称为** //Steps//**,也就是射线穿过体积类型对象的次数。显然,采样 volume 比起 采样 surface 的消耗更大。
{{ :vfx:houdini:rendering:volumesampling.jpg?400 |}}
当渲染的时候,射线按照指定的 //Step rate// 来进行采样。在每一步,射线都会测量 shader,并将本步的结果按照**体积的密度**累加到当前点上。需要注意的是,体积对象的密度可能会急剧的变化(比如云的稀疏程度),因此相邻的 ray 很可能会计算出差异很大的两个密度值,而这是导致 volume rendering 中噪点的最大原因。该问题可以通过提高射线数量,或使用更小的 //Step// 来解决。
{{ :vfx:houdini:rendering:volumesamplecompare.jpg?400 |}}
==体积渲染的相关优化==
即便是在采样率很低的情况下,一张清楚的体积渲染图也是代价昂贵的,因为 shading 的过程包括了射线每一次穿过体积的运算。幸运的是,Mantra 可以通过一些优化在不牺牲细节的情况下减少渲染的时间。
\\
\\
有一种方法被称作 //Stochastic Transparency//,也就是将密度的累积与 shading 的样本之间的关联割离开。在这种情况下,采样的复杂程度会由光线决定。由于光线的分布并不像体积那样变化剧烈,因此会大大减少由于变化而产生的采样量。
{{ :vfx:houdini:rendering:volumesamplingstochastic.jpg?400 |}}
{{ :vfx:houdini:rendering:volumestochasticcompare.jpg?400 |}}
==体积渲染的 passes==
体积渲染也可以通过添加指定的渲染层来输出 AOV。同样,Houdini 也允许用户使用 image planes 上的选项查看不同射线的贡献。
====Sampling 参数====
===Counting by Number===
==Pixel samples==
决定在每个像素上采样的** Primary ray 数量**。该参数是有两个分量,分别代表从像素的 X 轴和 Y 轴上将像素划分为多少块(见下图)。当像素不是正方形的时候,这两个值可以不相等。很明显,//Primary ray// 的**数量**就是 ''X * Y'' **的值**。
\\
\\
增加 Pixel sample 会提高渲染的质量。但也需要注意的是,Pixel sample 是从两个维度上增加的,因此会显著的提升 Primary ray 的数量。因此需要注意控制 pixel sample,按需添加。
* Houdini render property://vm_samples//
* IFD property://image:samples//
==Variance color space==
通过对色彩空间采样来消除因为差异性导致的锯齿(混叠)。设置该参数至 GAMMA 2.2 会导致图中暗色部分获得更多的采样数。(该参数在实际生产中基本保持默认)
* Houdini render property://vm_colorspace//
* IFD property://renderer:colorspace//
===Counting by Variance===
==Ray variance anti-aliasing==
启用该选项后会导致 Mantra **不再使用固定数量的射线**。取而代之的是,Mantra 将会使用 Ray variance anti-aliasing 决定每个 Primary ray 所关联的 Secondary ray (在Ray Tracing 中,所谓的 Secondary Ray 是源自 Primary ray 与几何体碰撞处的射线)的数量。具体的来讲,Mantra 首先会使用数量较小的射线和当前的采样结果来测量差异性。当得到结果后,取决于差异的大小,Mantra 会继续发送更多射线直到达到 Max Ray Sample 的限制。
\\
\\
该选项可以有效的优化渲染过程,因为更多的射线被送到了需要这些射线的区域。当然,如果在 remove noise 选项中,射线的最小数量和最大数量相等,我们可以关闭该选项获得更加的渲染时间。
\\
\\
//注:该参数与Noise Level 相关,因为该参数通过差异性衡量射线的数量。//
* Houdini render property://vm_dorayvariance//
* IFD property://object:dorayvariance//
==Min Ray Samples==
该选项决定了渲染时,对应 **BSDF** 类型使用的**Secondary rays** 的**最小值**。如果关闭 Ray variance anti-aliasing,该选项等于 Secondary rays 的数量,不管 Noise Level 是多少。
\\
\\
该数值会与当前的 Pixel sample 数量和 BDSF 的类型数量相乘。相乘之后得到的才是最终的 secondary ray 的数量。
\\
\\
//注:此处可以将 BSDF的类型视作光照模型中的不同部分,比如 diffuse,reflection 等。//
* Houdini render property://vm_minraysamples//
* IFD property://object:minraysamples//
==Max Ray Samples==
当 Ray Variance anti-aliasing 启用的时候,该参数表示**每个** **BSDF** 允许使用的 Secondary rays 的数量上限,即便 Noise Level 从未达到上限。该属性与 Min Ray samples 一起,可以允许用户自定义渲染采样的范围。
\\
\\
与 Min ray samples 相同,最终的 secondary ray 的**数量上限**是该参数与 Pixel samples 和 BDSF 类型数量的**乘积**。距离来说,比如渲染一个只有 diffuse 的材质,而 Pixel sample 设置为 3*3。现在将 Max Ray sample 设置为 1,那么最终得到secondary ray 的**数量上限**就是:
1 (只有一个 BDSF: diffuse) * (3 * 3) (pixel sample) = 9
关于什么时候增加 Max Ray Sample 可以参考 Remove Noise 章节。
* Houdini render property://vm_maxraysamples//
* IFD property://object:maxraysamples//
==Noise Level==
该选项与 Ray variance anti-aliasing 参数有关。当 Mantra 使用差异的大小来决定 secondary ray 的数量的时候,该参数的意思是:如果测量到的差异性超过该参数的数值,那么 Mantra 将会产生更多的 secondary ray 来控制噪点处于用户希望的范围内。在这里,差异(//Variance//)主要是指的**采样的差异**(这个概念和统计里的方差基本上一个意思,也就是说明采样样本之间的差异性,一组样本全相同则方差为 0)。一般说来,如果渲染的结果中有不能接受的噪点区域,我们应该在可能的情况下尽量提高 Noise Level。这样的话,射线只会在差异性更大(也就是噪点更多更地方)增加,从而达到消除指定区域噪点的效果。至于的 sample 的分布是否在某个区域不足,可以通过查看 image plane 中的 sample 选项得知。
\\
\\
如果使用 Noise Level 并不能很好的选取我们想要降噪的区域,我们可以选择添加 per-object sampling 属性到出现问题的区域。
* Houdini render property://vm_variance//
* IFD property://object:variance//
===Independent Quality===
在 Mantra 中我们可以设置三种 BSDF 类型的质量,分别是 //Diffuse、Reflection、Refraction//。这三个参数非常类似,唯一不同的只是应用到不同的 BSDF 类型上。这三个参数有几个共同的特点:
* 都是作为 Min / Max ray samples 的**乘数**,并且作为 Noise Level 的**除数**,然后通过这种方式计算出 Mantra 产生 secondary ray 的范围。以 diffuse quality 为例,若 ray sample 的范围为 ''1-8'',noise level 为 ''0.1'',diffuse quality 为 ''2'',那么Mantra 会产生的 secondary ray 将处于 ''2-16'' 之间,而这个射线的计算是基于 ''Noise Level = 0.05'' 的。
* 这三个参数都只会应用到 **//Indirect Sample//** 上(Ray sample 和 Noise Level 也是)。
* 可以通过 ''Extra Image Plans - pre-compoent'' 添加对应 Pass 查看。
==Diffuse Quality==
//Diffuse Quality// 控制的是 //Indirect diffuse sampling//。通常,非直接的光源(比如表面反射的光,体积中散布的光)会显著的提升渲染中的噪点。提高本参数可以降低噪点,但提高渲染时间。
* Houdini render property://vm_diffusequality//
* IFD property://object:diffusequality//
==Reflection Quality==
该参数控制 //indirect reflection sampling// 的质量。
* Houdini render property://vm_reflectionquality//
* IFD property://object:reflectionquality//
==Refraction Quality==
该参数控制 //indirect refraction sampling// 的质量。//Indirect refractions// (光线的折射,比如玻璃)会导致噪点的产生。
* Houdini render property://vm_refractionquality//
* IFD property://object:refractionquality//
===Volume===
==Volume step rate==
Houdini 在射线穿过 Volume 的时候对其进行采样。该行为与 Mantra 的射线与几何体表面撞击类似,只是在 Volume 中的基本组成单位被称为 **Voxels**,而射线正是以 Voxel 为单位进行采样。本参数代表了每一次采样中,每一条射线会穿过多少个 Voxels。
\\
\\
{{ :vfx:houdini:rendering:volumequality.jpg?400 |}}
该参数的初始值是 ''0.25'',意味着每四个 Voxel 中就会有一个 Voxel 被射线穿过。同理,''1'' 代表所有 Voxel 都会被采样,''2'' 则代表所有 Voxel 都会被采样两次。可见的是, Volume step rate
也是作为乘数乘到对应体积对象的采样数上。这与之前提到的 Pixel sample 非常类似。
\\
\\
需要注意的是,Volume step rate 会显著提高渲染时间,因此我们最好按照需要来添加该次数的值。一般来说,初始设定就可以减少噪点,而超过 ''1'' 以后就基本不会看到任何改进了。
* Houdini render property://vm_volumesteprate//
* IFD property://object:volumesteprate//
==Volume shadow step rate==
该参数可以按比例的减少 Volume **Shadow** 的 step rate。该值变小会导致 Mantra 使用更大的 Step 来进行采样(也就是帮助中说的 large Ray)。当值为 ''1'' 的时候意味着 Mantra 会使用 质量相同的 Shadow ray 和 shading ray 进行采样。
* Houdini render property://vm_volumeshadowsteprate//
* IFD property://object:volumeshadowsteprate//
===Transparency===
==Stochastic transparency==
//注:Stochastic transparency 是一种计算透明的新算法,详情见参考资料章节相关论文。//
\\
\\
该参数控制当**射线穿过透明对象时进行采样的数量**。增加该值可以减低透明 / 半透明物体的噪点。该选项比起增加 Pixel sample / Volume Step rate / Min & Max Ray sample 等等效率更高。不过需要注意是,Stochastic 类型的采样对 Indirect ray 产生的噪点**没有任何影响**。
\\
\\
有几点需要注意:
* //Micropolygon rendering// 并不支持该选项。
* 不支持透明渲染的渲染器(pass)也不支持该选项(比如 deep shadow maps)
* 上述情况下将所有的与透明相关的结果组合在一起会更加有效。
* Houdini render property://vm_transparent//
* IFD property://image:transparent//
==Stochastic samples==
该参数控制透明采样的数量。该值越高得到的结果越好(适用于体积和半透明表面)。
* Houdini render property://vm_transparentsamples//
* IFD property://image:transparentsamples//
===Utilities===
==Enable Indirect Sample Limits==
将 Direct rays 从 Indirect rays 中分离出来,从而允许对这两种不同的射线应用不同的**采样率 / Noise level**。总的来说,如果渲染中 Direct Rays 产生了过多的采样,我们就可以将其分开处理。该选项会启动三个新的参数供 Indirect Rays 使用:''Min Indirect Ray Samples'', ''Max Indirect Ray Samples'', ''Indirect Noise Level''。
* Houdini render property://vm_decoupleindirect//
* IFD property://object:decoupleindirect//
==Sample lock==
采样得到的结果通常是随机的图案。如果在连续帧中,该图案可以能会根据帧的不同而变化。这样会导致一个后果:噪点在不同的帧上有不同的分布,而播放动画就会导致一种“嗡嗡” (类似电视机白躁)的情况出现。这种情况下,我们很难去评估场景里的其他元素。
\\
\\
Sample lock 提供了一个选项,让使用者可以将采样的分布固定下来,这样可以使每帧中的噪点都处于相同的位置。在某些情况下(特别是对渲染结果进行降噪的处理中),固定噪点的位置对分析噪点非常帮助。
\\
\\
该值在 Houdini 中默认关闭,因为锁定的采样对一般的渲染序列说并不能被接受。
* Houdini render property://vm_samplelock//
* IFD property://image:samplelock//
==Random seed==
改变该参数会导致 Mantra 用于采样的样本发生变化。一般来说不不用改。
* Houdini render property://vm_randomseed//
* IFD property://renderer:randomseed//
==Allow image motion blur==
提供这个选项的目的是因为某些情况下需要计算 motion blur 但又不想将 motion blur 添加到最后的渲染图片中。因此这种情况下该选项应该被关闭。
\\
\\
具体的来说,这些包含了模糊区域位置的信息(对 motion blur 来说是必须的)可以通过 Shading 中的 ''GetBlurP()'' 来导出,从而避免了通过最后渲染而产生的不必要的损耗。
\\
\\
该参数只有在 motion blur 启用的新情况下才有效。关闭该选项会导致 motion blur 将不再被渲染,但模糊的位置信息还是会被计算。
* Houdini render property://vm_imageblur//
* IFD property://renderer:imageblur//
====Mantra limit parameters====
总的来说,Limits 表示各种 BSDF 类型中射线反弹的次数。当反弹的次数超过该限制就将不会再反弹。
\\
\\
所有超过了 limit 数量的行为都可以通过 At Ray Limit 中的选项来控制。
==Reflect limit==
该属性控制射线在场景中的最大反射次数。
{{ :vfx:houdini:rendering:reflectlimitcompare.jpg?400 |}}
从摄像机的角度观看,可以看到 reflect limit 会对场景结果造成很大的的影响。但在某些情况下,该影响并不是那么明显。来看看下面这张图:
{{ :vfx:houdini:rendering:reflectsubtlecompare.jpg?400 |}}
在这张图中,reflection limit 的影响几乎不能被肉眼识别。因此这种情况下我们可以减少 reflect limit 的次数来优化整个场景的渲染时间。
\\
\\
需要记住的是,当光源第一次被某对象反射的时候,该反射会被考虑为 direct reflection。因此,即便是 Relfect limit 设置为 0,我们仍将看到对象上存在来自光源的高光反射。
* Houdini render property://vm_reflectlimit//
* IFD property://object:reflectlimit//
==Refract limit==
该属性控制射线在场景中的最大折射次数。
{{ :vfx:houdini:rendering:refractlimitcompare.jpg?400 |}}
上图是在不同 limit 数量下测试。产生折射的格子数量与对应的最大折射次数是匹配的。当然这种情况只是一种比较极端的情况;大多数情况下我们没有一堆正对着摄像机(折射现象最明显的位置),可以折射的对象。因此,通常我们可以在不影响图像质量的情况下降低 refract limits ,从而优化渲染时间。
{{ :vfx:houdini:rendering:refractsubtlecompare.jpg?400 |}}
需要注意的是,refract limit 代表的是射线穿过表面的次数,而不是对应对象的数量:
{{ :vfx:houdini:rendering:refractlimitsurfaces.jpg?400 |}}
与 reflect 类似,光源在几何体上的第一次折射是属于直接折射,因此即便 Limit 为 0,我们也会见到折射。但通常场景中的几何体和光源之间都有两个表面,因此直接折射在最后的渲染结果中并不会很明显。
* Houdini render property://vm_refractlimit//
* IFD property://object:refractlimit//
==Diffuse limit==
该参数决定场景中漫反射的最大次数。
{{ :vfx:houdini:rendering:diffuselimit.jpg?400 |}}
该参数与反射和折射不同。该参数会增加场景中所有光的数量,并且对**全局光照**(//Global illumination//)作出大部分的贡献。当该参数大于 0 的时候,产生漫反射的表面将使用来自场景中其他几何体的光源作为直接光源的补充,参考下图:
{{ :vfx:houdini:rendering:diffuselimitcompare.jpg?400 |}}
可以看到的是,当 Diffuse limit 增加以后,最后的渲染结果会被显著的影响。显然,如果需要更加真实的模拟现实光照条件,我们需要尽可能的增加 Diffuse limit 的数量。然而,因为光在传输的过程中(尤其是在每次反射的过程中)会衰减,因此,当 Diffuse limit 的值超过 4 以后,我们就很难再看到渲染结果有比较明显的提升了。除此之外,随着 Diffuse limit 的数量的增加,噪点的数量和渲染时间会显著增加。
{{ :vfx:houdini:rendering:diffusesubtlecompare.jpg?400 |}}
* Houdini render property://vm_diffuselimit//
* IFD property://object:diffuselimit//
==Volume limit==
该参数控制射线在体积中的传播次数。
{{ :vfx:houdini:rendering:volumelimit.jpg?400 |}}
通过增加该参数我们可以得到更加真实的体积渲染结果;该结果在有直接光源穿过体积某个部分的时候特别明显。需要注意的是,如果希望体积接收来自其他对象的光线,该参数必须大于 0.
{{ :vfx:houdini:rendering:volumelimitcompare.jpg?400 |}}
只要该参数大于 0,fog 类型的体积就能获得正确的 scattering 结果(也就是当光穿过体积时的那种特别有特点的散布结果)。但因为该参数需要与 Diffuse limit 一起决定光的贡献,因此该值超过 4 以后也同样不会对渲染结果有明显的提升。同时,增加该参数会显著的提高渲染时间。
* Houdini render property://vm_volumelimit//
* IFD property://object:volumelimit//
==Opacity limit==
每当射线穿过透明的表面或者是体积,该射线会自动累积透明的总量。如果累积的总量超过了本参数的限制,那么 Mantra 将假设之后所有的 surface / volume 都是**不透明**的。
{{ :vfx:houdini:rendering:opacitylimitdiagram.jpg?400 |}}
可以看到的是,Opacity limit 与反射 / 折射的限制非常像。但有一点不同,Opacity limit 是通过累积的方式而不是单纯计数的方式来控制结果的。来看看下面的例子:
{{ :vfx:houdini:rendering:opacitylimit.jpg?400 |}}
上图中三个网格的 opacity 都是 0.1。需要注意的是,透明(//transparent//)指的某些对象:**非完全不透明**,且没有出现因为**折射**导致的透明。在下面的例子中,我们将左边的球的 opacity 设置为 0.5, 且没有折射;将右边的球的 opacity 设为 1,并且带有折射。可以看到的是,**opacity limit 对折射是完全没有影响的**,且只对 opacity 值小于 1 的对象有影响。
{{ :vfx:houdini:rendering:opacityvsrefract.jpg?400 |}}
减少 opacity limit 可能会节省 1-5% 的渲染时间。但如果我们使用**过低**的 limit 值,则可能会**导致条纹状的图案**或者其他的痕迹。这种情况在摄像机移动 / 对象带动画的情况下非常明显;特别是烟雾的渲染,这种情况下烟雾的透明度会一直变化,因此观测到的问题也尤为明显。
{{ :vfx:houdini:rendering:badopacitylimit.jpg?400 |}}
默认初始值对于一般情况来说有一些过于大了。但在修改 limit 值的时候需要注意每一帧的情况,最好是逐帧检查,确保所有帧都不会出现问题。
* Houdini render property://vm_opacitylimit//
* IFD property://image:opacitylimit//
==Color limit==
该参数代表了来自 **indirect source** 的最大采样数。当使用 PBR 或者 Path tracing 的时候,总的光照也由该值决定上限。
{{ :vfx:houdini:colorlimit.jpg?400 |}}
当对强度非常高的间接光源进行采样的时候,PBR 会导致渲染结果会附带一些小白点(//spikes//),(就像是黑夜里的萤火虫一样)。这种情况如果不使用非常高的 sample rate,是很难去除的。来看看下面的例子:
{{ :vfx:houdini:rendering:colorlimitpixelsamples.jpg?400 |}}
可以看到的是,右图中即便我们使用 12 * 12 的 pixel sample,渲染结果中依然存在小白点。当然我们可以通过 min / max ray sample 来去掉这些点,但同时会导致渲染的时间大大增加。
\\
\\
而通过减少 Color limit 来限制光源颜色的最大值,是对该类问题非常好的一个解决方案。
{{ :vfx:houdini:rendering:colorlimitcompare.jpg?400 |}}
需要注意的是,虽然 Color limit 可以在不提高采样率的情况下有效的解决这种小白点的问题,但是限制间接光源的最大值**会导致整个场景光照强度的下降**。该现象在主要使用间接光源照明的的场景中尤其明显。
* Houdini render property://vm_colorlimit//
* IFD property://image:colorlimit//
==At ray limit==
该参数指定当射线达到了光线追踪设定上限的时候 Mantra 会采取的行为。比如下图就是当 refract limit 设定为 2的 时候不同选项呈现的结果:
{{ :vfx:houdini:rendering:atraylimitcompare.jpg?400 |}}
可以看到,如果使用了 ''Use Black Background'',Mantra 会对超过限制之外的元素进行黑色渲染。该选项作为默认值,一般用于大多数不会超过限制的场景渲染中。但当场景中某些限制被超过的时候,那么黑色就会非常明显。因此,我们会使用另外一个 ''Use Direct Lighting as Background Color'' 选项来处理;该选项会使用场景中直接光源的的颜色来取代黑色(这在使用环境贴图作为光源的时候尤其好用)。
* Houdini render property://vm_raylimiteval//
* IFD property://renderer:raylimiteval//
====Removing Noise====
如果采样的数量不足,最后的渲染结果将会有很多噪点。简单粗暴的增加总体的采样数可以减少噪点,但同时也会导致渲染结果中很多部分采样过度,从而导致渲染时间增加。总的来说,最理想的状态是向对应的区域发射对应数量的射线。这对渲染的优化是极其重要的,往错误的地方发射不匹配的射线不但不会提高渲染的质量,而且会提高渲染的时间。通常情况下在设置渲染的质量和速度的时候,我们一般在之间找一个平衡点。为了尽可能的减少噪点,我们可以从如下的部分开始组件渲染分层:
* Direct Lighting (per component)
* Indirect Lighting (per component)
* SSS (Subsurface Scattering)
* Direct Samples
* Indirect Samples
这些层允许我们分析场景中不同的部分。下面我们将通过一张具体的图片来分析整个测试流程:
{{ :vfx:houdini:rendering:fullscene.jpg?400 |}}
上面的图片包括了不同类型的材质和运动模糊。其他的设置都是默认,除了 pixel sample 设置到了 ''1 * 1''。而在下面的流程中,我们将通过每次只修正一个参数来进行之前所说的降噪。
===Motion blur===
当我们渲染运动物体的运动模糊的时候( Mantra 中的 ''Allow Motion Blur'' 启用的时候),可能会有大量的噪点出现。该 Noise 就像是对静态物体进行采样一样,如果在采样单位之间有细节或信息丢失,就会产生噪点。如果被渲染的物体需要通过时间 / 空间 进行采样,那么该噪点的现象会更加严重。
\\
\\
**处理办法:**
\\
\\
一种处理办法:增加 ''Pixel Samples''。
\\
\\
**为什么这么做**:
\\
\\
之前提到 ''Pixel Sample'' 的结果会作为 Multiplier 乘到其他所有的射线上;因此 ''Pixel Sample'' 对运动模糊也有效。如果增加 Pixel sample 是必要的,我们可以在增加 Pixel sample 的同时减少 secondary rays 的数量。
{{ :vfx:houdini:rendering:noise_motion_blur.jpg?600 |}}
**如何检查噪点:**\\
\\
我们可以通过检查被渲染物体的 Alpha 通道边缘来查看噪点的情况。如果物体有重叠,关闭 ''allow motion blur'',通过与没有运动模糊的场景对比噪点即可。
===Depth of field===
当摄像机启用 ''Enable Depth of Field'' 选项后,离摄像机有一定距离的物体会景深,而景深会导致噪点。这种情况在高光处和物体边缘特别明显。
{{ :vfx:houdini:rendering:doff_noise.jpg?600 |}}
**处理办法:**
\\
\\
增加 ''Pixel Samples'' 是**唯一**的解决方法。
\\
\\
不过,如果某个区域处于对焦位置,我们可能会注意到其他类型的噪点。对于这些噪点,我们可以通过共同使用提高 ''Pixel Sample'' 和使用其对应的降噪方式来得到更好的优化效果。但请记住,''Pixel samples'' 的提高等于乘以射线的数量,因此我们并不需要像关闭景深时那样多的 secondary rays(也就是为修正景深噪点而提高的 Pixel sample 同样会修正别的射线产生的噪点)。
\\
\\
**如何检查噪点:**\\
\\
对该种噪点的识别同样可以通过检查对应物体的 Alpha 通道来进行。一般来说,检查物体的边缘,或者沿着物体运动的路径检查是一种很有用的手段。对于重叠的物体,同样可以使用关闭景深选项,再与没有景深的渲染结果进行噪点数的对比来看出。
===Edge aliasing===
当 Primary Rays 数量不足时,被渲染对象的边缘会变得像锯齿一样粗糙。该现象在高对比度区域 / 高频重复图案中 有其明显。
{{ :vfx:houdini:rendering:edge_aliasing_noise.jpg?600 |}}
**处理办法:**
\\
\\
增加 ''Pixel Samples'' 是**唯一**的解决方法。对于 seoondary ray 数量的处理同景深。
\\
\\
**如何检查噪点:**\\
\\
检查 Alpha 通道中对应物体的边缘,或者沿着其运动路径检查即可。
===Direct Illumination===
==Direct reflections==
Direct reflections,也就是物体表面直接反射光源产生的图案,通常会产生斑点状的噪点图案。该现象在材质的 roughness 值处于 ''[0.1, 0.3]'' 之间非常明显,尤其是处于 area light 的照明下。
\\
\\
**处理办法:**
- 最好的去除这种类型的噪点是**提高对产生该噪点的光源的采样数**(//Lighting Sample//)。对光源的采样数实际上扮演了 Diffuse Rays 的**乘数**。因此,我们需要将该采样数控制在一定的范围内。
- 提高 ''Pixel samples'' 也会有帮助,但就像之前说过的,作为一个提升所有 ray 数量的手段,''Pixel samples'' 可能导致其他区域采样过度。
- 增加 Direct Rays 的数量也可以有效的清除该类型的噪点。
{{ :vfx:houdini:rendering:lighting_sample_noise-min.jpg?600 |}}
综上,我们自始至终都需要考虑,如何在清除指定光源产生噪点和清除直接光源产生的噪点之间找一个平衡点。
\\
\\
**如何检查噪点:**
使用 ''Direct Reflect'' pass 既可以检查 Direct reflections 对场景的贡献。对于复杂的、存在非常多灯光的场景,我们可以将 ''Direct Reflect'' 层用 ''Per light'' 的方式导出。这种方法允许我们将指定的、希望检查噪点情况的灯光分离出来;同时也允许我们只对这样的光源增加采样的数量。
==Direct refractions==
在渲染中,当光源直接穿过**单个表面**(比如一个 grid)的时候会产生 Direct Refractions;同时,也会产生斑点状的噪点图案。该现象在材质的 roughness 处于 ''[0.1, 0.3]'' 区间时非常明显,特别是在使用 Area / Environment 照明的情况下。
注意:只有**第一次**折射会被考虑为**直接折射**。任何超过一次以上的折射都会视作**间接折射**。
**处理办法:**
- 最好的方法是增加对导致噪点光源的采样数。增加光源采样数等于将采样数乘到 Diffuse Rays 的数量上,因此将该值控制在一定范围内比较好。
- 增加 ''Pixel Samples'' 也有帮助,但会导致没有噪点的区域采样过度。
- 增加 Directly Ray 的数量(与 reflection 一样需要找一个平衡点)。
{{ :vfx:houdini:rendering:refraction_noise-min.jpg?600 |}}
**如何检查噪点:**\\
\\
开启 ''Direct Refract'' 渲染层检查即可。
==Direct shadows==
如果场景中有一个点与光源没有直接的路径连接,那么该点处会产生 Direct Shadows。在成阴影的过程中,渲染器会在几何体的边缘产生斑点状的 / 粗糙的噪点图案。该现象在由 area light 产生的 soft shadow 下特别明显。
{{ :vfx:houdini:rendering:directshadowperlight-min.jpg?600 |}}
**处理办法:**
- 最好的方法是增加对产生噪点光源的采样数。
- 增加 ''Pixel samples'',缺点不再复述。
- 增加 Direct rays 的数量。
{{ :vfx:houdini:rendering:d_shadow_noise-min.jpg?600 |}}
**如何检查噪点:**
\\
\\
使用 ''Direct Diffuse'' 层即可。如果灯光较多,可以通过 ''Per Light'' 选项分离出指定的灯光。
===Indirect illumination===
==Indirect diffuse==
相比起 Direct diffuse,Indirect diffuse 由场景中其他的渲染对象贡献而来,而这个过程中也会产生噪点。在以下情况同时存在的情况下,该现象会尤其明显:
* 有物理精确光源(//physically accurate light sources//)
* 该光源特别靠近其他对象(比如光的相互遮罩、光的交叉)
* 相比直接光源,该光源的贡献特别小。
{{ :vfx:houdini:rendering:ind_diff_noise-min.jpg?600 |}}
**处理办法:**
\\
\\
- 最好的方式是增加 Indirect Sample 的数量(在 Mantra 中修改 ''Diffuse Quality'' 参数)。
- 增加 Pixel samples。
- 调整 ''Noise Level'',该方法可以控制噪点低的区域的采样数不会不会暴增。
推荐一开始从 Noise Level 入手,并且使用很小的数值进行调整,直到看到某些区域的 Indirect Diffuse 噪点开始被影响以后,再使用 Diffuse Quality 参数调整采样数(Noise Level 有助于筛选出最应该提高采样数的区域)。
**如何检查噪点:**\\
\\
使用 ''Indirect Diffuse'' 层即可查看细节。对于灯光多的场景,使用 ''per light'' 选项查看每个灯光的信息。
\\
\\
如果只是希望得到一张清晰的图片,那么试图从渲染结果中**完全**去除噪点是没有必要的。在大部分情况下,当直接光与间接光混合在一起的时候,indirect noise 通常是不可见的。我们可以通过 //Combined color// 面板来查看采样对对渲染图精确度的影响。
在某些情况下,如果我们想让我们的间接光源得到足够的采样数,那么我们不得不为噪点设一个非常低的阈值(Noise Level)。这种情况下,我们同样可以增加 ''min ray samples''。如果噪点仍然存在,那么增加 ''Pixel samples'' 可能是最好的选择了。
增加 Pixel samples 会得到更好的降噪效果,但会令 Noise Level / min & max ray samples 被重新评估。
{{ :vfx:houdini:rendering:id_noise_check-min.jpg?400 |}}
==Indirect reflections==
作为其他物体表面产生的反射, Indirect reflections 可能会贡献场景中大部分的 Noise。当 反射明亮、光滑、有光泽的时候(//Bright & glossy//),噪点会非常明显。同时,因为间接反射会为 pixel 贡献更多的颜色,这通常会导致 ''firefiles'' 类型的噪点(也就是因为)
====参考资料====
[[https://www.nvidia.com/object/nvidia_research_pub_016.html|Stochastic Transparency, Eric Enderton, Et Al. SIGGRAPH 2010]]