ue4集合类型_UE4粒子系统渲染管线概述
本文基于UE4版本4.25.3,對Cascade粒子系統的移動端渲染管線進行簡單的概括和描述。
Game Thread部分
粒子系統Actor被Spawn(或所在的Level被加載)的時候,UParticleSystemComponent注冊和初始化,并通過CreateSceneProxy函數注冊和創建FParticleSystemSceneProxy。
UParticleSystemComponent的主要數據成員是TArray<struct FParticleEmitterInstance*> EmitterInstances,包含粒子系統的所有粒子發射器。每一個粒子發射器對應一個FParticleEmitterInstance,管理當前發射器下所有的粒子。
FBaseParticle為粒子數據結構,保存粒子的Location、Rotation、Size和Velocity等數據。FParticleEmitterInstance用uint8* ParticleData指向保存FBaseParticle類型數據集合的連續內存空間。
UParticleSystemComponent關聯的所有粒子數據內存空間只由GameThread訪問。在幀結束的時候通過UpdateDynamicData函數創建一份包含粒子內存數據的拷貝——FParticleDynamicData,并異步傳遞給FParticleSystemSceneProxy,供RenderThread渲染使用。
大部分情況下,UE4通過給渲染線程生成一份渲染數據拷貝和函數線程專用(比如函數后綴加_RenderThread)的方式來防止出現多線程渲染的Race Condition問題。
GameThread部分調用示意圖Render Thread部分
在FParticleDynamicData被GameThread傳遞過來之后,粒子系統的渲染真正開始。
粒子系統的渲染始于FParticleSystemSceneProxy::GetDynamicMeshElements函數,輸出FMeshBatchs。FMeshBatch是FParticleSystemSceneProxy到MeshDrawCommand之間的一個中間數據結構,主要包含頂點數據流(FVertexStream)、IndexBuffer和材質等。
粒子系統渲染用到的頂點數據流主要有兩個:索引為0的幾何數據流和索引為1的Instanced數據流,由FParticleSpriteVertexFactory創建和關聯。幾何數據流描述每個粒子的幾何結構為4個頂點構成的單位大小的正方形。Instanced數據流為粒子數據集合,用于以Instanced的方式繪制這些粒子正方形。
Instanced數據流由FParticleDynamicData初始化而來。因為FParticleDynamicData的數據內容主要是GameThread使用的FBaseParticle類型數據集合的拷貝,所以RenderThread通過FDynamicSpriteEmitterData::GetVertexAndIndexData函數把原類型數據集合轉換成渲染使用的FParticleSpriteVertex類型數據集合。FParticleSpriteVertex定義了需要傳入GPU的頂點數據結構,與ParticleSpriteVertexFactory.ush 定義的頂點輸入類型FVertexFactoryInput對應。
為什么GameThread和RenderThread要分別定義粒子數據結構?GameThread對粒子的抽象是一個Pivot點,更新的是這個Pivot點的位置、旋轉和Size等信息。而RernderThread把粒子點幾何化為一個4個頂點,2個面構成的單位正方形,渲染的時候基于粒子Pivot點的位置、旋轉和Size等信息把粒子的4個頂點計算并繪制出來。
FMeshBatch生成后,進入到MeshDrawCommand的構建階段。FMeshBatch與MeshDrawCommand可理解為一對n的關系,n的值取決于該Mesh會被多少個EMeshPass處理。比如,產生實時陰影的不透明Mesh會被DepthPass、CSMShadowDepth和BasePass 三個EMeshPass處理來分別構建MeshDrawCommand。
為什么需要定義不同的EMeshPass?不同的EMeshPass繪制關聯的頂點數據流,Shader和渲染狀態等不一樣,比如DepthPass的繪制只需要設置頂點位置數據流(PositionOnlyStream),關聯的Shader主要功能為Vertex的空間變換和Pixel的深度輸出,不用做光照計算等。
對粒子系統來說,一般不寫場景深度,不產生陰影,所以DepthPass和CSMShadowDepth的MeshDrawCommand構建過程會被過濾掉。BasePass的構建始于FMobileSceneRenderer::SetupMobileBasePassAfterShadowInit函數,在關聯好Shader,設置好TaskContext渲染狀態等之后,調用BuildMeshDrawCommands函數真正進行MeshDrawCommand的構建。
所有相關EMeshPass的MeshDrawCommand構建好之后,開始MeshDrawCommand的提交和繪制。BasePass的繪制始于FMobileSceneRenderer::RenderMobileBasePassBasePass函數,然后根據構建階段生成的TaskContext渲染狀態設置PipelineState,根據MeshDrawCommand關聯的頂點數據流設置StreamSource等,最后調用RHICmdList::DrawIndexedPrimitive完成繪制。
構建MeshDrawCommand階段引擎默認是渲染線程起Work線程來并發執行,可以設置Console命令r.MeshDrawCommands.ParallelPassSetup=0來關掉并發,最后的Mesh繪制可以設置r.RHIThread.Enable=0來關掉RHI線程平臺相關的繪制API的調用,這樣上述所有階段都在RenderThread依次順序執行,方便調試。
RenderThread部分調用示意圖PS:UE4引擎的代碼量巨大,流程龐雜,單扣一個小細節就可能要研究上好幾天,想要用短短幾頁文字把渲染管線描述清楚難度很大,而且還需要一些寫作技巧使得描述不失偏頗,有點理解官網文檔的“言簡意賅”了(doge~~~
參考文獻:
總結
以上是生活随笔為你收集整理的ue4集合类型_UE4粒子系统渲染管线概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七号信令之MAP
- 下一篇: input子系统基础之按键3——inpu