UE4弹簧草及扩展

文摘   2024-12-10 18:30   上海  
【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!

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

作者主页:
https://www.zhihu.com/people/wantnon


如果草交互想实现回弹效果,就不能纯靠材质,而要有办法记录历史状态。


找了一圈,发现下面这种在RT上做物理迭代的方案最便捷:【UE5 模拟交互篇】(五)物理场方式实现植被交互

https://zhuanlan.zhihu.com/p/720303883


本文复现此法,并做一些简单扩展。


一、弹簧草


基本思路与参考文章相同,只记录一下差异点及注意事项。


1. 参考文章中算了多层弹簧,我只算了一层。即将草的尖端看作一层水平弹簧振子。另外参考文章中并没有将弹簧振子锁定在水平平面上,我这里是为了简单而且省通道,直接看作水平弹簧振子。


2. 用Offset代替POS


同参考文章一样,用到posRT和volRT两个RT,前者存位置,后者存速度。但我posRT里存的不是Position,而是Offset,就是此纹素代表的弹簧振子偏离平衡位置的Offset,这样数值范围更小,精度更高,而且方便Debug。


3. Offset和Volecity编码。


我是将Offset分解成offsetDir和offsetLen,然后再将offsetDir乘以0.5+0.5,这样,就全都变成了正值,再写入RT的。从RT采出来则需要进行解码再用。由于我简化为水平弹簧振子,所以offsetDir是二维的,再加上offsetLen,占三个通道。Volecity同理。


当然,如果用RT存负值,就用不着编解码了,也无需将Dir和Len分开存。


关于UE中RT如何存负值,搜到下面帖子(我还没试):



4. 在DrawMaterialToRenderTarget材质中通过UV和预设的Box框范围来计算WorldPosition,然后用WorldPosition与传进来的playerPos计算距离,决定哪里下压。


5. 分为stampPos、stampVol、updatePos和updateVol四个过程。

  • stampPos是将最新的压草偏移量覆盖到原RT上。

  • stampVol是将覆盖了最新压草偏移量的地方的Volecity清零,避免压草处速度持续积累失控。


6. deltaTime限制最大值,比如deltaTime=min(0.02,deltaTime),这样可以避免卡的时候因deltaTime过大而使速度增量过大。


7. 在草的Shader里采样posRT,根据采到的Offset计算Bend。

二、扩展1:弹簧草+Billboard


如果想表达海葵之类的管状生物,且不想用管状模型嫌面数太高,可以用Billboard来实现不管从哪个角度看,都保持恒定的宽度。


在草/海葵材质中,WPO计算如下:



三、扩展2:弹簧香菇


回想上面弹簧草的实现思路,是将平面上每个点看成一个弹簧振子,在RT上去迭代。


那么,如果把模型上每个点看成一个弹簧振子,RT上每个像素对应模型表面一点,对RT进行迭代,岂不是就能实现类似软体的效果了。


这里说“类似”,是因为相比于“正确”的软体实现方法——质点弹簧系统而言,它少了质点之间的相互影响,而只是各质点独立的振荡。这是一个非常大的简化,所以效果上一定会打折扣,但从发散思维角度讲,感觉又是一个不错的联想,所以尝试了一下。


主要问题是如何在DrawMaterialToRenderTarget过程中拿到WorldPosition(因为Blit时材质不是应用在模型上,所以无法在材质中直接拿到模型的WorldPosition)。解决办法是将WorldPosition预烘焙到贴图上,然后在DrawMaterialToRendeTarget的材质中采样此贴图。这个思路跟顽皮狗的车辆战损效果类似:


https://youtu.be/aZJQuHZQakQ?t=2153


只不过,战损效果是把铁皮撞凹陷以后就固定住了,而我们要回弹。


另外前面弹簧草是简化为只在xy平面运动的水平弹簧振子,所以存Offset只需三通道(offsetDir.x,offsetDir.y和offsetLen),Volecity同理。但弹簧香菇表面的振子就不能再看成二维的,而需要是三维的,Offset和Volecity都需要用四通道来存(假设不用RT存负值)


如何写入RT的a通道,参考:Draw Material To Render Target impossible to control alpha - always fully transparent

https://forums.unrealengine.com/t/draw-material-to-render-target-impossible-to-control-alpha-always-fully-transparent/136704/3


即Blit材质Blend Mode选Masked,Shading Model选Unlit,则emissiveColor引脚输出RGB,OpacityMask引脚输出Alpha。另外还需要:勾选Used with Editor Compositing,OpacityMaskClipValue设置为-0.01。


其余就和弹簧草实现一样了。


最终效果如下:


文末,再次感谢杨超wantnon的分享,作者主页:https://www.zhihu.com/people/wantnon如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)。



 

5000人测试背后的秘密|GPM 2.0案例精讲


近期精彩回顾

【学堂上新】浅谈骨骼动画技术原理

【万象更新】UWA Gears:Frame Capture事件浏览器之事件筛选

【学堂上新】虚幻引擎寒假班火热招生中!

【学堂上新】如何用AI制作3D模型?


侑虎科技
UWA,专业的游戏和VR应用性能优化平台。www.uwa4d.com
 最新文章