資料介紹
URP渲染管線初步解析
LWRP現(xiàn)在在unity2019已經(jīng)成為默認(rèn)的管線了,并更名為URP(通用渲染管線),替代了原來的builtin管線,以下是應(yīng)用階段的渲染流程順序。
步驟分析
URP整個渲染的主入口在UniversalRenderPipeline,他繼承的RenderPipeline,是rsp的渲染流程關(guān)鍵類
PipelineSettings:這里會獲取UniversalRenderPipelineAsset(也就是我們外部傳入的管線的參數(shù))
ScriptableRenderer:srp渲染器,需要把UniversalRenderPipelineAsset傳給他。他是渲染核心,他會收集所有當(dāng)前幀要渲染的pass,以及他會擁有渲染相關(guān)的燈光和后處理等執(zhí)行方法。
PerFrameBuffer:每幀設(shè)置的緩存數(shù)據(jù)
_GlossyEnvironmentColor:主要用于PBR這塊的全局光照的顏色,在Lighting.hlsl的GlossyEnvironmentReflection,可以看到他主要是全局光照的高光部分顏色。
_SubtractiveShadowColor:主要用在除了主光源外的lightmap計算的陰影顏色。在SubtractDirectMainLightFromLightmap里使用。
PerCameraBuffer:每幀攝像機(jī)的緩存數(shù)據(jù)
_InvCameraViewProj:視圖空間到投影空間的轉(zhuǎn)置矩陣,如果用原始矩陣乘以反向矩陣結(jié)果為identity矩陣。如果一些矩陣以一個特定的方式變換向量,反向矩陣可以將他們變換回去。例如worldToLoclaMatrix和localToWorldMatrix是互逆的。
_ScaledScreenParams:屏幕縮放參數(shù)
antiAliasing:從asset中獲取msaaSampleCount
Shader.globalRenderPipeline = " UniversalPipeline ";設(shè)置全局管線為UniversalPipeline
lightsDelegate:全局光照的回調(diào)
執(zhí)行到Render中執(zhí)行具體渲染流程:
SetupPerFrameShaderConstants:設(shè)置全局光照的數(shù)據(jù),設(shè)置PerFrameBuffer中的_GlossyEnvironmentColor和_SubtractiveShadowColor。
其中_GlossyEnvironmentColor是通過球形諧波方程決定顏色的,最后要轉(zhuǎn)到當(dāng)前顏色空間(gamma空間或線性空間)
_SubtractiveShadowColor則是直接賦值具體的除去主光源后的陰影顏色,只是也有最后轉(zhuǎn)到當(dāng)前顏色空間的轉(zhuǎn)換。
對當(dāng)前Render給過來當(dāng)前有哪些相機(jī)渲染的數(shù)據(jù)來進(jìn)行每個相機(jī)的渲染RenderSingleCamera。
每個相機(jī)中的渲染步驟如下:
CullResults.GetCullingParameters:獲取相機(jī)下的裁剪參數(shù),如果返回false說明沒有聶榮,不需要渲染這個相機(jī)。如果需要考慮到類似vr等情況需要區(qū)分左右眼的攝像機(jī)時需要把stereoAware設(shè)置為true。
CommandBuffer cmd = CommandBufferPool.Get(k_RenderCameraTag):這里從命令緩存池中獲取一個gl命令緩存,CommandBuffer主要用于收集一系列g(shù)l指令,然后之后執(zhí)行。
ProfilingSample是對指定名字做性能采樣。
InitializeCameraData:初始化攝像機(jī)數(shù)據(jù)。
cameraData.msaaSamples:如果數(shù)量大于1說明需要多重采樣。
cameraData.isSceneViewCamera:這個是查看當(dāng)前要渲染的是否在unity的scene視圖。
cameraData.isOffscreenRender:屏幕外渲染,如果攝像機(jī)的targettexture存在并且不是scene視圖則這個為true。
cameraData.isStereoEnabled:就是左右眼做區(qū)別的攝像機(jī),用于vr等
cameraData.isHdrEnabled:是否支持hdr,也就是高動態(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:是一個vector4,包括相機(jī)像素的長寬和紋素
PerCameraBuffer._InvCameraViewProj:設(shè)置攝像機(jī)視角的逆矩陣,通過GL.GetGPUProjectionMatrix獲取到當(dāng)前gpu正確坐標(biāo)系的投影矩陣,再跟camera.worldToCameraMatrix視圖矩陣相乘得到視圖到投影的矩陣,再用Matrix4x4.Inverse獲取逆矩陣。
cullingParameters.shadowDistance:設(shè)置陰影距離,這里會根據(jù)攝像機(jī)最遠(yuǎn)渲染距離來獲得最遠(yuǎn)可達(dá)到的距離。
ScriptableRenderContext.ExecuteCommandBuffer(cmd):執(zhí)行命令緩存
cmd.Clear();清除緩存數(shù)據(jù)
CullResults.Cull:根據(jù)裁剪的參數(shù)cullingParameters和context指定的渲染指令得到裁剪的燈光,物體等。
InitializeRenderingData:初始化渲染相關(guān)數(shù)據(jù)
GetMainLight:獲取主光源,如果是直線光并且mainLightRenderingMode不為LightRenderingMode.PerPixel就是主光源。
mainLightCastShadows:如果可見光存在而且陰影設(shè)置存在則為true。
additionalLightsCastShadows:如果additionalLightsRenderingMode是LightRenderingMode.PerPixel并且可見光存在并且lightType是LightType.Spot且陰影存在則為true。
InitializeLightData:初始化燈光數(shù)據(jù),這里設(shè)置了mainLightIndex(也就是GetMainLight獲取的),設(shè)置additionalLightsCount獲取疊加光源的數(shù)量,maxPerObjectAdditionalLightsCount最大疊加光源數(shù)量,shadeAdditionalLightsPerVertex就是是否是疊加光源,visibleLights可視光源,supportsMixedLighting支持混合光源。
InitializeShadowData:初始化陰影數(shù)據(jù),如果有多光源會添加LWRPAdditionalLightData到光源的gameobject上,m_ShadowBiasData會設(shè)置陰影偏移和陰影發(fā)現(xiàn)偏移,主要用于解決自陰影的問題。
supportsMainLightShadows支持主光源陰影 。
mainLightShadowCascadesCount是陰影的級聯(lián)個數(shù),(mainLightShadowmapWidth、mainLightShadowmapHeight)主光源陰影貼圖的寬高。
mainLightShadowCascadesSplit是陰影的級聯(lián)分割,supportsAdditionalLightShadows是否支持多光源陰影。
additionalLightsShadowmapWidth、additionalLightsShadowmapHeight是多光源陰影貼圖的寬和高都是additionalLightsShadowmapResolution。
supportsSoftShadows支持軟陰影。
supportsDynamicBatching:是否支持動態(tài)批處理,這個是lwrp的動態(tài)批處理。
設(shè)置完渲染數(shù)據(jù)后就是開始設(shè)置渲染的順序了:
renderer.Clear():再設(shè)置之前需要清理renderer的數(shù)據(jù),不然前一幀渲染的dc是不會清掉的,dc就會越來越高。
setupToUse.Setup(renderer, ref renderingData):默認(rèn)lwrp是用DefaultRendererSetup來設(shè)置的,當(dāng)然你也可以實現(xiàn)IRendererSetup然后傳入Render來自己實現(xiàn)。
DefaultRendererSetup:lwrp默認(rèn)會有一系列渲染過程。會再Setup中確定渲染的先后。
SetupPerObjectLightIndices設(shè)置每個對象光照信息。
CreateRenderTextureDescriptor創(chuàng)建rt數(shù)據(jù)信息。
GetCameraClearFlag獲取當(dāng)前攝像機(jī)清理方式,lwrp對這層做了一些處理,主要是對深度剔除做了一些選項
如果是渲染到紋理則用CreateLightweightRenderTexturesPass這個pass執(zhí)行一次渲染。
如果有渲染前要執(zhí)行的pass要實現(xiàn)IBeforeRender接口,并且可以多個pass。
如果支持主光源陰影投放則執(zhí)行MainLightShadowCasterPass的pass。
如果支持多光源陰影投放則執(zhí)行AdditionalLightsShadowCasterPass。
之后執(zhí)行SetupForwardRenderingPass,這個pass是必然執(zhí)行的,設(shè)置攝像機(jī)到context里。
如果支持深度貼圖獲取的話會執(zhí)行DepthOnlyPass(requiresDepthPrepass決定是否執(zhí)行他),這里會用一個rt保存深度貼圖新消息。
如果支持屏幕空間陰影獲取,則會執(zhí)行ScreenSpaceShadowResolvePass,這里會用一個rt記錄屏幕空間中的陰影貼圖。
然后執(zhí)行SetupLightweightConstanstPass,主要設(shè)置主光源和其他光源的顏色,位置以及其他屬性。如果不設(shè)置則會是默認(rèn)顏色和位置等信息。
然后執(zhí)行RenderOpaqueForwardPass,這個pass定義了兩個pass名,LightweightForward和SRPDefaultUnlit。然后再Execute申請cmd來做不透明渲染。
如果支持后處理則會執(zhí)行OpaquePostProcessPass,里面是申請一個臨時rt做相關(guān)不透明的后處理。
如果是相機(jī)是天空盒清除方式的話并且天空盒不是空的話則執(zhí)行DrawSkyboxPass,里面會繪制天空盒。
如果需要天空盒處理之后執(zhí)行的話需要繼承IAfterSkyboxPass實現(xiàn)相關(guān)pass。
如果是支持深度貼圖的話并且沒有執(zhí)行requiresDepthPrepass的話(就是前面執(zhí)行DepthOnlyPass的判斷)則會執(zhí)行CopyDepthPass,這里主要是拷貝深度貼圖到全局變量_CameraDepthAttachment中,shader可以直接獲取這個變量(如果有開深度貼圖獲取)
如果開啟了接收不透明貼圖的話則執(zhí)行CopyColorPass,這里主要是把不透明渲染后的顏色輸出到臨時rt中。
然后執(zhí)行RenderTransparentForwardPass,透明渲染方式。
如果支持后處理則執(zhí)行TransparentPostProcessPass,也是一樣申請一個臨時rt做相關(guān)透明渲染的后處理。如果不需要并且不支持屏幕外渲染并且不是渲染到紋理的則要執(zhí)行FinalBlitPass,這里主要設(shè)置貼圖到全局變量_BlitTex,然后把顏色blit到內(nèi)置rt中。
然后如果攝像機(jī)有IAfterRender的mono則會執(zhí)行pass中的GetPassToEnqueue方法。
最后還會有一個EndXRRenderingPass的渲染,這個是支持立體攝像機(jī)的情況下執(zhí)行的,主要是停止立體攝像機(jī)渲染。
然后再到外面renderer.Execute(context, ref renderingData);也就是把所有pass都執(zhí)行一次。(前面只是加入到列表中,并沒有執(zhí)行每個pass的execute)
最后需要context.Submit來提交渲染,這時相應(yīng)的gpu才會根據(jù)cmd來執(zhí)行所有的pass。
源碼分析
渲染前階段:
根據(jù)渲染資產(chǎn)初始化渲染管線
public UniversalRenderPipeline(UniversalRenderPipelineAsset asset) { SetSupportedRenderingFeatures(); //設(shè)置渲染支持功能 //PerFrameBuffer類中的參數(shù)指定 PerFrameBuffer._GlossyEnvironmentColor = Shader.PropertyToID("_GlossyEnvironmentColor"); PerFrameBuffer._SubtractiveShadowColor = Shader.PropertyToID("_SubtractiveShadowColor"); PerFrameBuffer._Time = Shader.PropertyToID("_Time"); PerFrameBuffer._SinTime = Shader.PropertyToID("_SinTime"); PerFrameBuffer._CosTime = Shader.PropertyToID("_CosTime"); PerFrameBuffer.unity_DeltaTime = Shader.PropertyToID("unity_DeltaTime"); PerFrameBuffer._TimeParameters = Shader.PropertyToID("_TimeParameters"); PerCameraBuffer._InvCameraViewProj = Shader.PropertyToID("_InvCameraViewProj"); PerCameraBuffer._ScreenParams = Shader.PropertyToID("_ScreenParams"); PerCameraBuffer._ScaledScreenParams = Shader.PropertyToID("_ScaledScreenParams"); PerCameraBuffer._WorldSpaceCameraPos = Shader.PropertyToID("_WorldSpaceCameraPos"); // Let engine know we have MSAA on for cases where we support MSAA backbuffer if (QualitySettings.antiAliasing != asset.msaaSampleCount) //設(shè)置多重采樣抗鋸齒 QualitySettings.antiAliasing = asset.msaaSampleCount; // For compatibility reasons we also match old LightweightPipeline tag. Shader.globalRenderPipeline = "UniversalPipeline,LightweightPipeline"; //設(shè)置渲染管線 Lightmapping.SetDelegate(lightsDelegate); CameraCaptureBridge.enabled = true; RenderingUtils.ClearSystemInfoCache(); }
渲染階段
1. 開始幀渲染
BeginFrameRendering(renderContext, cameras); //開始幀渲染
2. 判斷色彩空間是否為線性空間
GraphicsSettings.lightsUseLinearIntensity = (QualitySettings.activeColorSpace == ColorSpace.Linear); //色彩空間是否是線性空間
3. 設(shè)置資產(chǎn)中的Batcher
GraphicsSettings.useScriptableRenderPipelineBatching = asset.useSRPBatcher; //設(shè)置資產(chǎn)中的Batcher
4. 設(shè)置每幀shader參數(shù)
SetupPerFrameShaderConstants(); //設(shè)置幀著色器常量
5. 排序相機(jī)
SortCameras(cameras); //排序相機(jī)
6. 遍歷相機(jī)/開始相機(jī)渲染/渲染單個相機(jī)/結(jié)束相機(jī)渲染
foreach (Camera camera in cameras) //遍歷相機(jī){ BeginCameraRendering(renderContext, camera); //開始相機(jī)渲染 #if VISUAL_EFFECT_GRAPH_0_0_1_OR_NEWER //It should be called before culling to prepare material. When there isn't any VisualEffect component, this method has no effect. VFX.VFXManager.PrepareCamera(camera); #endif RenderSingleCamera(renderContext, camera); //渲染單個相機(jī) EndCameraRendering(renderContext, camera); //結(jié)束相機(jī)渲染 }
7. 結(jié)束幀渲染
EndFrameRendering(renderContext, cameras); //結(jié)束幀渲染
渲染單個相機(jī)流程(RenderSingleCamera)
源碼分析
1. 初始化剔除參數(shù)
if (!camera.TryGetCullingParameters(IsStereoEnabled(camera), out var cullingParameters)) //初始化剔除參數(shù)return;
2. 獲取UniversalAdditionCameraData
UniversalAdditionalCameraData additionalCameraData = null;if (camera.cameraType == CameraType.Game || camera.cameraType == CameraType.VR)camera.gameObject.TryGetComponent(out additionalCameraData);
3. 初始化CameraData,InitializeCameraData方法
InitializeCameraData(settings, camera, additionalCameraData, out var cameraData);
4. 設(shè)置每個相機(jī)的shader參數(shù)
SetupPerCameraShaderConstants(cameraData);
SetupPerCameraShaderConstants方法:
//設(shè)置每個相機(jī)的shader參數(shù)static void SetupPerCameraShaderConstants(CameraData cameraData){ Camera camera = cameraData.camera; float scaledCameraWidth = (float)cameraData.camera.pixelWidth * cameraData.renderScale; float scaledCameraHeight = (float)cameraData.camera.pixelHeight * cameraData.renderScale; Shader.SetGlobalVector(PerCameraBuffer._ScaledScreenParams, new Vector4(scaledCameraWidth, scaledCameraHeight, 1.0f + 1.0f / scaledCameraWidth, 1.0f + 1.0f / scaledCameraHeight)); Shader.SetGlobalVector(PerCameraBuffer._WorldSpaceCameraPos, camera.transform.position); float cameraWidth = (float)cameraData.camera.pixelWidth; float cameraHeight = (float)cameraData.camera.pixelHeight; Shader.SetGlobalVector(PerCameraBuffer._ScreenParams, new Vector4(cameraWidth, cameraHeight, 1.0f + 1.0f / cameraWidth, 1.0f + 1.0f / cameraHeight)); Matrix4x4 projMatrix = GL.GetGPUProjectionMatrix(camera.projectionMatrix, false); Matrix4x4 viewMatrix = camera.worldToCameraMatrix; Matrix4x4 viewProjMatrix = projMatrix * viewMatrix; Matrix4x4 invViewProjMatrix = Matrix4x4.Inverse(viewProjMatrix); Shader.SetGlobalMatrix(PerCameraBuffer._InvCameraViewProj, invViewProjMatrix); }
5. 獲取ScriptableRenderer
ScriptableRenderer renderer = (additionalCameraData != null) ? additionalCameraData.scriptableRenderer : settings.scriptableRenderer;
6. 填充剔除參數(shù)、CameraData
renderer.SetupCullingParameters(ref cullingParameters, ref cameraData);
7. 性能采樣
context.ExecuteCommandBuffer(cmd);
8. 編輯器模式下Scene相機(jī)額外顯示UI
#if UNITY_EDITOR// Emit scene view UI 編輯器模式下Scene相機(jī)額外顯示UIif (cameraData.isSceneViewCamera)ScriptableRenderContext.EmitWorldGeometryForSceneView(camer);#endif
9. 剔除
var cullResults = context.Cull(ref cullingParameters); //剔除
10. 根據(jù)管線設(shè)置、CameraData、剔除結(jié)果,初始化渲染數(shù)據(jù)RenderingData
InitializeRenderingData(settings, ref cameraData, ref cullResults, out var renderingData);
11. 使用ScriptableRenderer根據(jù)RenderingData,Setup并Exute渲染上下文
renderer.Setup(context, ref renderingData);renderer.Execute(context, ref renderingData);
12. 釋放CommandBufferPool
CommandBufferPool.Release(cmd);
13. 提交渲染上下文
context.Submit();
- MATLAB使用教程-初步入門大全.PPT 0次下載
- 解析無線電偽碼測目標(biāo)距離系統(tǒng)的設(shè)計 0次下載
- EMI的診斷技巧與案例解析資源下載 45次下載
- 對嵌入式系統(tǒng)的初步認(rèn)識
- 如何解析定時器產(chǎn)生的脈沖信號? 15次下載
- 渲染管線簡單梳理
- URP中如何用多個相機(jī)?
- LWRP渲染流程梳理
- API6D的DBB及DIB型管線閥門結(jié)構(gòu)解析 15次下載
- 如何選擇直管線架空供熱管網(wǎng)中的補償器 3次下載
- 基于方位測量的地下管線探測系統(tǒng)設(shè)計與研究 2次下載
- 大型廠區(qū)內(nèi)的地下管線探測
- 二進(jìn)制無線傳感器網(wǎng)絡(luò)目標(biāo)定位解析算法初步研究
- 地鐵迷流對埋地管線腐蝕及抗蝕方法
- 地下管線的三維可視化研究
- 在NVIDIA Holoscan SDK中使用OpenCV構(gòu)建零拷貝AI傳感器處理管線 347次閱讀
- CPU渲染和GPU渲染優(yōu)劣分析 405次閱讀
- 揭秘:實時渲染、離線渲染、云渲染和混合渲染的區(qū)別 570次閱讀
- 圖形渲染的技術(shù)和原理:探索視覺效果的奇妙世界 683次閱讀
- 三極管線性電源頻域與時域分析 756次閱讀
- 華為云渲染實踐 1135次閱讀
- 3D渲染——光柵化渲染原理解析 1930次閱讀
- HDMI穿管線在預(yù)埋上可避免干擾問題 3569次閱讀
- GPU渲染過程的幾個階段 8467次閱讀
- 一文詳解Unity中渲染順序問題 1.7w次閱讀
- GPU管線各個階段知識點詳細(xì)的分析理解 5324次閱讀
- GPU原理 GPU渲染流程 9300次閱讀
- 正向渲染和延遲渲染彼此之間有什么不同 1.1w次閱讀
- 對正極材料的檢測方法做一個初步的介紹 1w次閱讀
- 什么是強(qiáng)制gpu渲染_強(qiáng)制渲染gpu有什么用 7712次閱讀
下載排行
本周
- 1電子電路原理第七版PDF電子教材免費下載
- 0.00 MB | 1491次下載 | 免費
- 2單片機(jī)典型實例介紹
- 18.19 MB | 95次下載 | 1 積分
- 3S7-200PLC編程實例詳細(xì)資料
- 1.17 MB | 27次下載 | 1 積分
- 4筆記本電腦主板的元件識別和講解說明
- 4.28 MB | 18次下載 | 4 積分
- 5開關(guān)電源原理及各功能電路詳解
- 0.38 MB | 11次下載 | 免費
- 6100W短波放大電路圖
- 0.05 MB | 4次下載 | 3 積分
- 7基于單片機(jī)和 SG3525的程控開關(guān)電源設(shè)計
- 0.23 MB | 4次下載 | 免費
- 8基于AT89C2051/4051單片機(jī)編程器的實驗
- 0.11 MB | 4次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費
- 2PADS 9.0 2009最新版 -下載
- 0.00 MB | 66304次下載 | 免費
- 3protel99下載protel99軟件下載(中文版)
- 0.00 MB | 51209次下載 | 免費
- 4LabView 8.0 專業(yè)版下載 (3CD完整版)
- 0.00 MB | 51043次下載 | 免費
- 5555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33562次下載 | 免費
- 6接口電路圖大全
- 未知 | 30320次下載 | 免費
- 7Multisim 10下載Multisim 10 中文版
- 0.00 MB | 28588次下載 | 免費
- 8開關(guān)電源設(shè)計實例指南
- 未知 | 21539次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935053次下載 | 免費
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537793次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420026次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191183次下載 | 免費
- 7十天學(xué)會AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183277次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138039次下載 | 免費
評論
查看更多