实时阴影具有相当高的渲染开销;任何可能投射阴影的游戏对象都必须首先渲染到阴影贴图中,然后该贴图将用于渲染可能接受阴影的对象。
柔和阴影比生硬阴影具有更大的渲染开销,但这仅影响 GPU,不会导致额外的 CPU 工作。
直接获得光照的表面有时看起来部分处于阴影中。之所以出现这种情况,是因为应该精确位于阴影贴图中指定距离处的像素有时被计算为更远距离(这是对阴影贴图使用阴影过滤或低分辨率图像的结果)。造成的结果是阴影中出现任意像素图案(这些像素其实应当获得光照),带来称为“阴影暗斑”(shadow acne) 的视觉效果。
为了防止阴影暗斑,可在阴影贴图中的距离上添加 Bias 值,从而确保边线上的像素确实符合比较预期,或者确保在渲染到阴影贴图时游戏对象可以沿着自身法线插入一点点。启用阴影后,这些值由 Light Inspector 窗口中的 Bias 和 Normal Bias 属性设定。
不要将 Bias 值设置得太高,因为游戏对象附近的阴影周围区域有时会被错误地照亮。这会导致阴影脱离游戏对象,使游戏对象看起来好像飘在地面上方。
同样,将 Normal Bias 值设置得太高会使阴影对于游戏对象来说太窄:
在某些情况下,__Normal Bias__ 会导致称为“光渗”(light bleeding) 的不良效果,这种情况下,光线从附近的几何体渗透到应该产生阴影的区域。一种可能的解决方案是打开游戏对象的网格渲染器,并将 Cast Shadows 属性更改为 Two Sided。这种做法有时会有所帮助,但可能会占用更多资源,并在渲染场景时增加性能开销。
光源的 Bias 值可能需要适当调整以免产生不想要的效果。通常用眼睛衡量正确值会更简单,而不是试图计算该值。
为了进一步防止阴影暗斑,我们采用一种称为__阴影平坠__的技术。该技术旨在减少沿光照方向渲染阴影贴图时使用的光照空间范围。这可以提高阴影贴图的精度,减少阴影暗斑。
在上图中:
将这些阴影投射物钳制在优化空间的近裁剪面(在顶点着色器中)。请注意,虽然这通常很有效,但对于穿过近裁剪面的大型三角形,这会带来瑕疵:
在此情况下,只有蓝色三角形的一个顶点位于近裁剪面背后并被钳制到此处。但是,这会改变三角形的形状,并可能产生不正确的阴影。
您可以从 Quality 窗口中调整 Shadow Near Plane Offset 属性以避免发生此问题。这将拉回近裁剪面。但是,如果将此值设置得非常高,最终会引入阴影暗斑,因为它会提高阴影贴图需要在光照方向上覆盖的范围。或者,您也可以细分有问题的阴影投射三角形。
如果您发现一个或多个对象未投射阴影,则应检查以下几点:
可在 Quality 窗口中彻底禁用实时阴影。确保启用了正确的质量级别并为该设置启用了阴影。
场景中的所有网格渲染器都必须正确设置相应的 Receive Shadows 和 Cast Shadows。默认情况下两者都已启用,但请检查确保未意外禁用它们。
只有不透明对象才投射和接受阴影,因此使用内置透明着色器或粒子着色器的对象既不会投射也不会接受阴影。通常,您可以使用透明镂空着色器代替具有“间隙”的对象,例如栅栏、植被等。自定义着色器必须采用像素光照并使用几何渲染队列。
使用__顶点光照 (VertexLit)__ 着色器的对象不能接受阴影,但可投射阴影。
如果游戏对象的材质具有“无光照”类型的着色器,Unity 无法为这些游戏对象计算阴影。只有材质的着色器支持光照时,Unity 才能为材质计算阴影。
在内置渲染管线中,使用前向渲染路径时,有些着色器只允许最亮的方向光投射阴影(这种情况尤其发生在 Unity 4.x 版本的旧版内置着色器中)。如果想使用多个阴影投射光,则应改用延迟着色 (Deferred Shading) 渲染路径。您可以使用 fullforwardshadows
表面着色器指令启用您自己的着色器以支持“全阴影”。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.