虛幻引擎 4 渲染流程分析
今天為大家?guī)淼氖寝D載自虛幻引擎愛好者王文濤的博客文章《虛幻引擎 4 渲染流程分析》,這篇文章通過 Renderdoc 的分析通俗地介紹虛幻引擎 4 的渲染過程。
UE4作為當今商業(yè)引擎界的大佬,渲染和圖形質量一直是首屈一指的水準,但是相對于unity來說UE4基本上是一套完整方案提供,不通過源碼修改對渲染進行定制的可能性比較小,而且同時UE4這方面的文檔很少,因此這篇文章就是想通過分析UE4的渲染過程,來給大家針對自己使用ue4開發(fā)的游戲的內容特點做出優(yōu)化帶來啟發(fā)。
我們使用Renderdoc對UE4(PC,DX11)截幀,UE4的版本為4.18. 可以看到UE4一幀畫面的渲染過程如下
可以看到的是整個渲染流程還是很清晰明了的,接下來就會逐步分析每個過程。
1.Z-Prepass
UE4在deferred shading 過程之前這個,會有一系列的culling過程剔除掉不需要的像素或者幾何體,基本上可以猜測是UE4是為了減輕后期在deferred shadinggbuffer 生成中的龐大計算量,第一遍的zpass會先渲染一遍場景中的幾何,用于生產SceneDepthZ以及HZB buffer,格式為R24G8TYPELESS
2.Compute light grid
在Pre-Z之后UE4會把場景中的燈光按照屏幕空間分成相應的grid,類似于cluster shading的方法,注意這里的grid只考慮點光源,聚光燈,以及reflection captures,UE4這一步是通過compute shader實現(xiàn)的,所以只在sm>5.0的平臺上有。具體shader代碼在LightGridInjection.usf,閱讀代碼之后我們可以發(fā)現(xiàn) UE4的燈光空間grid的劃分是按照指數(shù)增長的。也就是每個grid的z隨著距離會增長。
在真正計算光照時,我們可以用GridIndex來快速決定某點是否受到燈光影響。Lightculling的方法在forward下對于提高燈光的渲染效率是十分有用的,但UE4在DS下仍然保有了這一個過程。其效果存疑,初步推測是為了和UE4新加的Forward renderer統(tǒng)一。
3.Occlusion query
這一步在light culling之后,和Pre-Z pass 不同的是,Occlusion query 主要在物體級別做culling。ue4同樣使用的是hardware occlusion queries(GPU query)的技術。在這一個pass中,所有的不透明物體會被渲染為一個occluder(包圍盒):
在根據(jù)深度計算query之后,query的數(shù)據(jù)會傳回cpu,我們就可以計算每個物體有多少像素可見。這樣我們就能知道物體最終是否會被渲染。
在不透明物體的query pass之后。Unreal 還有一些其他的query pass,例如燈光(點光源)會有一個ShadowFrustumQUeries(一般是畫一個球體)反射則有 PlanarReflection queries(一般是畫一個 Cube)
4.HZB generation
接下來UE4會生成場景的Hi-z(Hierarchical Z),R16_Float 格式,這一步也就是對之前的zbuffer做連續(xù)的downsample。HZB buffer會在之后的計算中起到很多作用,特別是Image based 的lighting技術,例如SSR等等。
5.ShadowMap 渲染
接下來的一步就是渲染shadowmap(shadowDepth,注意,這里指的是實時陰影的計算。根據(jù)UE4中燈光類型的不同,實時陰影的計算也有一定的差別。
UE4中的燈光類 型分為stationary, static,moveable三種,相應的每種燈光cast realtime shadow的方式也不同。
對于stationary light,靜態(tài)物體的陰影會bake到static shadowmap,shadowmap只計算標記為動態(tài)物體的陰影,而對于dynamic light 會對所有物體投射陰影,而靜態(tài)燈光不會產生實時陰影。
ue4首先會渲染方向光的陰影,一般會渲染3split的cascade shadow ,所以我們能在截幀信息看到split0, split1和split2,注意cascade split數(shù)目在ue4中也是可以在方向光參數(shù)中設置的變量。
之后是stationary light的shadow渲染,注意這里只針對場景中的moveable的物體。
最后是對于movable light的渲染,對于movable的方向光,ue4仍然是cascade shadow map計算陰影,需要注意的是對于movable的點光源,ue4使用了cubemap shadowmap,在cubeshadowmap的第一個pass CopyCachedShadowMap中,ue4會直接cachecopy static物體的shadowmap,例如這個場景中
圓柱體為static,其他兩個物體設為movable,因此最后我們能看到Shadow 只畫了兩個幾何體。
最后動態(tài)物體的shadow會添加在這個cubemap上面。
注意 shadowcubemap使用了geometry shader來選擇畫在那個面上。
6.G-prepass
其實在g-prepass之前還會渲染一個volumtric fog(如果場景中有的話) 這里我們先跳過,
G-prepass就是ue4中常說的basspass,這個bass會真正的渲染場景并產生我們在deferred shading 中需要的G-buffers:
SceneColorDefferd:包含了間接光照信息,例如lightmap和lightprobe(ue4叫ILC)
場景Normal
場景Albedo顏色
PBR Specular信息
除此之外還有針對特殊shading模型的特殊Custom Data RT(例如 頭發(fā)的tangent sss等)和Pre baked shadow factors RT,一般情況下UE4的渲染需要5-6個RT輸出,除了產生GBuffer的計算之外,在這一步UE4還會計算完間接光照的信息,主要包括采集lightmap信息(靜態(tài)物體)和球諧函數(shù)信息(Indirect lighting cache或者Volumetric light map)
UE4在4.18引入了新的半動態(tài)光照技術也就是Volumetric lightmap,相比于之前的 ILC機制,Volumetric lightmap能夠更加細致的根據(jù)物體的空間位置對球諧函數(shù)probe做插值(ILC是每個物體做插值)
Volumetric lightmap的Texture3d
7.Velocity rendering
在basepass之后是Velocity rendering,Velocity buffer會渲染為一張R16B16UNorm,主要用于motion blur和TAA
8.Pre-Lighting
UE4在這一部分會計算DeferredDecal(屏幕空間貼花),和AmbientOcclusion, UE4的屏幕空間AO考慮了深度和Normal信息,UE4的SSAO分為兩個Pass,第一個pass會計算一個四分之一分辨率的RT,使用的是四分之一分辨率的normal和depth, 注意這里就用了之前生成的HZB buffer,第二個pass會渲染一個全分辨率RT并與第一個combine.注意最后計算的結果會乘到SceneColorDeferred這個RT上.
9.Lighting
接下來就是光照的渲染部分,UE4在渲染燈光光照時會先處理translucent 物體的照明。
在這之后會分別計算陰影燈光和非陰影燈光的standarddeferredlighting,
在這個pass之后,SceneColorDeferred RT就會包含最后直接光照的結果
10.ImageBased lighting
接下來UE4會渲染屏幕空間的一些光照效果,例如SSR(屏幕空間反射)還有ReflectionProbe等等
SSR會用到我們之前生成的HZB,在屏幕空間做Zbuffer的raymarching ,同時ue4的SSR會每幀jitter和TAA結合來提高質量。當擊中時SSR的shader會采樣上一幀的RT來獲得顏色
在SSR之后是ReflectionEnvironment Pass。這一步會結合場景中的反射球和之前的SSR結果會疊加到SceneColorDeferred這個RT中。
11. Post Processing
最后一步是UE4的Postprocessing,主要包括Temporal AA; Bloom;EyeAdaption等等這些可以自定義的內容。
UE4 的TAA會經歷兩個pass,第一個pass會處理沒被stencil的像素(例如有粒子特效的時候),會用到MainRT和velocity buffer,第二個pass會處理例如粒子這樣stencilled的pixel。兩個pass的區(qū)別在于混合當前RT和History buffer的blendfactor的不同,第一個pass的blendfactor會根據(jù)pixel的亮度距離等等變化,而第二個pass的blendfactor嘖固定為0.25,也就是說第二個pass的像素會更多考慮當前像素,很可能這是為了減少TAA中很常見的ghosting effect
注意:TAA的處理只包含動態(tài)的光照部分,也就是純動態(tài)光照。
以上的分析還是省略了很多的細節(jié),例如半透照明這種還沒涉及。從整體的流程分析來看,UE4在設計渲染方案的時候還是最大限度的考慮了功能的最大化,UE4的DS renderer包含了非常齊全的光照特效,包括靜態(tài)的lightmap,動態(tài)的lightprobe,屏幕空間的lighting,以及一些影視級別的渲染技術,例如頭發(fā)的渲染模型等等,但同時為了功能UE4的計算任務是很繁重的,因此也就不難理解為什么UE4需要Pre-Z和Occlusion Culling去剔除掉不用的像素。當然,對于使用UE4制作游戲的團隊來說,根據(jù)游戲內容特點,畫面的藝術風格,渲染管線都沒必要一成不變,例如對于一款開放世界的野外生存游戲。我們可以考慮省掉Pre-Z的過程,或者,只用地表去畫Pre-Z,又或者對于NPR畫面的游戲我們完全可以不需要6-7個RT去做Deferred shading。UE4應對這些定制化開發(fā)的需求的方法就是:開源。代碼就在DeferredShadingRenderer.cpp里。
-
分享到:
全部評論:0條