渲染應(yīng)用階段
LWRP現(xiàn)在再unity2019已經(jīng)成為默認(rèn)的管線了,替代了原來(lái)的builtin管線,我當(dāng)前項(xiàng)目用的還是2018.4的lwrp,使用了一段時(shí)間,覺(jué)得還是想總結(jié)下lwrp的渲染流程。總結(jié)過(guò)程中也學(xué)到了不少東西,所以想在這里分享下我了解的lwrp管線
執(zhí)行應(yīng)用階段流程順序如下:
lwrp從結(jié)果來(lái)看就是前向渲染的流程,沒(méi)有g(shù)buffer保存幾何信息。他實(shí)現(xiàn)原理是將不透明渲染,天空盒渲染,透明渲染加入CommandBuffer里,最終一次性提交渲染。其中如果需要Depth或Opaque圖片則可以拷貝到rt輸出到指定全局變量給開發(fā)用。
下面我想說(shuō)下我了解的lwrp的詳細(xì)流程,設(shè)計(jì)的東西會(huì)比較多。也是看代碼的過(guò)程中學(xué)習(xí)了很多東西。
下面分享下:
lwrp整個(gè)渲染的主入口在LightweightRenderPipeline,他繼承的RenderPipeline,是rsp的渲染流程關(guān)鍵類
首先是構(gòu)造函數(shù)
PipelineSettings:這里會(huì)獲取LightweightRenderPipelineAsset(也就是我們外部傳入的管線的參數(shù))
ScriptableRenderer:srp渲染器,需要把LightweightRenderPipelineAsset傳給他。他是渲染核心,他會(huì)收集所有當(dāng)前幀要渲染的pass,以及他會(huì)擁有渲染相關(guān)的燈光和后處理等執(zhí)行方法。
PerFrameBuffer:每幀設(shè)置的緩存數(shù)據(jù)
_GlossyEnvironmentColor:主要用于PBR這塊的全局光照的顏色,在Lighting.hlsl的GlossyEnvironmentReflection,可以看到他主要是全局光照的高光部分顏色。
_SubtractiveShadowColor:主要用在除了主光源外的lightmap計(jì)算的陰影顏色。在SubtractDirectMainLightFromLightmap里使用
PerCameraBuffer:每幀攝像機(jī)的緩存數(shù)據(jù)
_InvCameraViewProj:視圖空間到投影空間的轉(zhuǎn)置矩陣,如果用原始矩陣乘以反向矩陣結(jié)果為identity矩陣。如果一些矩陣以一個(gè)特定的方式變換向量,反向矩陣可以將他們變換回去。例如worldToLoclaMatrix和localToWorldMatrix是互逆的。
_ScaledScreenParams:屏幕縮放參數(shù)
antiAliasing從asset中獲取msaaSampleCount
Shader.globalRenderPipeline = "LightweightPipeline";設(shè)置全局管線為L(zhǎng)ightweightPipeline
lightsDelegate:全局光照的回調(diào)
執(zhí)行到Render中執(zhí)行具體渲染流程:
SetupPerFrameShaderConstants:設(shè)置全局光照的數(shù)據(jù),設(shè)置PerFrameBuffer中的_GlossyEnvironmentColor和_SubtractiveShadowColor。
其中_GlossyEnvironmentColor是通過(guò)球形諧波方程決定顏色的,最后要轉(zhuǎn)到當(dāng)前顏色空間(gamma空間或線性空間)
_SubtractiveShadowColor則是直接賦值具體的除去主光源后的陰影顏色,只是也有最后轉(zhuǎn)到當(dāng)前顏色空間的轉(zhuǎn)換。
對(duì)當(dāng)前Render給過(guò)來(lái)當(dāng)前有哪些相機(jī)渲染的數(shù)據(jù)來(lái)進(jìn)行每個(gè)相機(jī)的渲染RenderSingleCamera。
每個(gè)相機(jī)中的渲染步驟如下:
CullResults.GetCullingParameters:獲取相機(jī)下的裁剪參數(shù),如果返回false說(shuō)明沒(méi)有聶榮,不需要渲染這個(gè)相機(jī)。如果需要考慮到類似vr等情況需要區(qū)分左右眼的攝像機(jī)時(shí)需要把stereoAware設(shè)置為true。
CommandBuffer cmd = CommandBufferPool.Get(k_RenderCameraTag):這里從命令緩存池中獲取一個(gè)gl命令緩存,CommandBuffer主要用于收集一系列g(shù)l指令,然后之后執(zhí)行。
ProfilingSample是對(duì)指定名字做性能采樣。
InitializeCameraData:初始化攝像機(jī)數(shù)據(jù)。
cameraData.msaaSamples:如果數(shù)量大于1說(shuō)明需要多重采樣
cameraData.isSceneViewCamera:這個(gè)是查看當(dāng)前要渲染的是否在unity的scene視圖
cameraData.isOffscreenRender:屏幕外渲染,如果攝像機(jī)的targettexture存在并且不是scene視圖則這個(gè)為true。
cameraData.isStereoEnabled:就是左右眼做區(qū)別的攝像機(jī),用于vr等
cameraData.isHdrEnabled:是否支持hdr,也就是高動(dòng)態(tài)范圍圖像,就是可以在高光情況下能看清一些光照細(xì)節(jié),提高細(xì)節(jié)渲染。
cameraData.postProcessLayer:后處理
cameraData.postProcessEnabled:是否開啟后處理
cameraData.renderScale:渲染縮放比例
cameraData.opaqueTextureDownsampling:降采樣
cameraData.isDefaultViewport:如果是正常的(0,0,1,1)則是默認(rèn)的
cameraData.maxShadowDistance:最大陰影范圍
cameraData.requiresDepthTexture:是否啟用深度紋理
cameraData.requiresOpaqueTexture:是否保存非透明顏色信息
cameraData.defaultOpaqueSortFlags:默認(rèn)的非透明渲染順序
SetupPerCameraShaderConstants
PerCameraBuffer._ScaledScreenParams:是一個(gè)vector4,包括相機(jī)像素的長(zhǎng)寬和紋素
PerCameraBuffer._InvCameraViewProj:設(shè)置攝像機(jī)視角的逆矩陣,通過(guò)GL.GetGPUProjectionMatrix獲取到當(dāng)前gpu正確坐標(biāo)系的投影矩陣,再跟camera.worldToCameraMatrix視圖矩陣相乘得到視圖到投影的矩陣,再用Matrix4x4.Inverse獲取逆矩陣。
cullingParameters.shadowDistance:設(shè)置陰影距離,這里會(huì)根據(jù)攝像機(jī)最遠(yuǎn)渲染距離來(lái)獲得最遠(yuǎn)可達(dá)到的距離。
ScriptableRenderContext.ExecuteCommandBuffer(cmd):執(zhí)行命令緩存
cmd.Clear();清除緩存數(shù)據(jù)
CullResults.Cull:根據(jù)裁剪的參數(shù)cullingParameters和context指定的渲染指令得到裁剪的燈光,物體等。
InitializeRenderingData:初始化渲染相關(guān)數(shù)據(jù)
GetMainLight:獲取主光源,如果是直線光并且mainLightRenderingMode不為L(zhǎng)ightRenderingMode.PerPixel就是主光源
mainLightCastShadows:如果可見(jiàn)光存在而且陰影設(shè)置存在則為true
additionalLightsCastShadows:如果additionalLightsRenderingMode是LightRenderingMode.PerPixel并且可見(jiàn)光存在并且lightType是LightType.Spot且陰影存在則為true
InitializeLightData:初始化燈光數(shù)據(jù),這里設(shè)置了mainLightIndex(也就是GetMainLight獲取的),設(shè)置additionalLightsCount獲取疊加光源的數(shù)量,maxPerObjectAdditionalLightsCount最大疊加光源數(shù)量,shadeAdditionalLightsPerVertex就是是否是疊加光源,visibleLights可視光源,supportsMixedLighting支持混合光源
InitializeShadowData:初始化陰影數(shù)據(jù),如果有多光源會(huì)添加LWRPAdditionalLightData到光源的gameobject上,m_ShadowBiasData會(huì)設(shè)置陰影偏移和陰影發(fā)現(xiàn)偏移,主要用于解決自陰影的問(wèn)題。supportsMainLightShadows支持主光源陰影 。mainLightShadowCascadesCount是陰影的級(jí)聯(lián)個(gè)數(shù),(mainLightShadowmapWidth、mainLightShadowmapHeight)主光源陰影貼圖的寬高。mainLightShadowCascadesSplit是陰影的級(jí)聯(lián)分割,supportsAdditionalLightShadows是否支持多光源陰影。additionalLightsShadowmapWidth、additionalLightsShadowmapHeight是多光源陰影貼圖的寬和高都是additionalLightsShadowmapResolution。supportsSoftShadows支持軟陰影
supportsDynamicBatching:是否支持動(dòng)態(tài)批處理,這個(gè)是lwrp的動(dòng)態(tài)批處理
設(shè)置完渲染數(shù)據(jù)后就是開始設(shè)置渲染的順序了:
renderer.Clear():再設(shè)置之前需要清理renderer的數(shù)據(jù),不然前一幀渲染的dc是不會(huì)清掉的,dc就會(huì)越來(lái)越高。
setupToUse.Setup(renderer, ref renderingData):默認(rèn)lwrp是用DefaultRendererSetup來(lái)設(shè)置的,當(dāng)然你也可以實(shí)現(xiàn)IRendererSetup然后傳入Render來(lái)自己實(shí)現(xiàn)。
DefaultRendererSetup:lwrp默認(rèn)會(huì)有一系列渲染過(guò)程。會(huì)再Setup中確定渲染的先后。
SetupPerObjectLightIndices設(shè)置每個(gè)對(duì)象光照信息
CreateRenderTextureDescriptor創(chuàng)建rt數(shù)據(jù)信息
GetCameraClearFlag獲取當(dāng)前攝像機(jī)清理方式,lwrp對(duì)這層做了一些處理,主要是對(duì)深度剔除做了一些選項(xiàng)
如果是渲染到紋理則用CreateLightweightRenderTexturesPass這個(gè)pass執(zhí)行一次渲染。
如果有渲染前要執(zhí)行的pass要實(shí)現(xiàn)IBeforeRender接口,并且可以多個(gè)pass
如果支持主光源陰影投放則執(zhí)行MainLightShadowCasterPass的pass
如果支持多光源陰影投放則執(zhí)行AdditionalLightsShadowCasterPass
之后執(zhí)行SetupForwardRenderingPass,這個(gè)pass是必然執(zhí)行的,設(shè)置攝像機(jī)到context里
如果支持深度貼圖獲取的話會(huì)執(zhí)行DepthOnlyPass(requiresDepthPrepass決定是否執(zhí)行他),這里會(huì)用一個(gè)rt保存深度貼圖新消息
如果支持屏幕空間陰影獲取,則會(huì)執(zhí)行ScreenSpaceShadowResolvePass,這里會(huì)用一個(gè)rt記錄屏幕空間中的陰影貼圖
然后執(zhí)行SetupLightweightConstanstPass,主要設(shè)置主光源和其他光源的顏色,位置以及其他屬性。如果不設(shè)置則會(huì)是默認(rèn)顏色和位置等信息。
然后執(zhí)行RenderOpaqueForwardPass,這個(gè)pass定義了兩個(gè)pass名,LightweightForward和SRPDefaultUnlit。然后再Execute申請(qǐng)cmd來(lái)做不透明渲染。
如果支持后處理則會(huì)執(zhí)行OpaquePostProcessPass,里面是申請(qǐng)一個(gè)臨時(shí)rt做相關(guān)不透明的后處理。
如果是相機(jī)是天空盒清除方式的話并且天空盒不是空的話則執(zhí)行DrawSkyboxPass,里面會(huì)繪制天空盒
如果需要天空盒處理之后執(zhí)行的話需要繼承IAfterSkyboxPass實(shí)現(xiàn)相關(guān)pass
如果是支持深度貼圖的話并且沒(méi)有執(zhí)行requiresDepthPrepass的話(就是前面執(zhí)行DepthOnlyPass的判斷)則會(huì)執(zhí)行CopyDepthPass,這里主要是拷貝深度貼圖到全局變量_CameraDepthAttachment中,shader可以直接獲取這個(gè)變量(如果有開深度貼圖獲取)
如果開啟了接收不透明貼圖的話則執(zhí)行CopyColorPass,這里主要是把不透明渲染后的顏色輸出到臨時(shí)rt中。
然后執(zhí)行RenderTransparentForwardPass,透明渲染方式
如果支持后處理則執(zhí)行TransparentPostProcessPass,也是一樣申請(qǐng)一個(gè)臨時(shí)rt做相關(guān)透明渲染的后處理。如果不需要并且不支持屏幕外渲染并且不是渲染到紋理的則要執(zhí)行FinalBlitPass,這里主要設(shè)置貼圖到全局變量_BlitTex,然后把顏色blit到內(nèi)置rt中
然后如果攝像機(jī)有IAfterRender的mono則會(huì)執(zhí)行pass中的GetPassToEnqueue方法。
最后還會(huì)有一個(gè)EndXRRenderingPass的渲染,這個(gè)是支持立體攝像機(jī)的情況下執(zhí)行的,主要是停止立體攝像機(jī)渲染
然后再到外面renderer.Execute(context, ref renderingData);也就是把所有pass都執(zhí)行一次。(前面只是加入到列表中,并沒(méi)有執(zhí)行每個(gè)pass的execute)
最后需要context.Submit來(lái)提交渲染,這時(shí)相應(yīng)的gpu才會(huì)根據(jù)cmd來(lái)執(zhí)行所有的pass
這樣整個(gè)渲染流程的應(yīng)用階段就算完成了,但是其實(shí)每個(gè)pass里面還有一些處理過(guò)程,我還是分到下一章再總結(jié)了!
來(lái)源:電子創(chuàng)新網(wǎng)
審核編輯黃昊宇
-
渲染
+關(guān)注
關(guān)注
0文章
70瀏覽量
10937 -
Unity
+關(guān)注
關(guān)注
1文章
127瀏覽量
21856
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論