版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。
在前节中,我们使用Unity内置的Shadow生成算法生成了阴影,在使用Soft Shadow时,如果想得到更加柔和的阴影,就需要调高Quality Level、Shadow Resolution、Shadow Cascades设置值,但调高这些参数会对性能产生比较明显的影响。本节我们使用一个免费的Unity插件Dynamic Shadow Projector来实现更柔和的阴影,经测试,在不大幅提高性能消耗的情况下可以获得比内置阴影更好的阴影效果。
Dynamic Shadow Projector插件读者可以在Asset Store上下载导入,Dynamic Shadow Projector使用投影的方式产生阴影而不是使用shadowmap,可以作为移动平台阴影生成的一个很好的替代品,而且几乎可以在所有设备上运行。
(一)ProjectorShadow
使用上节工程,因为我们使用Dynamic Shadow Projector,所以我们首先需要关闭Unity自带的阴影生成。在Hierarchy窗口中选中Directional Light,修改其属性Shadow Type为No Shadows,禁止其生成阴影。
接下来,我们需要制作一个带有Shadow Projector的虚拟对象prefab。
1、在Hierarchy窗口中新建一个空对象,命名为Softspider。
2、将前一节制作的ARPlane及虚拟对象Spider拖到场景Softspider对象下,并调整好位置关系,通常为了防止生成的阴影与检测到的平面交叠出现闪烁的问题,需将ARPlane在Y轴上的位置稍微向上提一点。
3、在Softspider对象下新建一个空对象,命名为softshadow,在其Inspector窗口中,点击 “Add Component” 按钮,依次选择 “Scripts” > “DynamicShadowProjector” > “Draw Target Object”,或者直接在输入框中输入“Draw Target Object”,为其添加“Draw Target Object”组件,默认会自动添加所依赖的其他组件,如下图所示。
Softspider对象形成的结构如下图所示。
4、进行相应设置。将Projector组件下的Material设置为Dynamic Shadow Projector自带的SoftShadowProjetor,并将Softspider对象下的SPIDER对象赋给Draw Target Object组件下的Target属性。这两个参数设置最为重要,一个负责使用特定的Shader渲染阴影,一个为需要渲染阴影的对象。
根据需要调整Projector组件下的其他参数,并在Scene窗口中调整Projector的位置及旋转方向,直至在Scene窗口右下角的Shadow Texture小窗口中看见虚拟对象的阴影,如下图所示。
为防止阴影投射到虚拟物体本身上,我们需要将虚拟物体排除在阴影渲染对象外,具体的做法是在Hierarchy窗口中选中Softspider下的SPIDER对象,在Inspector为其新建一个layer,命名为Spider,如下图所示。设置softshadow对象中Projector组件下的Ignore Layers为Spider。
在Shadow Texture Renderer组件中我们可以设置阴影的颜色、阴影纹理大小,阴影纹理大小直接影响阴影的质量,越大的阴影越清晰但内存占用会越高。Multi Sampling与Super Sampling主要是用来抗锯齿,在移动设备中,建议只设置Multi Sampling,值越大效果越好但性能开销也越大。Blur Level与其子属性Blur Size设置阴影边缘柔和程度,值越高阴影越柔和,需要注意的是这个参数对性能影响很大,并且在iOS端可能会导致问题,建议慎重设置。其他相关设置请读者参考文献1。
设置好之后,将Softspider制作成Prefab并从Hierarchy窗口中删除之,并将Softspider Prefab赋给Hierarchy窗口中AR Session Origin对象上Appcontroller脚本的Spawn prefab属性。因为我们已经将接受阴影的平面放置到Prefab中,所以在AppController.cs脚本中无需再实例化一个ARPlane,可以注掉以下代码。
spawnedObject = Instantiate(spawnPrefab, hitPose.position, hitPose.rotation);
// spawnedObject.transform.Rotate(Vector3.up, mARCoreAngle);
// var p = Instantiate(ARPlane, hitPose.position, hitPose.rotation);
// p.transform.Translate(0, 0.000012f, 0);
// p.transform.parent = spawnedObject.transform;
运行后效果如下,可以看出,Projector 阴影比Soft 阴影更加柔和,性能消耗与使用Close Fit的Soft Shadow基本相当或略有增加。
(二)BlobShadow
在实际应用中,有时我们可能还会使用斑点阴影(Blob Shadow,或者叫模糊阴影),这种阴影是一种超柔和的阴影,往往用于模拟真实场景中只有环境光而没有明确光源的超柔和阴影效果,如下图所示。
使用Dynamic Shadow Projector也可以制作这种动态的斑点阴影,基本步骤与上节基本一致,只是需要将渲染阴影的材质替换为BlobShadowProjector即可,实际运行效果如下图所示。
)
在我们的测试中,斑点阴影生成与上节中的投影阴影生成性能消耗相差不大,但Dynamic Shadow Projector官方文档不建议在移动端使用Blob Shadow,因此在开发中还需要根据实际情况进行评估。
(三)参数详解
Dynamic Shadow Projector作为Unity自带阴影的一个替代品,可以实现更柔和和模糊的阴影效果,用户可控度高,可以控制在哪些区域、哪些物体上产生或更新阴影,也可以通过大量的参数对阴影的质量进行精细的控制,还可以实现超柔和的斑点阴影,在实际项目中可以灵活应用。为方便读者参考,现将其阴影渲染组件Shadow Texture Renderer中影响阴影生成的最重要的参数列表如下。
参数属性 | 描述 |
---|---|
Shadow Color | 阴影颜色。在Projector使用Shader调整阴影颜色和强度时,设置为黑色有利于提高性能。 |
Texture Width | render texture宽度。 |
Texture Height | render texture高度。 |
Multi Sampling | 使用multisampling level抗锯齿,该参数设置需要硬件支持。 |
Super Sampling | 使用supersampling level抗锯齿,因为Supersampling使用更大的内部render texture纹理,因此,建议在移动平台使用multisampling 。 |
Blur Level | 模糊程度,0为硬阴影,1、2、3为软阴影,值越高阴影越模糊,但性能开销越大,在使用软阴影时,建议使用更小的纹理尺寸。 |
Blur Size | 模糊过滤器尺寸,只有Blur Level选择软阴影才有效。 |
Mip Level | 设置mipMap,如果不使用mipMap时设置为0。 |
Single Pass Mipmap Blur | 使用单个Shader pass做mipMap模糊,这比通常的模糊方法更快。 |
Mipmap Blur Size | 模糊过滤器尺寸。 |
Don’t update while out of view | 勾选时,当阴影Projector在视锥平截头体之外时阴影将不再更新。 |
Blur Filter | 模糊过滤器类型,Uniform适合软阴影,Gaussian适合斑点阴影。 |
Mipmap Falloff | mipMap衰竭类型,通常选择linear,也可以自行设置。 |
Near Clip Plane | 摄像机渲染 render texture时的近平面,与Projector中的近平面不一样,默认为0.01。 |
Blur Shader | 模糊Shader,使用默认值即可。 |
Downsample Shader | 降采样Shader,使用默认值即可。 |
Copy Mipmap Shader | 复制Shader,使用默认值即可。 |
Preferred Texture Formats | 用于设置render texture格式,默认为ARGB32,通常情况下我们不需要修改该值,为了适应特定移动平台GPU,也可以设置多种纹理格式。 |
参考文献
1、Dynamic Shadow Projector Dynamic Shadow Projector