2

大世界树木阴影方案集合

 3 years ago
source link: https://blog.uwa4d.com/archives/USparkle_Shadowmap.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

大世界树木阴影方案集合

这是侑虎科技第909篇文章,感谢作者偶尔不帅供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

作者主页:https://zhuanlan.zhihu.com/p/349282312,作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!


Unity引擎对Terrain上的树阴影处理的稍显简易,常常满足不了项目需求。当动态物体采样Light Probe,默认是不给树烘焙Lightmap的。但我们知道这种大型的动态物体即便light probe proxy volume(不支持,改支持也卡) 也仅仅是更丰富间接光和大型遮挡,无法有效地表达自阴影效果。一旦出了实时阴影距离,画面就差了很多。而且手上的《生死狙击2》是一款投入4亿研发的大型项目。我作为负责图形渲染技术的人,自然是需要做大量的技术方案尝试与对比的。

具体需求是50米内用Shadowmap,50-1500米都要有平行光阴影,平行光是静态的。

以下是我尝试过或了解过可以满足这个需求的7种方案。

  1. 烘焙可实例复用的无方向性间接光阴影
  2. 烘焙可实例复用+可旋转的平行光阴影
  3. 低精度预计算静态Shadowmap阴影
  4. 稀疏八叉树体素化静态阴影
  5. 屏幕空间接触实时阴影
  6. 基于低精度高度图实时阴影
  7. 距离场加速Ray Marching阴影

方案1:烘焙可实例复用的无方向性间接光阴影

这是最简单粗暴的一种做法,就是在3DsMax下利用天光烘焙一个类似AO一样的阴影,这样树木在旋转任意角度后和在任何角度的阳光下都兼容,资源复用率最高,但没有考虑到平行光阴影有点不真实和符合要求不高的问题。得到类似这样的烘焙图,作用在树的两套UV上。代码也很简单,只需要在SpeedTreeCommon.cginc内加入UV1传递,最后*到Albedo上,因为仅仅像AO一样作用间接光影响不够大。

1.png

2.png
Max烘焙的AO图绑定树的Prefab复用,Unity烘焙无法复用且带方向

3.png
实时阴影内

4.png
实时阴影外

5.png
本方案效果

优点:简单好用,用4行代码实现,性能很高,一张低分辨率图采样1次。

缺点:没考虑方向光,只能自己改善阴影,不能遮挡树下动态物件(静态可以烘焙Shadowmask)。


方案2:烘焙可实例复用+可旋转的平行光阴影

与上一个方案很像,但加上了方向考虑,烘焙这样的8个平行光烘焙图。

6.png

根据树实例不同的朝向,设置不同的AO图,但由于树在地形上设置起来不方便,可以做成数组或图集。Shader内根据朝向自己取Index或Offset,因为效果和上一个类似,但带了更好的方向性。每个方向都比较正常。如果觉得8个方向不够可以用2个方向插值或做16个朝向的图。

7.png
本方案效果

优点:简单好用,性能很高,一张低分辨率图集采样1次或2次,支持旋转,带有方向性阴影。

缺点:不同角度太阳的地图可能都需要一套独立的贴图, 只能自己改善阴影,不能遮挡树下动态物件(静态可以烘焙Shadowmask)。


方案3:低精度预计算静态Shadowmap阴影

先对比下实时阴影内的效果,树叶自阴影还不错,但第二张,在实时阴影外就惨不忍睹了。

8.png

9.png

用4M静态Shadowmask效果:

10.png

原理:离线对场景拍一张记录深度图的Shadowmap且记录灯光相机的matrix_vp。但因为这种大范围的拍摄,深度精度或许会不足,所以我没用16位的,而是用RGBA32自己压缩了深度,所以看起来是条纹的。

优点:不仅自己有阴影还能遮挡远处的人物等动态对象,实现简单,运行时省Draw Call,不用反复拍摄远景。

缺点:显存大。

继续升级的方案:基于虚拟贴图的静态Shadowmap或Texture streaming的Shadowmap。

之前工程:https://github.com/jackie2009/ScrollingStaticShadowmap


方案4:稀疏八叉树体素化静态阴影

用0.9M体素化阴影的效果:

11.png

原理:每0.5米一个立方体,记录0或1,表示是否在阴影内,作为八叉树节点。然后通过树的压缩节省内存。

要研究压缩的可以看我另一篇全面压缩的4种算法。

《四叉树阴影高级压缩技巧》

12.png

优点:不仅自己有阴影还能遮挡远处的人物等动态对象,运行时省Draw Call,不用反复拍摄远景,相比Shadowmap省显存。

缺点:实现复杂些,预计算写高并发才能够快。Shader需要多次采样才能查询到结果。

原理引用:《Shader内用八叉树实现体素化阴影》

工程文件:https://github.com/jackie2009/ocTreeVoxelizedShadows/

方案5、6、7 :每个Demo开发都比较复杂,后面更新或单独一篇。


文末,再次感谢偶尔不帅的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

也欢迎大家来积极参与U Sparkle开发者计划,简称“US”,代表你和我,代表UWA和开发者在一起!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK