蒙版/阴影对象和摄影机贴图

介绍

通常,需要将合成1 对象包括到填充了现实世界对象的现有摄影背景板中,例如,将尚待施工的建筑添加到空地,在道路上添加一辆虚拟车,或者让一个虚拟角色走过某场景并与现实世界场景中的对象进行逼真的交互。

有两种主要着色器可帮助实现此目的,分别为:mip_cameramap,用于将图像从摄影机“投影”到几何体;mip_matteshadow,注重生成延续蒙版,并允许照相底板中的现实世界对象能够同时投射和接收阴影以及接收反射和间接光。

mip_cameramap

此着色器用于根据曲面点屏幕像素坐标查找颜色纹理。此着色器在功能上类似于 库中的 mib_lookup_backgroundbase,但有以下重要区别:

declare shader "mip_cameramap" (
        color texture "map",
        scalar  "multiplier"               default 1.0,
        scalar  "degamma"                  default 1.0,
        boolean "per_pixel_match"          default off,
        boolean "transparent_alpha"        default off,
        boolean "offscreen_is_environment" default on,
        color   "offscreen_color"
    )
    version 4
    apply material, texture, environment
end declare

map 参数是要查找的颜色纹理,而 multiplier 是该贴图的倍增。

如有必要,着色器可以通过 degamma 参数将反向 Gamma 校正应用于纹理。如果 Gamma 由链中的其他着色器处理,或者使用全局 mental ray Gamma,请使用值 1.0,它表示“保持不变”。

禁用 per_pixel_match 时,仅拉伸纹理以完全填充场景。启用 per_pixel_match 时,贴图左下角的像素会与左下角渲染像素完全匹配。如果贴图的像素大小和渲染的像素大小不同,将显示一条警告,但仍然会渲染图像(尽管将根据需要裁剪或填充图像)。

有时,需要将着色器作为背景来应用,但仍从 Alpha 通道提取信息。如果启用了 transparent_alpha,则 Alpha 值始终为零。如果禁用了它,则使用来自纹理的 Alpha 值。

着色器执行着色点到光栅空间的实际“反向变换”。这种情况必然会导致将眼光线定位在屏幕上,但对反射和折射等不会如此。这些光线可能射中屏幕外的对象上的点。如果启用了 offscreen_is_environment,则这些光线将返回环境。如果禁用了它,则返回 offscreen_color。在任一情况下,此颜色都倍增Gamma 的影响。

mip_matteshadow

此着色器用于创建“蒙版对象”(即用于在现有照相底板中表示现有现实世界对象的对象),以便...

在上述所有情况下,mip_matteshadow 应用于表示现实世界对象的对象,而合成对象使用传统材质。

该着色器还可以用作“仅阴影”着色器,即仅显示传入光投射到点上所产生的阴影所占的比例,但忽略传入光本身的实际量(仅遮挡百分比)。

declare shader
        struct {
            color "result",
            color "shadows_raw",
            color "ao_raw",
            color "refl_raw",
            color "indirect_raw",
            color "illumination_raw"
        } "mip_matteshadow" (
        color   "background"        default 0 0 0 0,
        # Shadows
        boolean "catch_shadows"     default on,
        color   "shadows"           default 0 0 0 1,
        color   "ambient"           default 0.2 0.2 0.2,
        boolean "no_self_shadow"    default on,
        boolean "use_dot_nl"        default on,
        scalar  "colored_shadows"   default 1.0,
        # AO
        boolean "ao_on"             default on,
        color   "ao_dark"           default 0.0 0.0 0.0,
        integer "ao_samples"        default 16,
        scalar  "ao_distance"       default 0.0,
        # Reflections
        boolean "catch_reflections" default off,
        color   "refl_color"        default 0.2 0.2 0.2 0.2,
        color   "refl_subtractive"  default 0.2 0.2 0.2 0.2,
        integer "refl_samples"      default 0,
        scalar  "refl_glossiness"   default 10.0,
        scalar  "refl_max_dist"     default 0.0,
        scalar  "refl_falloff"      default 2.0,
        # Indirect
        boolean "catch_indirect"    default off,
        color   "indirect",
        # System
        boolean "multiple_outputs"  default off,
        # Additional illumination
        boolean "catch_illuminators" default off,
        array light "illuminators",
        # Extra input
        color   "additional_color"  default 0 0 0,
        # Light linking
        integer     "mode",
        array light "lights"    
    )
    version 6
    apply material, texture
end declare

注意:此部分将仅简短列出参数,而 matteuseagetips 页面上的“用法提示”部分详细解释了不同的用例。

该着色器有多个输出(它将返回一个结构)。但是,默认情况下(由于兼容性原因),它仅填充结构的第一项,即复合“结果”。仅当参数 multiple_outputs 处于启用状态时,才将单独的结果写入其他输出。

Background 参数是背景色。如果 catch_... 选项都处于禁用状态,则仅返回此结果(包括其 Alpha),并且着色器不执行任何操作。否则此参数是指执行所有其他操作所依据的基础颜色。当使用外部合成时,此颜色通常是透明黑色 (0 0 0 0),否则将使用借助 mip_cameramap 着色器映射的现实世界背景图版。

catch_shadows 选项允许其他对象在此对象上投射阴影。

shadows 参数是阴影的颜色。检测到阴影时,背景阴影之间的混合取决于点中阴影所占的比例。

ambient 参数设置“基础光级别”。它将提升最低的“阴影中”级别。例如,如果此级别为 0.2 0.2 0.2,则生成的最暗阴影混合将包含 20% 的背景和 80% 的阴影(除非启用了环境光遮挡)。

启用 no_self_shadow 选项(还将着色器实例用作阴影着色器)会导致使用 mip_matteshadow 的所有对象不接收其他任何此类对象上的阴影。

use_dot_nl 选项定义是否在计算传入的量时考虑光的角度。

如果 color_shadows 为 0.0,则所有阴影都投射为灰度。如果它为 1.0,则阴影为纯色。例如,如果曲面由一个红色灯光和一个绿色灯光照亮,则红色灯光将有绿色阴影,而绿色灯光将有红色阴影。

如果启用了 ao_on,则内置的环境光遮挡(以下简称“AO”)将基于 ambient 参数中的颜色进行应用。AO 会考虑 no_self_shadow 开关,因此不会导致对象的 AO 具有与自身相同的材质实例。

ao_dark 参数决定 AO 将导致的阴影的暗度。通常,使用默认黑色就足够了,但是较浅的颜色会导致着色效果不太明显。

ao_samples 是投射的 AO 光线数。可以使用 ao_distance 参数限制 AO 光线到达的范围。如果该参数为零,则表示光线可以达到无穷远。短光线可显著提高性能,但这会将 AO 效果局部化。

catch_reflections 启用反射。

refl_color 是反射的倍增。请注意,此颜色的 Alpha 值对反射是否将按此数值影响 Alpha 非常重要。在某些情况下,反射可能需要相减,即需要使用 refl_subtractive - 请参见 matteuseagetips 页面以获取详细信息。

refl_samples 参数设置光泽反射采样数。如果它为零,则使用镜像反射。否则,refl_glossiness 设置反射的区域光泽度。

反射可通过大多数 refl_max_dist 看见,而衰减的形状可通过 refl_falloff 显示,这与 base 库的着色器 mib_glossy_reflection 非常相似。

如果启用了选项 catch_indirect,则间接光由 indirect 颜色聚集和缩放,通常将该颜色与 background 颜色设置为相同颜色,从而将背景色视为间接光的反射比值。

multiple_outputs 可使着色器在返回的结构中输出多个值。

如果打开了 catch_illuminators 开关,将测试列为 illuminators 的灯光,并允许它们实际照亮场景。这是一个简单的朗伯 (Lambertian) 照明,将 Background 参数视为漫反射颜色2

additional_color 是仅添加到结果的颜色输入,便于着色器绘图使用。它可用于任何事务3

最后,就像在许多其他着色器中一样,mode 设置灯光的包含/排除模式,而 lights 是用于投射阴影的灯光列表。

该着色器还具有多个输出。出于兼容性考虑,如果禁用了 multiple_outputs 参数,则着色器实际上不会将任何值写入主输出以外的任何位置。但是,如果启用了此参数,该着色器将输出以下值:

尽可能让所有输出均为“原始”输出,以便在最大程度上用作后期制作(例如,反射尚未与反射颜色相乘,等等)中的层。

mip_matteshadow_mtl

这是嵌入 mip_matteshadow材质现象,它将用作材质的曲面、阴影和光子着色器。除了标量不透明度以外,它所具有的其他参数与 mip_matteshadow 本身相同。

不透明度不应用于阴影或光子,仅应用于可见的曲面着色本身。通过使用不透明度,用户可将绘制的遮罩用于不规则的边。例如,使用简单的锥形圆柱体可大致匹配前臂,而使用摄像机投影的遮罩(需要借助 mip_cameramap 来应用)可绘制手臂的实际轮廓。这还允许借助遮罩来匹配背景图版中可能存在的运动模糊。

用法提示

此部分中的着色器侧重于将现实世界照相底板与合成对象组合。为了便于描述我们的示例,我们以下面的厨房餐桌照片为基础,此餐桌上放置有一个旧的拉盖式塑料盐罐、一个调味罐、一张纸以及其他物品:

这是我们的背景照片。此图尚未渲染...。
这是我们的背景照片。此图尚未渲染...。

摄影机映射说明

mip_cameramapbase 库中的 mib_lookup_background 有何区别?

主要区别在于,前者只使用当前光栅位置(即当前渲染的像素的 X 坐标和 Y 坐标),而后者实际上计算着色点的图像空间位置。

为什么这很重要?举例说明。请参见以下有关背景照片顶部的反射球体(使用两个不同着色器映射到一个平面)的示例:

mib_lookup_background
mib_lookup_background
mip_cameramap
mip_cameramap

请注意,使用 mib_lookup_background 的左侧图像看起来不正确。它看起来是透明的球体而非反射球体。导致此现象的原因是什么?

假设我们要渲染位于该球体上的像素坐标 (200,200)。投射眼光线并射中该球体。此射中点实际上位于像素坐标 (200,200) 处。但是该光线作为反射光线继续前进,射中了地平面。

地平面上的这个新点与正在渲染的像素不同,它位于模型中的其他位置。但 mib_lookup_background 仅注重当前像素 (200,200) 并从贴图返回在该点的颜色。

相反,mip_cameramap 实际上会将此新点转换为一组新的光栅坐标(例如 (129,145)),并查找位于新位置上的贴图,以便在反射中创建正确的外观。

但存在一个意外的问题;如果反射的点位于屏幕外面,将发生什么情况?如果计算的光栅坐标为 (-45,39),将发生什么情况?结果是 mip_cameramap 返回指定的颜色或返回该光线方向的环境颜色(如果启用了 offscreen_is_environment)。

蒙版对象和捕捉阴影

在此部分中,我们将使用 mip_matteshadow 为现实世界几何体创建替代对象(也称为“蒙版对象”)。对于示例,我们仅考虑图像左侧的旧塑料盐罐以及厨房餐桌本身。已构建以下简单的 3D 模型:

简单的背景 3D 模型
简单的背景 3D 模型

如果使用 mip_matteshadow,例如仅尝试将背景映射到标准的朗伯 (Lambertian) 曲面,将得到以下结果:

将背景映射到朗伯 (Lambertian) 着色器
将背景映射到朗伯 (Lambertian) 着色器

这种结果显然不够理想,因为朗伯 (lambertian) 着色应用于现实世界图像中已存在的着色顶部。而我们需要做的是将阴影着色分离

这可以通过使用 mip_matteshadow 来完成。通过在白色背景和黑色阴影中应用着色器,可以显示结果:

原始阴影信息
原始阴影信息

此图像包含原始阴影信息,否则将为白色。此操作模式对外部合成用法非常有用,在此模式下,通过使合成对象对摄影机(本示例中的圆环)不可见,然后在白色背景和黑色阴影中使用 mip_shadowmatte,可生成完全独立的x阴影过程。

注意:此用法支持彩色阴影!存在红色和绿色灯光时,绿色灯光将显示红色阴影,反之亦然。

上述图像存在一个问题:它包含盐罐的阴影。但现实世界图片中已经包含盐罐的阴影。通过以下步骤可解决此问题:

mip_matteshadow 材质不会遮挡自身
mip_matteshadow 材质不会遮挡自身

当着色器用作材质阴影着色器且 no_self_shadow 处于启用状态时,使用 mip_matteshadow 的任何对象都不会遮挡另一个使用 mip_matteshadow 的对象,但此对象仍然会将阴影投射到其他对象上,而其他对象也将在此对象上投射阴影。

请注意,尽管阴影很暗,但投射盐罐的圆环阴影具有明显左边缘。要解决此问题,可以将 ambient 颜色设置为较小的值并启用 use_dot_nl,这将在阴影垂直于灯光时使阴影逐渐“淡出”,从而避免出现明显的边缘:

较浅的阴影和启用 use_dot_nl
较浅的阴影和启用 use_dot_nl

此时,我们可以使用 mip_cameramap 将白色部分替换为实际背景:

使用背景替换白色部分
使用背景替换白色部分

高级阴影捕捉

可以使用 mip_matteshadow 通过多种方法处理阴影。我们在上面已经介绍了使用白色 background 和黑色 shadows 设置创建阴影过程的方法。

还介绍了将图片用于 background 和将黑色用于 shadows 的方法。

但是,还有其他两个选项:

一个选项是,将已照亮场景的图片用于 background,而将阴影场景的另一张图片用于 shadow 参数。

场景被完全照亮
场景被完全照亮
阴影中的场景
阴影中的场景

此技术尤其有用,因为它可以完美地解决任何自阴影问题,甚至建议在此模式下禁用 no_self_shadow。以下为结果图:

阴影来自未照亮的照片版本
阴影来自未照亮的照片版本

在不必进行任何优化的情况下,这可以提供精美详图并自动提供“正确”颜色和阴影强度。

最后一种方法是在外部合成中完全处理阴影。这可以通过将 background 设置为 0 0 0 0(即透明黑色,Alpha 值为零)并将 shadow 设置为 0 0 0 1(即不透明黑色,Alpha 值为一)来完成。

这将创建一个渲染,如下所示:

颜色通道
颜色通道
Alpha 通道
Alpha 通道

此图像可在背景的顶端外部合成,因为阴影信息存在于 Alpha 通道中。

反射

由于使用的是背景的 mip_cameramap 反射和折射,所以对象能够正常显示:

反射和折射
反射和折射

请注意,即使使用的是盐罐的反射,此反射也是正确的。

请注意,这也意味着,最终聚集将正确拾取背景并作为间接照明:

最终聚集照亮对象
最终聚集照亮对象

该着色器还显示其他对象的(光泽)反射:

光泽纸反射对象
光泽纸反射对象

请注意反射如何仅涉及添加的实际合成对象,着色器已假设现实世界照片包含其他现实世界对象的反射,即 mip_matteshadow 对象永远不会反射另一个对象,也不会反射环境。

但仍然忽略了一个小小的细节。请注意,圆柱体仅反射了纸,未反射任何其他对象。这是因为 mip_matteshadow 不知道如何处理射中地平面上“屏幕外的”某个位置的光线。

无反射
无反射

通过使用 mip_cameramapoffscreen_is_environment 参数,然后利用环境贴图(例如 mip_mirrorball)提供环境贴图可解决此问题:

效果更好
效果更好

该着色器还可以接收间接光,例如最终聚集和光子(如果还用作光子着色器)。为说明此功能,我们启用了 catch_indirect,然后将白色对象设置为发光红色,并确保玻璃球体生成焦散效果:

接收间接光
接收间接光

如上所述,着色器可确保不存在任何间接光从一个隐藏对象反弹到另一个蒙版对象,并且不接收来自环境的任何间接光(因为假设这两种效果都存在于原始的现实世界照片中)。

反射的最终特殊情况是背景照片已经包含大量反射。以下是一个新的背景照片,物品位于反射效果极好的曲面上:

盐罐位于反射效果很好的曲面上的照片
盐罐位于反射效果很好的曲面上的照片

如果将合成对象添加到此场景中并使用与光泽纸相同的设置,将得到以下相当怪异的结果:

相加反射 - 看起来不正确
相加反射 - 看起来不正确

但这看起来存在很大问题!您可以通过添加的反射查看背景的反射,而添加的反射看起来更亮。

要解决此问题,请使用 refl_subtract 设置由反射引起的背景衰减量。当然,这可能是一个用以匹配图像中反射区域的绘制贴图,例如房屋前面的水坑等。

相减反射 - 效果会更好!
相减反射 - 效果会更好!

以上为正确的结果图。合成反射会覆盖现有反射并替代它们!另请注意,即使对象位于现实世界对象的后面,该对象的反射在现实世界反射中也能够正常显示(盐罐后面的白色球即使在反射中也是位于盐罐后面)。

最后,所有对象都基于背景图版本身拾取间接照明。在渲染中只存在一个矩形区域光源。

反射和 Alpha

当准备外部合成并对 background 使用透明黑色,对 shadows 使用不透明黑色时,反射也获取一个 Alpha 通道非常重要。

refl_color 参数的 Alpha 分量定义了 Alpha 通道中存在的反射量。

同样,indirect 参数的 Alpha 分量定义了可以在 Alpha 通道中看见多少间接光。

如果将背景的 Alpha 值设置为 1.0(例如使用背景图片时),则以上两个分量均没有任何功能。

两个世界同时获取最佳效果的模式

如果需要合成对象来反映实际对象但仍需要灵活执行外部合成阴影(例如,不希望在已经进行渲染时在背景中添加对象),可以创建一种混合方法。

这可以借助 mip_rayswitch 着色器来完成。使用该着色器可在对眼光线使用透明黑色 (0 0 0 0) 背景与对其他光线(例如,反射、折射和最终聚集)使用摄影机映射照片之间进行切换。

总结和工作流程提示

以下是将合成对象渲染到背景图版中的简单分步工作流程。假定具有

必备材料
必备材料

然后按如下所述执行操作:

着色树
着色树

添加包含物理上看似合理的着色器的任何 CG 对象(例如建筑库中的 mia_material)。渲染。微笑。

渲染。微笑。
渲染。微笑。


脚注
1
使用术语“合成”时,指的是要插入到场景中的其他对象,而“现实世界”指的是已经存在的对象。
2
lightsilluminators 之间的差异在于,lights 仅用于在背景上产生阴影,而 illuminators 用于在背景上投射实际灯光。这意味着,lights 阵列中应包含背景图版中已存在的灯光,而 illuminators 阵列包含 CG 元素引入的任何其他灯光,例如 CG 汽车前灯。
3
例如,通过插入 mib_illum_phong(其漫反射颜色设置为黑色)将镜面反射高光添加到照明装置中。
4
如果使低动态范围镜像球照片略微曝光不足,通常可以不使用此照片。