虛幻4多pass渲染向虛幻4巨佬低頭【第一卷:Dynamic Character HitMask】
來自專欄 虛幻4渲染編程
本專欄的「虛幻4向巨佬低頭」篇會慢慢介紹epic官方大神Ryan Brucks 所做的一些效果。什麼都不用說,先讓我們膜拜巨佬三秒。
先聲明一下這一部分內容主要是對Ryan大神所展示的效果的研究和自己實現,我不是簡單搬運!因為你是找不到Ryan實現這些效果從資源準備開始的每一步詳細步驟的。
先上效果吧:
我在這裡只做了這個效果的核心,就是如何繪製mask
巨佬Ryan做的效果是這樣的:
我們只要有了mask,就能做巨佬的這種動態損傷效果啦。下面我們就開始吧
這是一個實時繪製污漬的多pass效果。虛幻里實現多pass的方式目前用得比較多的就rendertarget還有一個是多重疊模型。也許後期虛幻4會暴露出更多介面和特性。
首先我們要準備一下幾個資源
第一個BP-DamageCHaracter,繼承於ACharacter類,用於接收我們的滑鼠輸入和架一台攝像機,第二個BP_DamagePlayer,繼承於Actor類,用於完成這次效果的主要功能,第三個就是這次效果的場景,第四個為繪製最後一個HitResult的材質,第五個是呈現角色最後效果的材質,它會使用M_AccumDamage繪製出的RT_HitResult。M_UnWrap用於將角色瞬間展成一個平面(後面會闡述為啥要這麼做)。
完成好這幾個資產的準備後,我們需要打開腳本,為腳本做一些設置
首先BP_DamagePlayer中,我們需要為它準備一個模型資產和一個動畫資產。動畫資產不用多說,只需要滿足虛幻4對動畫資源的要求即可。模型資產有一個需要注意的地方,就是我們需要為模型資源製作2套UV。由於通常模型製作過程中我們會將模型對稱來製作,這時候製作出的模型其實是uv重疊的。這樣的好處就是節約,不管是貼圖的利用率還是建模的速度。但是uv重疊對我們這種繪製來說是不可以的,所以我們需要再分一套不重疊的uv。
這是max里的展開後的效果。導入引擎後你應該看到下圖的結果
為BP_DamagePlayer準備好動畫和模型資產後,我們還需要創建一個SceneCapturecomponent2D,然後將他上移到模型頭頂,rotation設置為(0,-90.270)即可。再新建一個hitLocation成員變數,用於儲存滑鼠的點擊位置。最後你的SceneCapturComponent2D應該是下圖這樣設置的
BP_DamagePlayer是下圖這樣的
注意模型的正面朝嚮應該和Y軸一致,調整senecapturecomponent2D和模型的朝向位置是為了更方便後期繪製的時候對應坐標。
完成好這些準備後我們需要為BP_DamagePlayer添加一些邏輯
下面是這次效果的主要邏輯
主要分為五部分,第一部分是將瞬間展開材質給予模型,讓模型瞬間被展開成一個平面(後面會詳細闡述這麼做的目的),第二部分為抓取展開成平面的模型,並將這些信息(其實這裡抓取的是頂點位置信息)儲存到RT_HitMask里。第三部分將角色原來的材質設置回去,完成抓取操作,第四部分為將滑鼠位置傳入M_AccumDamage里。最後用M—AccumeDamage繪製RT_HitResult。
最後的一步就是在beginPlay上給RT_HitResult一個clear操作。
完成BP_DamagePlayer操作後我們需要來到BP_DamageCharacter中。
邏輯很簡單,我們需要創建一個BP_DamageHitPlayer來指向關卡里的BP_DamagePLayer的一個實例。
完成這一切後,剩下的就是shader(材質)的工作了
首先來說一下M_Unwrap。這個材質如下圖
這個材質會瞬間將模型展成一個屏面。首先來說一下為什麼要展成一個平面。我們想要在模型上繪製,就需要解決幾個問題。第一個是在哪兒繪製,第二是怎麼繪製。第二個問題很好解決,直接向RT上繪製就可以了(可以看看我前面的幾篇博客---RenderTarget在虛幻4的應用)。那麼現在來解決在哪兒繪製的問題。以前RenderTarget在虛幻4的應用中是直接在RT上繪製然後把RT映射到平面上,這是沒問題的。因為模型平面和RT是一個簡單映射關係
而現在是一個極為複雜的映射關係,不僅如此。模型還在動畫的驅動下不停運動變化
所以要是有個辦法能儲存各個頂點的位置,然後我把這些位置拿出來用就好了。所以現在就可以把模型瞬間展開成一個平面,然後把這個平面照下來成一張圖,這個圖裡存的不是顏色,而是頂點的位置,就像法線貼圖裡存所有定點法線一樣。這裡再把這個材質的截圖放過來對照講解。
首先Texcoord【1】表示獲取的是模型的第二套UV。由於UV的範圍是X【0,1】Y【-1,0】所以我們用constantbiassScale把UV坐標調整到X【-0.5,0.5】Y【-0.5,0.5】。相當於把uv坐標平移到角色腳底。(隨手拿滑鼠畫的,丑請見諒)
再乘以1000,將以前大小為1X1的平面放大到1000X1000方便捕獲。最後減去頂點本身的位置信息,最後得到的就是個平面。
最後就是要考慮究竟要捕獲的什麼了,現在只是把頂點展開了,裡面記錄的信息應該是模型頂點未被展成平面時的位置
完成這一切後我們只需要在M_AccumDamage中把這些記錄到RT_HitMask的信息和HitPosition進行比較做個sphereMask就能繪製出RT_HitResult了
下面是M_AccumDamge的邏輯
R就是我們的筆刷大小,P是BP_DamagePlayer上傳的HitLocation。那上面那個Texture是RT_HitMask。RT_HitMask的來源是
最後需要注意的一點是記得把BP_DamagePlayer中的SkeletonMeshComponent(我們的模型)碰撞設置為blockall。最後就大功告成啦。
這還能做很多其他效果,比如繪製污漬,繪製傷口,給角色繪製眼淚,實時流下來,等等。
下面章會介紹巨佬Rayan的其他效果並且我們自己一步步實現它!!!
推薦閱讀:
※pixi-action - 一個類似 cocos2d-x 使用方法的 Pixi.js 動畫插件
※從零開始寫引擎(OPENGL)(四)-後處理實現
※[DOD Series][CppCon14] Data-Oriented Design and C++
※[GDC16]Global Illumination in Tom Clancys The Division
※UE4中創建自定義模塊