unity3d软阴影和硬阴影的原理_Unity3D中两种默认阴影的实现

unity3d软阴影和硬阴影的原理_Unity3D中两种默认阴影的实现_第1张图片

Unity3D中两种阴影的实现

传统的ShadowMap

ShadowMap说起来十分简单,把摄像机和光源的位置重叠,那么场景中该光源的阴影区域就是那些摄像机看不到的地方,主要应用在前向渲染路径中。

具体实现分以下几个步骤:

  • 如果有平行光开启了阴影,Unity就会为该光源计算它的ShadowMap(只会计算一个平行光),这张ShadowMap其实就是深度图,记录了从该光源的位置出发、能看到的场景中距离它最近的表面位置(深度信息)。
  • Unity中实现了一个额外的Pass来专门更新光源的ShadowMap,这个Pass就是LightMode标签被设置为ShadowCaster的Pass。
  • 然后在正常渲染的Pass中把顶点位置变换到光源空间下,以得到它在光源空间中的三维位置信息。然后根据坐标信息对ShadowMap采样,得到该点在ShadowMap中的深度信息。比较后,判断该点是否应该在阴影中。
  • 注意:利用Receive Shadows的开关可以控制物体是否显示阴影,但是不影响渲染。而Cast Shadows的开关则控制该物体是否会加入到Shadowmap的渲染。

屏幕空间的阴影

延迟渲染中的光照计算绝大部分都是在屏幕空间里进行的,同样也包括阴影。这种屏幕空间的阴影实现主要有这么几个步骤:

延迟渲染中的光照计算绝大部分都是在屏幕空间里进行的,同样也包括阴影。这种屏幕空间的阴影实现主要有这么几个步骤:

  1. 首先得到从当前摄像机处观察到的深度纹理。在延迟渲染里这张深度图本来就有,如果是前向渲染的话就需要把场景整个渲染一遍,把深度渲染到深度图中。
  2. 然后再从光源出发得到从该光源处观察到的深度纹理,也被称为这个光源的ShadowMap
  3. 然后在屏幕空间做一次阴影收集计算(Shadows Collector),这次计算会得到一张屏幕空间阴影纹理,也就是说这张图里面需要有阴影的部分已经显示在图上了。这个过程概括来说就是把每一个像素根据它在摄像机深度纹理中的深度值得到世界空间坐标,再把它的坐标从世界空间转换到光源空间中,和光源的ShadowMap里面的深度值对比,如果大于ShadowMap中的深度距离,那么就说明光源无法照到,在阴影内。
  4. 最后,在正常渲染物体为它计算阴影的时候,只需要按照当前处理的fragment在屏幕空间中的位置对步骤3得到的屏幕空间阴影图采样就可以了。

Unity3D中开启不同阴影的情况

截止到Unity 5.4,当项目工程的目标平台是Mobile的时候,就不会使用屏幕空间的阴影映射技术,即使用原始的Shadows Map方法。在代码里,Unity会定义内置宏UNITY_NO_SCREENSPACE_SHADOWS来控制。而当项目工程的目标平台是支持屏幕空间阴影的话,例如PC, Mac & Linux Standalone平台时,会开启屏幕空间的阴影映射技术。

我们可以通过帧调试器(Frame Debugger)来分辨当前是否使用了屏幕空间的阴影映射技术:

unity3d软阴影和硬阴影的原理_Unity3D中两种默认阴影的实现_第2张图片

unity3d软阴影和硬阴影的原理_Unity3D中两种默认阴影的实现_第3张图片

整理自 《Unity Shader入门精要》

你可能感兴趣的:(unity3d软阴影和硬阴影的原理_Unity3D中两种默认阴影的实现)