1. 程式人生 > >虛幻4 在Material中如何實現 車子壓倒草的功能

虛幻4 在Material中如何實現 車子壓倒草的功能

比較 shader cnblogs 浮點 性能 nan 向量 eve 要求

上次發了篇介紹車子壓倒草的博文

http://www.cnblogs.com/JinT-Hwang/p/8169146.html

中的2.部分。

不過存在一個問題,就是如果草很多,會有很多個碰撞體,雖然物理效果比較真實但是可能會導致性能問題。

這次介紹一下在草的材質中編碼,實現車子壓倒草的功能。

material中會用到一些數學的知識,還需要各位有一定的概念才能很好的理解。

關鍵詞:unreal4、虛幻4、汽車、草、壓倒、伏地、Material、材質編輯器、Shader

實現思路:通過求出草離車子的水平和垂直距離(如果只判斷車子離草的距離,結果周圍的草會成一個圓形倒地而不是一個長方形),再根據距離讓草旋轉不同的角度。

思路詳解:

1.要實現的功能如下圖。

技術分享圖片

2.O點是車子的中心坐標,A是草的中心坐標,只需求出ABAC的長度,然後再跟自己設定的觸發距離比較,符合就草根據距離做逐漸倒地的動作。(需要兩個實現,一距離判斷,二倒地動作)

技術分享圖片

3.只有OA兩點的坐標還不足以求出ABAC的距離,註意上圖表示的是車子本地XY軸坐標系,車子不是在世界原點。

4.要求出BO(AC)的長度,至少要知道CosAOB,此處可利用點乘(即數量積、點積),向量OA·向量OB=|向量OA|·|向量OB|·CosAOB,求出CosAOB後,即可求出OB的向量和OB長度。

5.求出OB長度後,用勾股定理即可求出

AB的長度,第一個實現就完成了,第二個實現以及細節的請往下看。

一、虛幻4如何通過Material編程實現車子壓倒草的功能

A.先創建一個MaterialParameterCollection(材質參數集合),因為material下的局限,只能通過調用MaterialParameterCollection來獲取外部標量和矢量。具體介紹可參考下方官方文檔。

https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/ParameterCollections/index.html?lang=zh-CN

技術分享圖片

創建後雙擊打開,Scalar Parameters下創建的是標量

(0)Vector Parameters下創建的是矢量(0,0,0,0),此處先創建一個矢量的,命名為CarPosition,用來儲存車子坐標,來傳入Material使用的。

技術分享圖片

技術分享圖片

打開車子的藍圖,在EventTick事件引出一條線用於實時獲取車子坐標。

技術分享圖片

車子的坐標有了,車子指向草的矢量(向量)就可得到了,還需要一個車子指向前方的矢量,此處車子的藍圖的component面板中添加一個空的組件,調整到車後底部並且對準車子的中心線。

技術分享圖片

技術分享圖片

在前面的MaterialParameterCollection中再添加一個表示車後坐標的矢量參數。

技術分享圖片

回到車子的藍圖中,從Event中再引一條線出來用來獲取車子後面點的坐標。

技術分享圖片

B.將前面的MaterialParameterCollection拖動到草的Material裏,點擊該Material Parameter Collection,並在Details面板中的Parameter Name下拉框選到表示車子坐標矢量的參數,再復制一個,選到表示車子背後坐標矢量的參數。

技術分享圖片

技術分享圖片

技術分享圖片

兩個坐標需要先用Mask去掉第四個坐標,將Float4轉換為float3。在material裏的參數、操作是以顏色RGBA碼來表示的。

技術分享圖片

車尾坐標指向車中心坐標的向量,用車中心的坐標減去車尾的坐標即可得到(後面簡稱向量DO)。此處相減前都乘了(1,1,0),這是去掉Z軸坐標的幹擾,計算的時候只要算XY軸平面的距離即可,只要2D向量即可滿足。當然,也可以前面mask的時候只保留RG值組成為Float2坐標。

技術分享圖片

同理,車中心坐標指向草中心坐標的向量(後面簡稱向量OA)。下圖的Object Position是指當前這個material的中心在世界坐標中的位置。

技術分享圖片

根據點乘的公式可得, CosAOB=(向量OA·向量OB)÷(|向量OA|·|向量OB|),此處向量OB不知道,用向量DO代替CosAOB=(向量OA·向量DO)÷(|向量OA|·|向量DO|),因為向量DO的指向和向量OB的指向相同,所以求出來的CosAOB值是一樣的。

向量的點積,用Dot接上兩個向量即可求出,向量的絕對值可用Vector Length即可求出(前面是Float2的用V2,前面是Float3的用V3)。此處有兩種做法,一種是用Normal將向量歸一化然後再求Cos,或者直接用本身向量長度求也可以。

技術分享圖片

技術分享圖片

可以先求向量OB,再求向量OB的長度,或者直接向量OA的絕對值乘上CosAOB直接得到OB的長度。

技術分享圖片

技術分享圖片

但是此處有一點要註意,向量OA和向量DO夾角大於90°時,CosAOB的值時負值的,會導致車子的前面部分草有壓倒的反應,但是後面部分草沒有反應。

技術分享圖片

要求的是CosAOB,但是當角度大於90°時,cos的值實際上是cosAOB。當AOB增大時,AOB在減小(90°->0°),由上面的cos值變化圖,可以看出當角度大於90°時,要求的cosAOB跟當前的cos值時相反的關系。

技術分享圖片

cosAOB大於零時,仍使用當前的cos值,cosAOB小於零時,即乘以-1即可得到向量OB

技術分享圖片

然後即可用勾股定理求出向量OB的長度,或者用向量OA=向量OB+向量BA,求出向量OB後再求向量OB的長度。到這裏草在水平方向和垂直方向離車子的距離就都求出來了,分別是|向量OA||向量OB|

技術分享圖片

C.接下來需要實現草旋轉的部分。如下。RotationAngle的值需為0~1.

技術分享圖片

旋轉是根據UV坐標系來旋轉的,x軸向右,y軸向上,z軸垂直xy軸從屏幕出來。

技術分享圖片

(1,0,0)表示沿著本地X軸旋轉,但我們需要在世界中,面向相機的方向倒下去,所以加上Transform Vector將本地的坐標空間轉換成世界坐標,此處除了使用View Space也可以使用Camera Space,效果等同。

技術分享圖片

還需要自定義三個參數來做判斷依據,CarLongCarWidth兩個參數用來判斷是否在車子底下,OutSideWidth用來結合另外兩個,來判斷外圈草倒地動作的範圍。

技術分享圖片

上面的自定義參數,carlong儲存車子長,carwidth儲存車子寬,outsidewidth儲存草開始觸發操作,離車子矩形邊緣的距離。

技術分享圖片

判斷草是否在觸發範圍內,如下圖。第一個if,出口接material上的World Position Offset,當A>B時,如果有之前有別的代碼連World Position Offset上,可連在此處,否則連一個0常量即可,第二個ifA>B時,相同,當A<B時,接旋轉草代碼。

技術分享圖片

草旋轉倒地也要做判斷,當草在車子底下時為倒地90°,在車子外但在+outsidewidth內時,根據距離由遠及近0°->90°改變倒地的角度。

此處將90÷OutSideWidth得到每1單位OutSideWidth對應多少°,|向量OB|(即草豎直方向離車子中心的距離)減去CarLong得到草離車子邊的距離L,然後L去乘上面得到的等分,得到L對應的角度,因為初始的角度時90°,即有這樣的關系,草離車子邊的距離L:OutSideWidth->0時,草的角度∠:0->9090再減去乘出來度數可得到草應旋轉的度數,然後除以360可以得到需要的浮點數。

技術分享圖片

技術分享圖片

此處還可以根據車子的前進後退,讓草分別做出往前旋轉還是往後旋轉,在前面的MaterialParameterCollection中新增一個CarForwardSpeed,並在EventTick下實時獲取車子的速度方向,然後根據CarForwardSpeed的值傳+360-360到上上圖中。

技術分享圖片

技術分享圖片

技術分享圖片

判斷草水平方向離車子邊的如下圖,同理。

技術分享圖片

完成後,大體結構如下。

技術分享圖片

如果需要HLSL代碼,可以點擊window->HLSL Code

技術分享圖片

到此就完成了。

虛幻4 在Material中如何實現 車子壓倒草的功能