【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)。
近期精彩回顧
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.