常规工具着色器

圆角

CG 很可能看起来不真实,原因是对象的边的几何形状都是尖锐的,而在现实世界中,所有边都是稍微有点圆、带切角、磨损或带圆角的。此圆角边常常“捕捉光”并产生使边更具视觉吸引力的高光。

mia_roundcorners 着色器在渲染时可以创建出“圆边”错觉。此功能主要用于加速建模,如桌面,无需将其创建为带圆角或切角的边。

无圆角
无圆角
圆角
圆角

着色器扰动法线向量,应该在通常使用凹凸贴图处应用该着色器,例如,如果是 mia_material,则在 bump 参数处。

该函数不是置换,它只是着色效果(和凹凸贴图一样),并且它最适合直边和简单几何体,而不适合高级的高度弯曲的几何体。

declare shader vector "mia_roundcorners" (
        scalar "radius",
        boolean "allow_different_materials",
        shader  "bump",
        integer "bump_mode",
        vector  "bump_vector",
    )
    version 3
    apply texture
end declare	

radius 参数定义圆角效果的半径,以世界空间为单位。

如果禁用allow_different_materials,则仅当所有面都具有相同材质时才发生圆角效果。如果启用了该参数,则任何材质的面都可以发生圆角效果。

bump 参数可以穿过所有处理附加曲面凹凸的其他凹凸着色器,例如,mib_bump_map2 或类似。仅当 bump_mode 为 0 时才使用该参数。

为更好地支持 OEM 集成,引入了新参数 bump_modebump_vector

bump_mode 定义 bump_vector 的坐标空间,和着色器本身的返回值(也是一个向量),以及是否将其解释为“法线向量扰动”或整个新的“法线向量”。

以下是合法的值:

“添加”模式意味着向量包含法线扰动,即向当前法线添加修改。“设定”模式意味着实际法线被替换为传入向量,上述坐标空间对其做出了解释。同样对于输出,“添加”模式意味着着色器返回要添加到当前法线的扰动向量,而“设定”模式意味着它将返回整个法线向量。在以上两种情况中,着色器实际上都没有修改当前法线。

环境模糊

着色器功能和参数

mia_envblur 着色器通过接受一些其他环境着色器作为输入以运行,这些环境着色器通常是在 HDRI 环境贴图中执行环境查找的着色器。渲染开始后,它执行一次性设置,并将该环境着色器的特殊格式的结果光栅化为内部棱锥过滤器结构。

继续渲染时,着色器可以在该环境贴图中执行十分有效的模糊操作,其操作方式与将大量光泽反射光线发射到着色器的方式类似,即快速产生完全平滑的结果。

declare shader "mia_envblur" (
        shader  "environment",
        scalar  "blur"               default 0.0,
        boolean "mia_material_blur"  default on,
        integer "resolution"         default 200
    )
    version 1
    apply environment, texture
end declare

environment 是该着色器查找的实际环境着色器。如果没有指定,则使用全局摄影机环境。

blur 是图像上应用的模糊量(范围从 0.0 到 1.0)。如果该值为 0.0,则忽略内部位图而直接查找环境着色器,就如同没有 mia_envblur 着色器一样。

mia_material_blur 设定为启用后,可以自动计算模糊量。mia_material 执行的任何反射环境查找都会在 mia_envblur 中产生相应的模糊。在这种情况下,将 blur 保留为 0.0。有关该功能的更多详细信息,请参见自动模糊页。

resolution 是用于过滤的内部棱锥数据结构的分辨率。默认值为 200,表示采用 200 x 200 采样的贴图并存储,用于后续过滤。应该将该值设定得足够高,以解析环境贴图中的最小功能。通常,对于静态图像,200 已经足够,但动画需要更高的分辨率 (1000)。

请务必记住,mia_envblur 在启动时对环境着色器执行一次性光栅化。这表示该着色器在整个场景中必须恒定,不能是复杂的依赖于位置的混合环境着色器。该环境可以随时间而更改,因为每个帧都重新执行光栅步骤。

使用情况

环境模糊着色器 mia_envblur 旨在提高渲染质量和性能,渲染主要是反射 mental ray 环境(即主要不是反射其他对象)。

着色器主要用于由 HDRI 环境贴图包围的产品可视化渲染,以便在希望借助 HDRI 反射集成真实场景中的 CG 对象和希望进行平滑但快速的查找时起到反射和视觉效果作用。

着色器不用于内部架构渲染,因为在这些(密封)场景中,大多数反射光线被反弹以照亮其他对象;该着色器的用途是帮助照亮其他对象的反射光线,即,其最大的优点是处于“开放”场景中1

反射环境贴图的对象
反射环境贴图的对象

此处是一个反射不具有光泽度的环境贴图2的示例对象(即,完美镜面反射)。这看起来没有问题,因为没有执行准随机采样。

但是什么是我们想要创建的光泽反射呢?如果只是简单地使用 mia_material 的光泽反射,则会获得以下结果:

具有 8 个采样的光泽反射
具有 8 个采样的光泽反射

显然,默认的 8 个光泽反射采样不论在何处都不够,特别是具有如此高对比度的环境贴图。尝试使用 100 个光泽采样数(较大性能损失处)时,将产生以下结果:

具有 100 个采样的光泽反射
具有 100 个采样的光泽反射

这样会更好,但是还是没有达到“平滑”光泽反射。100 个采样使渲染(按幅值顺序)速度变慢,且仍然不够!我们可以执行什么操作?

我们希望的不是多次查找环境。不是 8 次,也不是 100 次,而是 1 次,除非我们希望查找已经包含所需模糊

完成此过程需要启用 mia_materialsingle_env_sample 参数,然后将 mia_envblur 用作环境着色器,将“原始”环境贴图用作 mia_envblurenvironment 参数。

返回原始的 8 个光泽采样数,可以快速渲染以下结果:

使用 <i>mia_envblur</i> 的光泽反射
使用 mia_envblur 的光泽反射

这样看起来好很多,而且渲染速度更快,但是模糊级别是恒定的。一个更高级的方法是通过启用 mia_material_blurmia_envblur 派生模糊以应用。

假定我们已将以下贴图应用到 mia_materialrefl_gloss 参数:

光泽度贴图
光泽度贴图

借助 mia_envblur 生成的渲染如下所示:

通过 <i>mia_material_blur</i> 映射光泽度
通过 mia_material_blur 映射光泽度

请注意,mia_envblur 着色器仅支持各向同性查找,使用它进行查找时,将忽略 mia_material 的所有各向异性参数。

此外,请不要忘记使用 single_env_sample 功能;仅模糊环境贴图通常是不足以对抗噪波的。

请记住,其他对象仍将使用多个采样以传统方式反射,该功能仅适用于环境查找。因此,使用 refl_falloff_dist 将“实际”反射限制为仅对象附近时非常有用,而远距离对象的反射由环境接管3

无 <b>refl_falloff_dist</b>
refl_falloff_dist
使用 <b>refl_falloff_dist</b>
使用 refl_falloff_dist

在右侧图像中,马腿仅反射非常接近地面的部分,马仅反射最接近地面的部分,其余部分是环境反射。这样会比跟踪这些反射更快地产生结果,并减少图像中的噪波。

灯光曲面

着色器功能和参数

mia_light_surface 着色器主要用于帮助对光源“可见”部分(荧光灯管中的实际灯管、灯泡中的实际灯泡等)创建物理上正确的渲染,但仍然使用传统的 CG“灯光”创建场景照明(请参见下面描述的使用情况)。

使用 <i>mia_light_surface</i> 的示例
使用 mia_light_surface 的示例

在以上图像中,实际照明来自细长的矩形区域光,该区域光设定为不引起任何镜面反射高光。荧光灯管的可见“光晕”设定为在反射中可见(因此它将成为更加精确的“高光”),但是对最终聚集光线仍然不可见,所以它不会被错误地选择作为附加光。

mia_light_surface 着色器本身可以提供颜色,也可以从场景的现有灯光(集)中派生出颜色。

着色器仅返回颜色,不执行任何其他着色分析。有关提示是使用插入 mia_materialadditional_color 的着色器。

mia_light_surface 着色器的参数如下所示:

declare shader "mia_light_surface" (
        color		"color"        default 1 1 1,
        scalar      "intensity"    default 1.0,
        scalar      "fg_contrib"   default 0.0,
        scalar      "refl_contrib" default 0.0,
        boolean     "use_lights",
        scalar      "lights_multiplier" default 1.0, 
        vector      "lights_eval_point" default 0.0 0.0 0.0,
        array light "lights"
    )
    version 3
    apply texture
end declare

color 是总体颜色,将其应用到内置灯光或来自光源的灯光。

intensity 是“内置”灯光的强度,即该曲面将如同摄影机一样,获得的强度等于 color 乘以 intensity(假定禁用 use_light,请参见下文)。

fg_contrib 是最终聚集光线可以看见的灯光数,refl_contrib 是反射光线可以看见的灯光数。

如果启用了 use_lights,将轮询灯光数组中列出的灯光,并将这些灯光的强度(与 lights_multiplier 相乘)添加到由 intensity 参数决定的输出中,即,如果 L 是灯光列表中所有灯光的输出,则着色器的最终输出颜色为:

color * (L * lights_multiplier + intensity)

lights_eval_point 为 0,0,0 时,在正在着色的 3D 空间中的点上计算灯光强度(已禁用阴影)对于具有 IES 剖面的灯光,它可能会以不需要的方式变化,因此可以明确指定计算灯光颜色的点。该点位于灯光的坐标空间中。

使用情况

常规照明

在现实世界中,每个灯光发射对象都是可见的,都具有一个区域,且从该区域发射灯光。使用最终聚集时,mental ray 会处理将灯光能量添加到场景中的所有曲面,正如光源一样。但是,为了从中获得最佳质量,需要非常高的最终聚集设置,以及很长的渲染时间。

计算机图形中的光源既可以是点光也可以是区域光,区域光本身在渲染中有可能可见,也有可能不可见。在大多数情况下,使用实际的光源将更有效:

发射 FG,不发射 FG,并使用点光源
发射 FG,不发射 FG,并使用点光源

上图显示在棋盘格平面上使用 mia_light_surface 的 3 个面片。最左侧的面片将其 fg_contrib 设定为 1.0(因此,照明地板),其他两个面片将该参数设定为 0.0。但是最右边的面片将点光源隐藏在其后。

距离很近(或使用非常大的光源,例如整个室外天空)时,最终聚集可以很好地照亮对象并具有高质量。距离很远或使用小光源时,使用显式光源才会更加有效。

如果要通过 fg_contribrefl_contrib 参数使反射光线或最终聚集光线“看到”对象(以及看到的数量),mia_light_surface 需要提供单独的控制。该图像使用稍微有点反射的棋盘格平面进行说明。这些面片后没有使用任何光源:

FG 和反射的可见性
FG 和反射的可见性

最终聚集(照明平面)和反射(地面反射)都可以看到最左侧的面片。中间的面片不照明(fg_contrib 为零),最右侧的面片不反射(refl_contrib 为零)。

高光与反射

在现实世界中,可见的灯光发射对象对于拍摄场景的摄影机以及其他对象中的反射(光泽)都可见。在计算机图形中,摄影机通常看不见光源,在材质着色器的“高光”的帮助下,这些光源的反射也不可见。

mia_material 支持一个协议,该协议指示光源是否应生成高光。这由大多数 OEM 应用程序光源实现,在灯光上查找标志,如“影响镜面反射”或“发射镜面反射”或类似。

具有各种标志的面片后隐藏的光。
具有各种标志的面片后隐藏的光。

上图中每个面片后都隐藏一个灯光。最左侧的面片发射镜面反射灯光和漫反射灯光。中间的面片仅发射镜面反射灯光,最右侧的面片仅发射漫反射灯光。此外,最右侧的面片将其 fg_contrib 设定为零。

正如我们所见,最左侧的面片创建的照明过多,因为我们获得灯光和面片这两者的照明。中间的面片在我们尝试看作“可见灯光”的灯光反射中生成奇怪效果的小“高光”(光源只是一个点光)。

在这种情况下,此效果会分散注意力,因此我们希望禁用它,与我们对右侧灯光采取的操作一样。这是可采用的一种方法;由曲面处理反射而非照明;由灯光处理照明而非反射(即没有传统的“镜面反射高光”)。

另一种方法是,使用区域光时,允许区域光创建镜面反射高光:

区域光镜面反射高光也可运作
区域光镜面反射高光也可运作

此图对另一种方法进行了说明。最左侧的面片再次使用启用了镜面反射的点光源。这不是我们所希望的,因为它看起来很奇怪。其他两个面片使用区域光。中间的面片禁用区域光镜面反射并将其 refl_contrib 设定为 1.0,最右侧的面片启用灯光镜面反射并将其 refl_contrib 设定为 0。

正如我们所见,右侧的两个变量都“工作”,因此只需为区域光选择方法。

但是,首选方法是中间的方法,因为通常都使用几何形式的简单区域光(球体、矩形等),而不是实际的几何形式的复杂对象(如霓虹灯)。在这些情况下,必须使用反射对象的一种方法,且灯光发射镜面反射灯光:

复杂几何体需要真实反射
复杂几何体需要真实反射

两个霓虹灯都使用矩形区域光进行其照明,且都投射漂亮的区域阴影(小球体)。但左侧的霓虹灯的反射为矩形,没有任何意义。为此,必须使用右侧的方法,禁用灯光镜面反射,且曲面的 refl_contrib 为非零值。

复杂的灯光分布

在真实世界照明中,灯泡、反射器和各种遮挡器之间的复杂交互确定飞入场景中的灯光的最终分布。

通常,用户不希望考虑所有这些小细节,而仅渲染台灯,而事实上,此问题以测量数据的形式预先存在(即 IES 或 EULUMDAT 文件)。

mia_light_surface 着色器可从灯光中获取其强度。这样可以节省用户将“可见曲面”的强度和颜色与光源的强度和颜色保持同步的时间。如果启用了 use_lights 且某些灯光传递到 lights 参数中,则自动获取强度。

此操作适用于各向同性的点光源和类似光源,但如果使用测量的灯光数据,用户会遇到问题:

从灯光选择强度/颜色
从灯光选择强度/颜色

以上场景包含三个球体。假定它们是一些台灯的灯泡模型。它们都包含一个灯光,该灯光具有应用光源的 IES 剖面拟合。

最左侧的球体使用 mia_light_surface,并进行手动设置,即禁用 use_light。用户负责确保曲面的强度和颜色“正确”,并手动将其与任何动画强度更改等保持同步。

中间的球体使用 use_lights,但我们从它获得非常奇怪的效果;灯泡的一半为黑色。这是因为我们选择的 IES 剖面沿向下的方向发射灯光。由于光源位于球体的中心,因此,只有球体的下半部分将收集到灯光的任何强度值!

显然这不是我们所希望;IES 剖面是应用到整个照明的复合效果,不应该“绘制”灯泡本身!

解决方法是使用 lights_eval_point,正如最右侧的球体一样。选择灯光前面的一点(在灯光自己的坐标空间中)作为“计算点”。球体上的每个点(不管其位置)都将具有空间内测量所在点的强度。

这使得球体的颜色自动遵循灯光在任何强度和颜色更改后的颜色,在球体的整个曲面上进行统一。该球体将采用比传统“高光”更合理的方式正确进行反射。

总结:mia_light_surface 着色器允许以下操作...

使用 <i>mia_light_surface</i> 的另一个示例
使用 mia_light_surface 的另一个示例


脚注
1
结合使用 mia_material 中的 refl_falloff_dist 也非常有用。
2
www.debevec.org 中的“Galileo tomb”探测器,它包含许多小的明亮区域,在该环境中这些区域很麻烦。
3
这在视觉效果方面尤其正确。