虛幻4 在Material中如何實現 車子壓倒草的功能
上次發了篇介紹車子壓倒草的博文
http://www.cnblogs.com/JinT-Hwang/p/8169146.html
中的2.部分。
不過存在一個問題,就是如果草很多,會有很多個碰撞體,雖然物理效果比較真實但是可能會導致性能問題。
這次介紹一下在草的材質中編碼,實現車子壓倒草的功能。
material中會用到一些數學的知識,還需要各位有一定的概念才能很好的理解。
關鍵詞:unreal4、虛幻4、汽車、草、壓倒、伏地、Material、材質編輯器、Shader
實現思路:通過求出草離車子的水平和垂直距離(如果只判斷車子離草的距離,結果周圍的草會成一個圓形倒地而不是一個長方形),再根據距離讓草旋轉不同的角度。
思路詳解:
1.要實現的功能如下圖。
2.O點是車子的中心坐標,A是草的中心坐標,只需求出AB和AC的長度,然後再跟自己設定的觸發距離比較,符合就草根據距離做逐漸倒地的動作。(需要兩個實現,一距離判斷,二倒地動作)。
3.只有O、A兩點的坐標還不足以求出AB和AC的距離,註意上圖表示的是車子本地XY軸坐標系,車子不是在世界原點。
4.要求出BO(AC)的長度,至少要知道Cos∠AOB,此處可利用點乘(即數量積、點積),向量OA·向量OB=|向量OA|·|向量OB|·Cos∠AOB,求出Cos∠AOB後,即可求出OB的向量和OB長度。
5.求出OB長度後,用勾股定理即可求出
一、虛幻4如何通過Material編程實現車子壓倒草的功能
A.先創建一個MaterialParameterCollection(材質參數集合),因為material下的局限,只能通過調用MaterialParameterCollection來獲取外部標量和矢量。具體介紹可參考下方官方文檔。
https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/ParameterCollections/index.html?lang=zh-CN
創建後雙擊打開,Scalar Parameters下創建的是標量
打開車子的藍圖,在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的中心在世界坐標中的位置。
根據點乘的公式可得, Cos∠AOB=(向量OA·向量OB)÷(|向量OA|·|向量OB|),此處向量OB不知道,用向量DO代替Cos∠AOB=(向量OA·向量DO)÷(|向量OA|·|向量DO|),因為向量DO的指向和向量OB的指向相同,所以求出來的Cos∠AOB值是一樣的。
向量的點積,用Dot接上兩個向量即可求出,向量的絕對值可用Vector Length即可求出(前面是Float2的用V2,前面是Float3的用V3)。此處有兩種做法,一種是用Normal將向量歸一化然後再求Cos,或者直接用本身向量長度求也可以。
可以先求向量OB,再求向量OB的長度,或者直接向量OA的絕對值乘上Cos∠AOB直接得到OB的長度。
但是此處有一點要註意,向量OA和向量DO夾角大於90°時,Cos∠AOB的值時負值的,會導致車子的前面部分草有壓倒的反應,但是後面部分草沒有反應。
要求的是Cos∠AOB,但是當角度大於90°時,cos的值實際上是cos∠AOB’。當∠AOB’增大時,∠AOB在減小(由90°->0°),由上面的cos值變化圖,可以看出當角度大於90°時,要求的cos∠AOB跟當前的cos值時相反的關系。
當cos∠AOB大於零時,仍使用當前的cos值,cos∠AOB小於零時,即乘以-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,效果等同。
還需要自定義三個參數來做判斷依據,CarLong和CarWidth兩個參數用來判斷是否在車子底下,OutSideWidth用來結合另外兩個,來判斷外圈草倒地動作的範圍。
上面的自定義參數,carlong儲存車子長,carwidth儲存車子寬,outsidewidth儲存草開始觸發操作,離車子矩形邊緣的距離。
判斷草是否在觸發範圍內,如下圖。第一個if,出口接material上的World Position Offset,當A>B時,如果有之前有別的代碼連World Position Offset上,可連在此處,否則連一個0常量即可,第二個if當A>B時,相同,當A<B時,接旋轉草代碼。
草旋轉倒地也要做判斷,當草在車子底下時為倒地90°,在車子外但在+outsidewidth內時,根據距離由遠及近0°->90°改變倒地的角度。
此處將90÷OutSideWidth得到每1單位OutSideWidth對應多少°,|向量OB|(即草豎直方向離車子中心的距離)減去CarLong得到草離車子邊的距離L,然後L去乘上面得到的等分,得到L對應的角度,因為初始的角度時90°,即有這樣的關系,草離車子邊的距離L:OutSideWidth->0時,草的角度∠:0->90,90再減去乘出來度數可得到草應旋轉的度數,然後除以360可以得到需要的浮點數。
此處還可以根據車子的前進後退,讓草分別做出往前旋轉還是往後旋轉,在前面的MaterialParameterCollection中新增一個CarForwardSpeed,並在EventTick下實時獲取車子的速度方向,然後根據CarForwardSpeed的值傳+360或-360到上上圖中。
判斷草水平方向離車子邊的如下圖,同理。
完成後,大體結構如下。
如果需要HLSL代碼,可以點擊window->HLSL Code。
到此就完成了。
虛幻4 在Material中如何實現 車子壓倒草的功能