小草弯弯开源库评测
- 作者:admin
- /
- 时间:2019年01月21日
- /
- 浏览:7550 次
- /
- 分类:博物纳新
导读
GrassBending是一个实现了草地交互弯曲效果的开源项目。该项目中,提供了一个用于替换低矮植被(hua hua cao cao)的Shader,和用于传递数据的相关脚本。本文将简单介绍该项目的使用、实现,并展示在不同机型上的性能数据。
项目信息
Unity版本:2018.3+
https://lab.uwa4d.com/lab/5c29315472745c25a802d1a7
效果展示
使用方法
此项目中,提供了一个SampleScene,展示了如何使用这些脚本和Shader实现草地交互效果,即上文中效果展示的场景。在示例场景中,植被使用Unity Terrian制作,并且已经包含了6种不同的Details预设,并且它们的Billboard选项都是开启的。在示例场景中,作者提供的Shader为 "Hidden/TerrainEngine/Details/BillboardWavingDoublePass" ,可以直接应用到Billboard类型的Terrian Details上的。
对于角色或其他希望与草地相互作用的物体,您需要在其上挂载一个BendGrassWhenEnabled或BendGrassWhenVisible组件,用来标记交互关系。显然,这些脚本会在其所在上GameObject状态发生改变时,启用对应的检查,并将数据传递到草地的Shader中。
以BendGrassWhenEnabled为例,其上有两个参数。BendRadius用于控制物体影响草的球体范围大小。Priority则用来控制弯曲源的优先级,以防有超过上限的角色(或物体)同时影响到草地的弯曲,数字越小优先级越高。下图为调节Bend Radius造成的效果区别:
实现原理
本项目中,使用的是在Shader中改变顶点位置从而达到弯曲效果的方法。这种方法也是一个比较常见于手游项目的方法。
在添加了BendGrassWhenEnabled或BendGrassWhenVisible组件后,这些物体会在OnEnable/OnBecameVisible时会被添加为一个bender,再将所有benders的Position、BendRadius数据作为bendData传递给Shader。
1Shader.SetGlobalVectorArray(Shader.PropertyToID("_BendData"), bendData);
Shader拿到这些数据后,计算出顶点与bender的距离,并与BenderRadius进行比较,计算出顶点受的弯曲力大小bendPower和弯曲方向bendDir,并根据顶点色的alpha值,进行顶点位置的偏移,相关代码如下:
1float bendRadius = _BendData[i].w;
2//角色位置
3float3 benderWorldPos = _BendData[i].xyz;
4//顶点位置
5float3 vertexWorldPos = mul(unity_ObjectToWorld, v.vertex);
6
7//角色和顶点距离
8float distToBender = distance(float3(vertexWorldPos.x, 0, vertexWorldPos.z), float3(benderWorldPos.x, 0, benderWorldPos.z));
9//顶点受到的弯曲力
10float bendPower = (bendRadius - min(bendRadius, distToBender)) / (bendRadius + 0.001);
11//弯曲方向
12float3 bendDir = normalize(vertexWorldPos - benderWorldPos);
13//顶点偏移量
14float2 vertexOffset = bendDir.xz * bendPower * v.texcoord.y * v.tangent.y;
15//根据顶点色的alpha值计算该顶点是否需要进行偏移
16v.vertex.xz += lerp(float2(0, 0), vertexOffset, saturate(bendRadius * v.color.w));
通过Wireframe视图可以更明显地看出这一步实现的效果,注意看角色走过时网格发生的变化:
在草地的绘制上,Shader通过两个Pass分别绘制了不透明和半透明边缘(Alpha Blend)的部分。也因此,在渲染的性能效率上会比较低,在使用时可以根据项目的实际情况进行调整。
性能测试
从上述的介绍可知,在这个项目中,使用Shader中偏移顶点的方式,可以将主要计算工作放在了GPU端,减轻CPU端的性能压力。
对此,我们在【红米4X】、【Vivo Y85】、【小米8】这三款不同档次的机型上进行了性能测试,测试版本开启了多线程渲染。最终得到了如下数据:
以红米4X为例,具体查看一下其中逻辑代码的耗时情况。从这里看到逻辑代码的耗时主要集中在Gfx.WaitForPresent和Camera.Render两个函数上,由此再具体查看两个函数的耗时曲线。
(红米4X的逻辑代码耗时Top10函数列表,此处统计数据包含了所有线程的耗时情况)
(Gfx.WaitForPresent&Camera.Render函数耗时曲线)
在耗时曲线中,波动比较明显。耗时波动受视野内渲染的草量影响,如上图所示,渲染草量多时(红框区域),耗时也会有明显上涨的峰值波段,渲染草量少时(绿框区域),耗时明显偏低。
综合以上数据,可以看到Gfx.WaitForPresent有超过30ms的耗时。
首先我们来复习一下这个函数的意义:【扒一扒Profiler中的占坑鬼】,由此推测这里主要的性能瓶颈在GPU端,结合上文的分析,认为和Overdraw的关系比较大。对应Camera.Render的高值推测也是受GPU端压力造成的等待同步时间。
总结
使用Shader中偏移顶点的方式来实现草的交互效果也是一种常见可借鉴的思路。在移动端中更常见的是使用Mesh而非Terrian实现草地,并结合分块LOD处理分级效果。对于需要在移动端上实现上述效果的项目,建议参考此项目的实现思路,进行改进和优化后使用。
快用UWA Lab合辑Mark好项目!
今天的推荐就到这儿啦,或者它可直接使用,或者它需要您的润色,或者它启发了您的思路......
请不要吝啬您的点赞和转发,让我们知道我们在做对的事。当然如果您可以留言给出宝贵的意见,我们会越做越好。
【博物纳新】是UWA旨在为开发者推荐新颖、易用、有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目、前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性。很多时候,我们并不知道自己想要什么,直到某一天我们遇到了它。
更多精彩内容请关注:lab.uwa4d.com