{"id":488,"date":"2026-07-05T23:51:23","date_gmt":"2026-07-05T15:51:23","guid":{"rendered":"http:\/\/chenglixue.top\/?p=488"},"modified":"2026-07-13T00:55:57","modified_gmt":"2026-07-12T16:55:57","slug":"ue5-prepass","status":"publish","type":"post","link":"http:\/\/chenglixue.top\/?p=488","title":{"rendered":"UE5 Prepass \u62c6\u89e3"},"content":{"rendered":"<p><div class=\"has-toc have-toc\"><\/div><\/p>\n<h1>\u4ec0\u4e48\u662f Prepass<\/h1>\n<p><strong>Prepass<\/strong>\uff0c\u5168\u79f0Depth Prepass\uff0c\u4e5f\u5e38\u88ab\u79f0\u4e3a <strong>Early-Z Pass<\/strong><\/p>\n<p>\u5b83\u5728\u5f15\u64ce\u771f\u6b63\u5f00\u59cb\u753b\u753b\uff08Base Pass\uff09\u524d\uff0c\u5148\u8dd1\u7684\u4e00\u904d\u6781\u5176\u7b80\u5316\u7684\u6e32\u67d3\u6d41\u7a0b\u2014\u2014<strong>\u4e0d\u6267\u884c\u590d\u6742\u7684Pixel Shader<\/strong>\uff0c\u53ea\u8dd1Vertex Shader\uff0c\u552f\u4e00\u76ee\u7684\u662f<strong>\u6e32\u67d3\u573a\u666f\u6df1\u5ea6<\/strong><\/p>\n<h1>\u4e3a\u4ec0\u4e48\u9700\u8981\u4ed6<\/h1>\n<p>\u5982\u679c\u6ca1\u6709Prepass\uff0c\u4f1a\u5b58\u5728<strong>Overdraw<\/strong>\u8fd9\u4e00\u5927\u95ee\u9898<\/p>\n<p>\u4f17\u6240\u5468\u77e5\uff0c\u6e32\u67d3\u5c31\u662f\u753b\u753b\uff0c\u753b\u753b\u5982\u679c\u662f\u4ece\u540e\u5f80\u524d\u753b\uff0c\u5f88\u6709\u53ef\u80fd\u5b58\u5728\u5f88\u591a\u4e0d\u9700\u8981\u753b\u7684\u90e8\u5206\u2014\u2014\u88ab\u8986\u76d6\u7684\u90e8\u5206\uff0c\u8fd9\u90e8\u5206\u5c31\u662fOverdraw<\/p>\n<p>\u5982\u679c\u6211\u4eec\u53ef\u4ee5\u4fdd\u8bc1\u662f\u4ece\u524d\u5f80\u540e\u753b\u7684\uff0c\u8df3\u8fc7\u88ab\u906e\u6321\u90e8\u5206\u3002\u8fd9\u6837\u662f\u53ef\u4ee5\u5b8c\u5168\u907f\u514dOverDraw\uff0c\u4f46\u5b58\u5728\u4e00\u4e2a\u95ee\u9898\uff0c\u5982\u4f55\u4fdd\u8bc1\u5462\uff1f\u4e0d\u96be\u60f3\u5230\u5bf9\u76f8\u673a\u5185\u7269\u4f53\u7684z\u503c\u6392\u5e8f\uff0c\u4f46\u4f7f\u7528\u7684\u662fCPU\u6392\u5e8f\uff0c\u65f6\u95f4\u590d\u6742\u5ea6\u4e00\u822c\u662fNlogN\uff0c\u5982\u679c\u573a\u666f\u9876\u70b9\u5c11\uff0c\u8fd8\u9614\u4ee5\uff0c\u4f46\u4e00\u65e6\u591a\u4e86\uff0c\u6027\u80fd\u975e\u5e38\u582a\u5fe7<\/p>\n<p>\u56e0\u6b64\uff0cPrepass\u7531\u6b64\u8bde\u751f\uff0c<strong>\u4f7f\u7528GPU\u63d0\u524d\u7ed8\u5236\u573a\u666f\u7684\u6df1\u5ea6\u56fe\uff0c\u5728\u6e32\u67d3\u65f6\u6bd4\u8f83\u7ed8\u5236\u9876\u70b9\u7684\u6df1\u5ea6\u4e0e\u6df1\u5ea6\u56fe\u7684\u6df1\u5ea6\uff0c\u5982\u679c\u6bd4\u6df1\u5ea6\u56fe\u5927\uff0c\u4e0d\u7ed8\u5236<\/strong>\uff0c\u4ee5\u6b64\u4fdd\u8bc1\u6ca1\u6709\u591a\u4f59\u6d6a\u8d39\u7684draw<\/p>\n<h1>\u5982\u4f55\u5b9e\u73b0<\/h1>\n<p>\u5148\u6e32\u67d3\u573a\u666f\u6df1\u5ea6\u56fe\uff0c\u5728\u540e\u7eedBase Pass\u7ed8\u5236\u65f6\uff0c\u8bbe\u7f6e\u6df1\u5ea6\u6d4b\u8bd5\uff0c\u5927\u4e8e\u7b49\u4e8e\u7684\u5254\u9664\u6389<\/p>\n<h1>UE PrePass<\/h1>\n<p>\u8ba1\u7b97Prepass\u3001Velocity\uff0c\u6bcf\u5e27PrePass\u5f00\u59cb\u524dclear Depth Stencil<\/p>\n<pre><code class=\"line-numbers\">auto RenderPrepassAndVelocity = [&amp;](auto&amp; InViews, auto&amp; InNaniteBasePassVisibility, auto&amp; NaniteRasterResults, auto&amp; PrimaryNaniteViews, FSceneTextures&amp; LocalSceneTextures)\n{\n    FRDGTextureRef FirstStageDepthBuffer = nullptr;\n    {\n        \/\/ Both compute approaches run earlier, so skip clearing stencil here, just load existing.\n        const ERenderTargetLoadAction StencilLoadAction = DepthPass.IsComputeStencilDitherEnabled()\n            ? ERenderTargetLoadAction::ELoad\n            : ERenderTargetLoadAction::EClear;\n\n        const ERenderTargetLoadAction DepthLoadAction = ERenderTargetLoadAction::EClear;\n        AddClearDepthStencilPass(GraphBuilder, LocalSceneTextures.Depth.Target, DepthLoadAction, StencilLoadAction);\n\n        \/\/ Draw the scene pre-pass \/ early z pass, populating the scene depth buffer and HiZ\n        if (bNeedsPrePass)\n        {\n            RenderPrePass(GraphBuilder, InViews, LocalSceneTextures.Depth.Target, InstanceCullingManager, &amp;FirstStageDepthBuffer);\n        }\n        else\n        {\n            \/\/ We didn't do the prepass, but we still want the HMD mask if there is one\n            RenderPrePassHMD(GraphBuilder, InViews, LocalSceneTextures.Depth.Target);\n        }\n\n        \/\/ special pass for DDM_AllOpaqueNoVelocity, which uses the velocity pass to finish the early depth pass write\n        if (bShouldRenderVelocities &amp;&amp; Scene-&gt;EarlyZPassMode == DDM_AllOpaqueNoVelocity &amp;&amp; RendererOutput == ERendererOutput::FinalSceneColor)\n        {\n            \/\/ Render the velocities of movable objects.  Don't bind the velocity render target for custom render passes (it's not used downstream), to avoid needing to clear it again.\n            RenderVelocities(GraphBuilder, InViews, LocalSceneTextures, EVelocityPass::Opaque, bForceVelocityOutput, \/*bBindRenderTarget=*\/ InViews[0].CustomRenderPass == nullptr);\n        }\n    }\n\n    {\n        Scene-&gt;WaitForCacheNaniteMaterialBinsTask();\n\n        if (bNaniteEnabled &amp;&amp; InViews.Num() &gt; 0)\n        {\n            RenderNanite(GraphBuilder, InViews, LocalSceneTextures, bIsEarlyDepthComplete, InNaniteBasePassVisibility, NaniteRasterResults, PrimaryNaniteViews, FirstStageDepthBuffer);\n        }\n    }\n\n    if (FirstStageDepthBuffer)\n    {\n        LocalSceneTextures.PartialDepth = FirstStageDepthBuffer;\n        AddResolveSceneDepthPass(GraphBuilder, InViews, LocalSceneTextures.PartialDepth);\n    }\n    else\n    {\n        \/\/ Setup default partial depth to be scene depth so that it also works on transparent emitter when partial depth has not been generated.\n        LocalSceneTextures.PartialDepth = LocalSceneTextures.Depth;\n    }\n    LocalSceneTextures.SetupMode = ESceneTextureSetupMode::SceneDepth;\n    LocalSceneTextures.UniformBuffer = CreateSceneTextureUniformBuffer(GraphBuilder, &amp;LocalSceneTextures, FeatureLevel, LocalSceneTextures.SetupMode);\n\n    AddResolveSceneDepthPass(GraphBuilder, InViews, LocalSceneTextures.Depth);\n};\n<\/code><\/pre>\n<p>UEPrePass\u4e0d\u4ec5\u4ec5\u662f\u7ed8\u5236Depth\uff0c\u603b\u5171\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\uff1a<\/p>\n<ul>\n<li>\u7ed8\u5236Depth\u56fe<\/li>\n<\/ul>\n<h2>Pre Depth<\/h2>\n<h3>\u54ea\u4e9b\u7269\u4f53\u4f1a\u8d70Pre Depth<\/h3>\n<ul>\n<li>Opaque\uff1a\u53ea\u5305\u542bPosition\u7684VS\uff0c\u6ca1\u6709PS<\/li>\n<li>Masked\uff1a\u5305\u542bPosition\u3001uv\u7b49\u7684VS\uff0c\u6709PS<\/li>\n<\/ul>\n<h3>Render Target<\/h3>\n<ul>\n<li>Color RT\uff1a\u65e0<\/li>\n<li>Depth RT\uff1aSceneDepthTexture\n<ul>\n<li>Stencil\uff1a\u6709<\/li>\n<\/ul>\n<\/li>\n<li>Velocity RT\uff1a\u65e0<\/li>\n<\/ul>\n<h3>CPU\u7aef<\/h3>\n<h4>EDepthDrawingMode<\/h4>\n<ul>\n<li>\u4ec0\u4e48\u662fEDepthDrawingMode\n<p>EarlyZPassMode\u662f\u4e00\u4e2aenum\uff0c\u51b3\u5b9a PrePass \u753b\u54ea\u4e9b\u7269\u4f53\u3001\u662f\u5426\u5199 Velocity\u3001Velocity Pass \u4f55\u65f6\u8dd1\u3001\u6df1\u5ea6\u8bfb\u5199\u6743\u9650\u600e\u4e48\u8bbe\u3002\u5b58\u5728\u7684\u76ee\u7684\u5c31\u662f\u5728 PrePass \u5f00\u9500\u3001BasePass Overdraw \u8282\u7701\u3001 Velocity \u7cbe\u5ea6 \u4e4b\u95f4\u505a\u6743\u8861<\/p>\n<ul>\n<li>\u5b9a\u4e49<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">enum EDepthDrawingMode\n{\n\/\/ \u4e0d\u505a Early-Z \nDDM_None            = 0,\n\/\/ \u53ea\u6709 Opaque \nDDM_NonMaskedOnly   = 1,\n\/\/ Opaque and masked materials, but no objects with bUseAsOccluder disabled\nDDM_AllOccluders    = 2,\n\/\/ \u6240\u6709 Opaque + Masked \nDDM_AllOpaque       = 3,\n\/\/ Masked materials only\nDDM_MaskedOnly = 4,\n\/\/ \u6240\u6709 Opaque + Masked\uff0c\u4f46\u4e0d\u5199 Velocity\nDDM_AllOpaqueNoVelocity = 5,\n};\n<\/code><\/pre>\n<\/li>\n<li>\u4e3a\u4ec0\u4e48\u9700\u8981\u5b83\n<p>\u4e3a\u4e86\u4f18\u96c5\u5904\u7406\u4e0a\u8ff0\u6ce8\u91ca\u4e2d\u63d0\u5230\u7684\u51e0\u79cd\u60c5\u51b5\u2014\u2014\u51e0\u79cd\u4e0d\u540c\u7684\u573a\u666f\uff0c\u4e14EDepthDrawingMode\u4e0d\u4ec5\u4ec5\u5728Pre Pass\uff0c\u5728Velocity Pass\u4e5f\u9700\u8981<\/p>\n<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>\u573a\u666f\u7279\u5f81<\/th>\n<th>\u66f4\u5408\u9002\u6a21\u5f0f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u590d\u6742\u5ba4\u5185\u3001\u9ad8 Overdraw<\/td>\n<td>DDM_AllOpaqueNoVelocity \u6216 DDM_AllOpaque<\/td>\n<\/tr>\n<tr>\n<td>Masked \u690d\u88ab\u6781\u591a\u3001\u4e09\u89d2\u5f62\u5de8\u5927<\/td>\n<td>DDM_NonMaskedOnly(\u770bBase Pass\u5f00\u9500\uff0c\u82e5\u5f00\u9500\u9ad8\u4e8ePrepass PS\uff0c\u5c31\u8fd8\u662fDDM_AllOpaqueNoVelocity )<\/td>\n<\/tr>\n<tr>\n<td>\u7b80\u5355\u573a\u666f\u3001Draw \u5f88\u5c11<\/td>\n<td>DDM_None<\/td>\n<\/tr>\n<tr>\n<td>\u91cd\u5ea6 TSR\/TAA\uff0c\u52a8\u6001\u7269\u4f53\u591a<\/td>\n<td>DDM_AllOpaqueNoVelocity<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ul>\n<li>\u89e3\u6790\u5404Mode<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>\u4f5c\u7528<\/th>\n<th>\u4f18\u70b9<\/th>\n<th>\u7f3a\u70b9<\/th>\n<th>\u9002\u7528\u573a\u666f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>DDM_None<\/td>\n<td>\u65e0 PrePass \u2192 BasePass \u81ea\u5df1\u5199\u6df1\u5ea6 + GBuffer<\/td>\n<td>\u5c11\u4e00\u904d\u51e0\u4f55\u7ed8\u5236<br \/>\u5b9e\u73b0\u7b80\u5355<\/td>\n<td>BasePass Overdraw \u6700\u4e25\u91cd <br \/> \u590d\u6742\u573a\u666f GPU \u538b\u529b\u5927<\/td>\n<td>\u7b80\u5355\u573a\u666f\u3001\u79fb\u52a8\u7aef\u90e8\u5206\u8def\u5f84\u3001\u4e0d\u9700\u8981 Early-Z<\/td>\n<\/tr>\n<tr>\n<td>DDM_NonMaskedOnly<\/td>\n<td>PrePass\uff1a\u53ea\u753b Opaque<br \/>Masked\uff1a\u7559\u5230 BasePass \u518d clip<br \/>BasePass\uff1aZTest = Equal(Opaque \u8986\u76d6\u533a)<\/td>\n<td>PrePass \u66f4\u5feb\uff08Masked \u591a\u3001\u4e09\u89d2\u5f62\u591a<br \/>\u907f\u514d Masked \u5728 PrePass \u91cc\u5927\u91cf clip<\/td>\n<td>Masked \u591a\u65f6\u5149\u6805\u5316\u5f00\u9500\u540e\u79fb\u5230 BasePass<br \/> \u690d\u88ab\u573a\u666f\u4e0d\u5212\u7b97<\/td>\n<td>Masked \u5c11\u3001Opaque \u4e3a\u4e3b\u7684\u573a<\/td>\n<\/tr>\n<tr>\n<td>DDM_AllOpaque<\/td>\n<td>PrePass\uff1aOpaque + Masked\uff0c\u540c\u65f6\u5199 Velocity<br \/>BasePass\uff1aZTest = Equal<br \/>Velocity Pass\uff1a\u901a\u5e38\u53ea\u8bfb\u6df1\u5ea6\uff08DepthRead\uff09<\/td>\n<td>\u6df1\u5ea6\u8986\u76d6\u6700\u5168<br \/> PrePass \u5199 Velocity<\/td>\n<td>PrePass \u66f4\u91cd<br \/>\u5e26\u5bbd\u548c PS \u5f00\u9500\u66f4\u5927<\/td>\n<td>\u9700\u8981 PrePass \u5c31\u8f93\u51fa Velocity<\/td>\n<\/tr>\n<tr>\n<td>DDM_AllOpaqueNoVelocity<\/td>\n<td>PrePass\uff1aOpaque + Masked\uff0c\u53ea\u5199 Depth\uff0c\u4e0d\u5199 Velocity<br \/>Velocity Pass\uff08BasePass \u524d\uff09\uff1a\u52a8\u6001\u7269\u4f53\u5199 Velocity + \u4fee\u6b63\u6df1\u5ea6<br \/>BasePass\uff1aZTest = Equal<\/td>\n<td>PrePass \u6781\u5feb\uff08\u4e0d\u7ed1 Velocity RT\uff09<br \/>BasePass Overdraw \u5927\u5e45\u4e0b\u964d<\/td>\n<td>\u7ba1\u7ebf\u66f4\u590d\u6742\uff0c\u591a\u4e00\u6b21 Velocity Pass <\/td>\n<td>PC \u5ef6\u8fdf\u6e32\u67d3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ul>\n<li>\n<p>\u6574\u4f53\u6d41\u7a0b<\/p>\n<p><img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic1.imgdb.cn\/item\/6a3fe0a02546dff76d1f0d28.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic1.imgdb.cn\/item\/6a3fe0a02546dff76d1f0d28.png\" alt=\"\" \/><\/p><\/noscript>\n<\/li>\n<\/ul>\n<h4>\u9010View<\/h4>\n<ul>\n<li>\u505a\u4e86\u4ec0\u4e48\n<ul>\n<li>\u8bbe\u5b9a\u989c\u8272\u5199\u5165\u3001\u6df1\u5ea6\u6a21\u677f\u6d4b\u8bd5<\/li>\n<li>\u7ed1\u5b9a\u5e38\u91cf\u7f13\u51b2\u533a<\/li>\n<li>\u8bbe\u7f6eviewport\uff0c\u5e76Draw<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">for (int32 ViewIndex = 0; ViewIndex &lt; InViews.Num(); ++ViewIndex)\n{\n    FViewInfo&amp; View = InViews[ViewIndex];\n\n    FMeshPassProcessorRenderState DrawRenderState;\n    SetupDepthPassState(DrawRenderState);\n\n    const bool bShouldRenderView = View.ShouldRenderView() &amp;&amp; (bSecondStageDepthPass ? View.bUsesSecondStageDepthPass : true);\n    if (bShouldRenderView)\n    {\n        FDepthPassParameters* PassParameters = GetDepthPassParameters(GraphBuilder, View, SceneDepthTexture);\n\n        auto* Pass = View.ParallelMeshDrawCommandPasses[DepthMeshPass]\n        Pass-&gt;BuildRenderingCommands(GraphBuilder, Scene-&gt;GPUScene, PassParameters-&gt;InstanceCullingDrawParams);\n\n        if(bParallelDepthPass)\n        {\n            GraphBuilder.AddDispatchPass(\n    bSecondStageDepthPass ? RDG_EVENT_NAME(\"SecondStageDepthPassParallel\") : RDG_EVENT_NAME(\"DepthPassParallel\"),\n    PassParameters,\n    ERDGPassFlags::Raster,\n    [Pass, PassParameters, DepthMeshPass](FRDGDispatchPassBuilder&amp; DispatchPassBuilder)\n{\n    Pass-&gt;Dispatch(DispatchPassBuilder, &amp;PassParameters-&gt;InstanceCullingDrawParams);\n});\n        }\n        else\n        {\n            GraphBuilder.AddPass(\n    bSecondStageDepthPass ? RDG_EVENT_NAME(\"SecondStageDepthPass\") : RDG_EVENT_NAME(\"DepthPass\"),\n    PassParameters,\n    ERDGPassFlags::Raster,\n    [&amp;View, Pass, PassParameters, DepthMeshPass](FRDGAsyncTask, FRHICommandList&amp; RHICmdList)\n{\n    SetStereoViewport(RHICmdList, View, 1.0f);\n    Pass-&gt;Draw(RHICmdList, &amp;PassParameters-&gt;InstanceCullingDrawParams);\n});\n        }\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\n<p>\u5173\u95ed\u989c\u8272\u5199\u5165\uff0c\u5f00\u542f\u6df1\u5ea6\u6d4b\u8bd5 + \u6df1\u5ea6\u5199\u5165<\/p>\n<pre><code class=\"line-numbers\">void SetupDepthPassState(FMeshPassProcessorRenderState&amp; DrawRenderState)\n{\n\/\/ Disable color writes, enable depth tests and writes.\nDrawRenderState.SetBlendState(TStaticBlendState&lt;CW_NONE&gt;::GetRHI());\nDrawRenderState.SetDepthStencilState(TStaticDepthStencilState&lt;true, CF_DepthNearOrEqual&gt;::GetRHI());\n}\n<\/code><\/pre>\n<ul>\n<li>\u6df1\u5ea6\u6d4b\u8bd5\uff1a LessEqual<\/li>\n<\/ul>\n<\/li>\n<li>\u83b7\u53d6Pass Constant Buffer\n<pre><code class=\"line-numbers\">BEGIN_SHADER_PARAMETER_STRUCT(FDepthPassParameters, )\nSHADER_PARAMETER_STRUCT_INCLUDE(FViewShaderParameters, View)\nSHADER_PARAMETER_STRUCT_INCLUDE(FInstanceCullingDrawParams, InstanceCullingDrawParams)\nRENDER_TARGET_BINDING_SLOTS()\nEND_SHADER_PARAMETER_STRUCT()\n<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230Pre Pass\u7684Pass Parameter\u5305\u542b\uff1a<\/p>\n<ul>\n<li>View<\/li>\n<li>InstanceCullingDrawParams<\/li>\n<li>Render Target<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">FDepthPassParameters* GetDepthPassParameters(FRDGBuilder&amp; GraphBuilder, const FViewInfo&amp; View, FRDGTextureRef DepthTexture)\n{\nauto* PassParameters = GraphBuilder.AllocParameters&lt;FDepthPassParameters&gt;();\nPassParameters-&gt;View = View.GetShaderParameters();\nPassParameters-&gt;RenderTargets.DepthStencil = FDepthStencilBinding(DepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthWrite_StencilWrite);\nreturn PassParameters;\n}\n<\/code><\/pre>\n<p>\u7ed1\u5b9aView\u3001RenderTargets.DepthStencil\uff0c\u65e0Color RT<\/p>\n<\/li>\n<li>\n<p>\u83b7\u53d6Mesh Draw Command<\/p>\n<pre><code class=\"line-numbers\">Pass-&gt;BuildRenderingCommands(GraphBuilder, Scene-&gt;GPUScene, PassParameters-&gt;InstanceCullingDrawParams);\n<\/code><\/pre>\n<p>UE5\u7edf\u4e00\u5728 InitViews()\u521d\u59cb\u5316\u65f6\uff0c\u5bf9\u6240\u6709PassMeshProcessor AddMeshBatch Process\uff0c\u5e76\u5b58\u50a8\uff0c\u5728render \u5bf9\u5e94pass\u65f6\uff0c\u518d\u4f7f\u7528BuildRenderingCommands\u62ff\u5230\u53ef\u4f7f\u7528\u7684Mesh Draw Command<\/p>\n<ul>\n<li>AddMeshBatch\uff1a\u6ee1\u8db3\u4e00\u5b9a\u6761\u4ef6\u7684\u624d\u4f1a\u6267\u884c\u540e\u7eedPrePass<\/li>\n<\/ul>\n<\/li>\n<li>\u8bbe\u7f6ePass\uff1a\u8bbe\u7f6e\u89c6\u53e3\uff0c\u5e76\u7ed8\u5236\n<pre><code class=\"line-numbers\">GraphBuilder.AddDispatchPass(\n  bSecondStageDepthPass ? RDG_EVENT_NAME(\"SecondStageDepthPassParallel\") : RDG_EVENT_NAME(\"DepthPassParallel\"),\n  PassParameters,\n  ERDGPassFlags::Raster,\n  [Pass, PassParameters, DepthMeshPass](FRDGDispatchPassBuilder&amp; DispatchPassBuilder)\n{\n  Pass-&gt;Dispatch(DispatchPassBuilder, &amp;PassParameters-&gt;InstanceCullingDrawParams);\n});\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h4>GPU Draw\u8bbe\u5b9a<\/h4>\n<ul>\n<li>\u7ed1\u5b9a\u6e32\u67d3\u72b6\u6001\n<ul>\n<li>\u83b7\u53d6DepthPassShader<\/p>\n<\/li>\n<li>\n<p>\u53d6 Vertex Factory<\/p>\n<p>\u9876\u70b9\u5de5\u5382\u51b3\u5b9a\uff1a\u9876\u70b9\u4ece\u54ea\u6765\u3001\u600e\u4e48\u8499\u76ae\u3001\u600e\u4e48\u5b9e\u4f8b\u5316<\/p>\n<\/li>\n<\/ul>\n<p>DepthPass\u9700\u8981\u5224\u65admaterial\u6750\u8d28\u662f\u5426\u662fopaque\uff0c\u6765\u5224\u65ad\u662f\u5426\u9700\u8981\u7528\u5230pixel shader<\/p>\n<pre><code class=\"line-numbers\">if (!GetDepthPassShaders&lt;bPositionOnly&gt;(\n    MaterialResource,\n    VertexFactory-&gt;GetType(),\n    FeatureLevel,\n    MaterialResource.MaterialUsesPixelDepthOffset_RenderThread(),\n    DepthPassShaders.VertexShader,\n    DepthPassShaders.PixelShader,\n    ShaderPipeline))\n{\n    return false;\n}\n<\/code><\/pre>\n<p>TMeshProcessorShaders\uff1a\u628a VS+PS \u6253\u5305\uff0c\u540e\u9762\u4ea4\u7ed9 BuildMeshDrawCommands<\/p>\n<ul>\n<li>\u83b7\u53d6shader\u7684vs\u3001ps\u5b57\u6bb5\u7684bytecode\n<pre><code class=\"line-numbers\">FMaterialShaderTypes ShaderTypes;\nShaderTypes.AddShaderType&lt;TDepthOnlyVS&lt;bPositionOnly&gt;&gt;();\n\nShaderTypes.AddShaderType&lt;FDepthOnlyPS&gt;();\n<\/code><\/pre>\n<p>FMaterialShaderTypes\uff1a\u5411\u6750\u8d28\u7cfb\u7edf\u58f0\u660e\u8981\u54ea\u4e9bShader\u7c7b\u578b\uff0cDepth Pass \u81f3\u5c11\u8981\u6709 VS<\/p>\n<\/li>\n<li>\n<p>\u83b7\u53d6PipelineType<\/p>\n<pre><code class=\"line-numbers\">if (bPositionOnly)\n{\n  ShaderTypes.PipelineType = &amp;DepthPosOnlyNoPixelPipeline;\n}\nelse\n{\n  const bool bVFTypeSupportsNullPixelShader = VertexFactoryType-&gt;SupportsNullPixelShader();\n  const bool bNeedsPixelShader = !Material.WritesEveryPixel(false, bVFTypeSupportsNullPixelShader) || bMaterialUsesPixelDepthOffset || Material.IsTranslucencyWritingCustomDepth();\n  if (bNeedsPixelShader)\n  {\n      ShaderTypes.AddShaderType&lt;FDepthOnlyPS&gt;();\n      ShaderTypes.PipelineType = &amp;DepthPipeline;\n  }\n  else\n  {\n      ShaderTypes.PipelineType = &amp;DepthNoPixelPipeline;\n  }\n}\n<\/code><\/pre>\n<ul>\n<li>bPositionOnly \u4e3a true\uff1a\u53ea\u6709 VS\u3001\u6ca1\u6709 PS \u7684PipelineType<\/li>\n<li>bPositionOnly \u4e3a false<\/li>\n<li>\u770b VF \u662f\u5426\u652f\u6301 \u7a7a\u50cf\u7d20\u7740\u8272\u5668<\/li>\n<li>\u662f\u5426PS\u5e76\u4e0d\u662f\u6bcfpixel\u5199\u5165(\u5982masked)\u3001\u4f7f\u7528PDO\u3001\u662f\u5426\u534a\u900f\u660e\u81ea\u5b9a\u4e49Depth<\/li>\n<li>\u8981 PS \u2192 \u52a0\u5165 FDepthOnlyPS\uff0c\u7ba1\u7ebf\u7c7b\u578b DepthPipeline\uff08VS + PS)<\/li>\n<li>Opaque \u4e14 \u4e0d\u5199 PDO\u3001\u65e0\u7279\u6b8a CustomDepth \u2192 \u4e0d AddShaderType<FDepthOnlyPS>\uff0c\u7528 DepthNoPixelPipeline\uff08\u4ec5 VS\uff0c\u6700\u5feb\uff09<\/li>\n<\/ul>\n<\/li>\n<li>\u6839\u636e Vertex Factory\u3001Shader Type\u4eceShader\u53d8\u4f53\u67e5\u627eShader\u3001ShaderPipeline(\u6839\u636ePipelineType\u67e5\u627e)\n<pre><code class=\"line-numbers\">FMaterialShaders Shaders;\nif (!Material.TryGetShaders(ShaderTypes, VertexFactoryType, Shaders))\n{\n  return false;\n}\n\nShaders.TryGetPipeline(ShaderPipeline);\nShaders.TryGetVertexShader(VertexShader);\nShaders.TryGetPixelShader(PixelShader);\n<\/code><\/pre>\n<p>ShaderPipeline\u5f97\u5230\u7684Shader\u6307\u9488\u662f\u4e2a\u6cdb\u578b\uff0c\u540e\u7eed\u901a\u8fc7TryGetVertexShader\u8f6c\u6362\u6210\u6307\u5b9a\u7c7b\u578b\uff08\u6cdb\u578b\u52a0\u8f7dShader\u62ff\u5230shader\u53cd\u5c04\u4fe1\u606f\u2014\u2014\u7ed1\u5b9a\u7684SRV\u3001UAV\u3001CBV\u5177\u4f53\u4f4d\u7f6e\u4e0e\u987a\u5e8f\uff0c\u7531\u4e8e\u4e0d\u6b62\u4e00\u79cd\uff0c\u56e0\u6b64UE\u4e3ashader\u8bbe\u8ba1\u4e86\u6cdb\u578b\uff0c\u901a\u8fc7TryGetVertexShader\u7ed1\u5b9a\u8d44\u6e90\u5730\u5740\uff09<\/p>\n<\/li>\n<li>\n<p>\u8bbe\u7f6eStencil<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">if (!bDitheredLODFadingOutMaskPass &amp;&amp; !bShadowProjection)\n{\n    TOptional&lt;uint32&gt; DitheringFlag = GetOptionalDitheringFlag(ViewIfDynamicMeshCommand, MeshBatch, StaticMeshId);\n    if (DitheringFlag.IsSet())\n{\n    DrawRenderState.SetDepthStencilState(GetDitheredLODTransitionDepthStencilState());\n    DrawRenderState.SetStencilRef(DitheringFlag.GetValue());\n}\n}\n<\/code><\/pre>\n<p>\u975eDitherMask \u3001 \u975eShadow\u3001DitheringFlag\u6709\u503c(\u82e5Mesh\u5904\u4e8eLOD\u6de1\u5165\u6de1\u51fa\uff0c\u5219\u6709\u503c)\uff0c\u5219\u8bbe\u7f6eDepth Stencil\u6d4b\u8bd5<\/p>\n<ul>\n<li>\u7ed1\u5b9aUniform Buffer<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">FMeshMaterialShaderElementData ShaderElementData;\nShaderElementData.InitializeMeshMaterialData(ViewIfDynamicMeshCommand, PrimitiveSceneProxy, MeshBatch, StaticMeshId, true);\n\nvoid FMeshMaterialShaderElementData::InitializeMeshMaterialData()\n{\n    FadeUniformBuffer = GDistanceCullFadedInUniformBuffer.GetUniformBufferRHI();\n    DitherUniformBuffer = GDitherFadedInUniformBuffer.GetUniformBufferRHI();\n}\n\nvoid FMeshMaterialShaderElementData::InitializeMeshMaterialData(const FSceneView* SceneView, const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy, int32 sStaticMeshId, bool bDitheredLODTransition, bool bAllowStencilDither)\n{\n    InitializeMeshMaterialData();\n\n    if (SceneView)\n    {\n        checkSlow(SceneView-&gt;bIsViewInfo);\n        const FViewInfo* ViewInfo = (FViewInfo*)SceneView;\n\n        if (StaticMeshId &gt;= 0 &amp;&amp; bDitheredLODTransition &amp;&amp; !(bAllowStencilDither &amp;&amp; ViewInfo-&gt;bAllowStencilDither))\n        {\n            if (ViewInfo-&gt;StaticMeshFadeOutDitheredLODMap[StaticMeshId])\n            {\n                DitherUniformBuffer = ViewInfo-&gt;DitherFadeOutUniformBuffer;\n            }\n            else if (ViewInfo-&gt;StaticMeshFadeInDitheredLODMap[StaticMeshId])\n            {\n                DitherUniformBuffer = ViewInfo-&gt;DitherFadeInUniformBuffer;\n            }\n        }\n\n        if (PrimitiveSceneProxy)\n        {\n            int32 const PrimitiveIndex = PrimitiveSceneProxy-&gt;GetPrimitiveSceneInfo()-&gt;GetIndex();\n\n            if (ViewInfo-&gt;PrimitiveFadeUniformBufferMap.IsValidIndex(PrimitiveIndex) &amp;&amp; ViewInfo-&gt;PrimitiveFadeUniformBufferMap[PrimitiveIndex])\n            {\n                FadeUniformBuffer = ViewInfo-&gt;PrimitiveFadeUniformBuffers[PrimitiveIndex];\n            }\n        }\n    }\n}\n<\/code><\/pre>\n<p>\u7ed1\u5b9aFade\u3001Dither Buffer\uff0c\u7528\u4e8e\u5904\u7406LOD \u6296\u52a8\u6e10\u53d8\u3001\u8ddd\u79bb\u6e10\u53d8<\/p>\n<ul>\n<li>Depth\u6392\u5e8f<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">const bool bIsMasked = IsMaskedBlendMode(MaterialResource);\nconst FMeshDrawCommandSortKey SortKey = CalculateDepthPassMeshStaticSortKey(bIsMasked, DepthPassShaders.VertexShader.GetShader(), DepthPassShaders.PixelShader.GetShader());\n<\/code><\/pre>\n<pre><code class=\"line-numbers\">FMeshDrawCommandSortKey CalculateDepthPassMeshStaticSortKey(bool bIsMasked, const FMeshMaterialShader* VertexShader, const FMeshMaterialShader* PixelShader)\n{\n    FMeshDrawCommandSortKey SortKey;\n    if (GEarlyZSortMasked)\n    {\n        SortKey.BasePass.VertexShaderHash = (VertexShader ? VertexShader-&gt;GetSortKey() : 0) &amp; 0xFFFF;\n        SortKey.BasePass.PixelShaderHash = PixelShader ? PixelShader-&gt;GetSortKey() : 0;\n        SortKey.BasePass.Masked = bIsMasked ? 1 : 0;\n    }\n    else\n    {\n        SortKey.Generic.VertexShaderHash = VertexShader ? VertexShader-&gt;GetSortKey() : 0;\n        SortKey.Generic.PixelShaderHash = PixelShader ? PixelShader-&gt;GetSortKey() : 0;\n    }\n\n    return SortKey;\n}\n<\/code><\/pre>\n<ul>\n<li>\u5728\u6392\u5e8f\u65f6\uff0c\u9700\u8981\u8003\u8651opaque\u3001masked\u4e24\u79cd\u60c5\u51b5\n<ul>\n<li>\u5f53\u573a\u666f\u91cc\u6709\u8bb8\u591amasked\u7269\u4f53\uff0c\u4e14\u4ed6\u4eec\u4e92\u76f8\u8fd8\u6709\u5927\u91cf\u906e\u6321\uff0c\u6b64\u65f6\u62c6\u5206opaque\u3001masked\uff0c\u5148\u6392opaque\u518d\u6392masked\u53ef\u4ee5\u8282\u7701\u4e0d\u5c11\u6027\u80fd\u3002\u56e0\u4e3aopaque\u4e0d\u9700\u8981fragment shader\uff0c\u800cmasked\u9700\u8981\uff0c\u8fd9\u6837\u53ef\u4ee5\u5c3d\u91cf\u8ba9masked\u5c11\u753b<\/li>\n<li>\u5f53\u573a\u666f\u57fa\u672c\u6ca1\u6709masked\u7269\u4f53\uff0c\u6b64\u65f6\u5c31\u65e0\u9700\u62c6\u5206\u4e86\uff0c\u6839\u636eshader\u5206\u7ec4\u5373\u53ef<\/li>\n<\/ul>\n<\/li>\n<li>\u6784\u5efaMeshDrawCommand(\u5305\u542b\u8bb8\u591a\u6e32\u67d3\u72b6\u6001\u53c2\u6570)<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">BuildMeshDrawCommands(\n    MeshBatch,\n    BatchElementMask,\n    PrimitiveSceneProxy,\n    MaterialRenderProxy,\n    MaterialResource,\n    DrawRenderState,\n    DepthPassShaders,\n    MeshFillMode,\n    MeshCullMode,\n    SortKey,\n    bPositionOnly ? EMeshPassFeatures::PositionOnly : EMeshPassFeatures::Default,\n    ShaderElementData);\n<\/code><\/pre>\n<ul>\n<li>bPositionOnly ? EMeshPassFeatures::PositionOnly : EMeshPassFeatures::Default\n<ul>\n<li>bPositionOnly \u4e3atrue\uff1astruct VSInput\u53ea\u5305\u542bPosition<\/li>\n<li>bPositionOnly \u4e3afalse\uff1astruct VSInput\u4e0d\u4ec5\u5305\u542bPosition\uff0c\u4e5f\u5305\u542b\u5176\u4ed6\u6570\u636e<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u7ed1\u5b9a\u7ec4\u88c5shader\u7b97\u6cd5<\/p>\n<pre><code class=\"line-numbers\">IMPLEMENT_MATERIAL_SHADER_TYPE(template&lt;&gt;,TDepthOnlyVS&lt;true&gt;,TEXT(\"\/Engine\/Private\/PositionOnlyDepthVertexShader.usf\"),TEXT(\"Main\"),SF_Vertex);\nIMPLEMENT_MATERIAL_SHADER_TYPE(template&lt;&gt;,TDepthOnlyVS&lt;false&gt;,TEXT(\"\/Engine\/Private\/DepthOnlyVertexShader.usf\"),TEXT(\"Main\"),SF_Vertex);\n\nIMPLEMENT_MATERIAL_SHADER_TYPE(,FDepthOnlyPS,TEXT(\"\/Engine\/Private\/DepthOnlyPixelShader.usf\"),TEXT(\"Main\"),SF_Pixel);\n\nIMPLEMENT_SHADERPIPELINE_TYPE_VS(DepthNoPixelPipeline, TDepthOnlyVS&lt;false&gt;, true);\nIMPLEMENT_SHADERPIPELINE_TYPE_VS(DepthPosOnlyNoPixelPipeline, TDepthOnlyVS&lt;true&gt;, true);\nIMPLEMENT_SHADERPIPELINE_TYPE_VSPS(DepthPipeline, TDepthOnlyVS&lt;false&gt;, FDepthOnlyPS, true);\n<\/code><\/pre>\n<ul>\n<li>\u7ed1\u5b9a\u4e24\u4e2aVS Shader<\/li>\n<\/ul>\n<pre><code class=\"line-numbers\">template &lt;bool bUsePositionOnlyStream&gt;\nclass TDepthOnlyVS : public FMeshMaterialShader\n{\n    DECLARE_SHADER_TYPE(TDepthOnlyVS,MeshMaterial);\nprotected:\n\n    TDepthOnlyVS() {}\n\n    TDepthOnlyVS(const FMeshMaterialShaderType::CompiledShaderInitializerType&amp; Initializer) :\n        FMeshMaterialShader(Initializer)\n    {}\n\npublic:\n\n    static bool ShouldCompilePermutation(const FMeshMaterialShaderPermutationParameters&amp; Parameters)\n    {\n        \/\/ Only the local vertex factory supports the position-only stream\n        if (bUsePositionOnlyStream)\n        {\n            return Parameters.VertexFactoryType-&gt;SupportsPositionOnly() &amp;&amp; Parameters.MaterialParameters.bIsSpecialEngineMaterial;\n        }\n\n        if (IsTranslucentBlendMode(Parameters.MaterialParameters))\n        {\n            return Parameters.MaterialParameters.bIsTranslucencyWritingCustomDepth;\n        }\n\n        \/\/ Only compile for the default material and masked materials\n        return (\n            Parameters.MaterialParameters.bIsSpecialEngineMaterial ||\n            !Parameters.MaterialParameters.bWritesEveryPixel ||\n            Parameters.MaterialParameters.bMaterialMayModifyMeshPosition)\n            &amp;&amp; !Parameters.VertexFactoryType-&gt;SupportsNaniteRendering();\n    }\n<\/code><\/pre>\n<ul>\n<li>ShouldCompilePermutation\uff1a\u5224\u65ad\u975eopaque\u7684\u5176\u4ed6\u6750\u8d28\u7684shader\u662f\u5426\u7f16\u8bd1\u6210\u4e8c\u8fdb\u5236\n<ul>\n<li>bUsePositionOnlyStream\u4e3atrue\uff1a\u82e5\u652f\u6301PositionOnly\u4e5f\u662f\u9ed8\u8ba4\u6750\u8d28\uff08\u5f15\u64ce\u9ed8\u8ba4\u7684\u7070\u767d\u76f8\u95f4\u7684\u68cb\u76d8\u683c\uff09\uff0c\u5219\u7f16\u8bd1<\/li>\n<li>bUsePositionOnlyStream\u4e3afalse<\/li>\n<li>\u5224\u65ad\u662f\u4e0d\u662f\u534a\u900f\u660e\u6750\u8d28\uff0c\u662f\u4e14\u542f\u7528\u4e86\u534a\u900f\u660e\u6df1\u5ea6\u5199\u5165\uff0c\u5219\u7f16\u8bd1<\/li>\n<li>\u6700\u540e\u515c\u5e95\uff0c\u770b\u662f\u4e0d\u662f\u9ed8\u8ba4\u6750\u8d28\u6216Masked\u6750\u8d28\u6216\u652f\u6301WPO\u7684\u6750\u8d28\uff0c\u4e14\u4e0d\u652f\u6301Nanite<\/li>\n<\/ul>\n<\/li>\n<li>Opaque VS Shader<br \/>\n\u4f60\u53ef\u80fd\u4f1a\u7591\u60d1\u8fd9\u91cc\u7ed1\u5b9a\u7684\u4e24\u4e2aVS Shader\u90fd\u4e0d\u662f\u7528\u4e8eopaque material\u7684\uff0c\u90a3opaque \u662f\u5728\u54ea\u5904\u7406\u7684\uff0c\u5982\u4f55\u5904\u7406\u7684\u5462\uff1f<\/p>\n<\/li>\n<\/ul>\n<p>\u771f\u76f8\u662f\uff0c\u5bf9\u4e8eOpaque Material\uff0cUE\u76f4\u63a5\u4f7f\u7528\u9ed8\u8ba4\u6750\u8d28\u66ff\u6362<\/p>\n<pre><code class=\"line-numbers\">bool FDepthPassMeshProcessor::ShouldRender(const FMaterial&amp; Material, bool bMaterialModifiesMeshPosition, bool bSupportPositionOnlyStream, bool bVFTypeSupportsNullPixelShader, bool&amp; bUseDefaultMaterial, bool&amp; bPositionOnly)\n{\n    bool bShouldRender = false;\n    bUseDefaultMaterial = false;\n    bPositionOnly = false;\n\n    if (FeatureLevel == ERHIFeatureLevel::ES3_1 &amp;&amp; EarlyZPassMode == DDM_None)\n    {\n        \/\/ Do not cache MDC and do not pre-cache PSOs for a depth pass if it's never going to be used on mobile platforms\n        return false;\n    }\n\n    if (IsOpaqueBlendMode(Material)\n        &amp;&amp; EarlyZPassMode != DDM_MaskedOnly\n        &amp;&amp; bSupportPositionOnlyStream\n        &amp;&amp; !bMaterialModifiesMeshPosition\n        &amp;&amp; Material.WritesEveryPixel(false, bVFTypeSupportsNullPixelShader))\n    {\n        bShouldRender = true;\n        bUseDefaultMaterial = true;\n        bPositionOnly = true;\n    }\n    else\n    {\n        \/\/ still possible to use default material\n        const bool bMaterialMasked = !Material.WritesEveryPixel(false, bVFTypeSupportsNullPixelShader) || Material.IsTranslucencyWritingCustomDepth();\n        if ((!bMaterialMasked &amp;&amp; EarlyZPassMode != DDM_MaskedOnly) || (bMaterialMasked &amp;&amp; EarlyZPassMode != DDM_NonMaskedOnly))\n        {\n            bShouldRender = true;\n\n            if (!bMaterialMasked &amp;&amp; !bMaterialModifiesMeshPosition)\n            {\n                bUseDefaultMaterial = true;\n                bPositionOnly = false;\n            }\n        }\n    }\n\n    return bShouldRender;\n}\n<\/code><\/pre>\n<p>\u5bf9\u4e8e\u975emask\u3001\u652f\u6301PositionOnly\u3001\u6ca1\u6709\u7528\u5230WPO\u7684material\uff0cShouldRender\u624d\u8fd4\u56detrue\uff0c\u4e5f\u5c31\u662fopaque material<\/p>\n<pre><code class=\"line-numbers\">bool FDepthPassMeshProcessor::TryAddMeshBatch(const FMeshBatch&amp; RESTRICT MeshBatch, uint64 BatchElementMask, const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy, int32 StaticMeshId, const FMaterialRenderProxy&amp; MaterialRenderProxy, const FMaterial&amp; Material)\n{\n    const bool bIsTranslucent = IsTranslucentBlendMode(Material);\n    bool ShouldRenderInDepthPass = (!PrimitiveSceneProxy || PrimitiveSceneProxy-&gt;ShouldRenderInDepthPass());\n\n    bool bResult = true;\n    if (!bIsTranslucent\n        &amp;&amp; ShouldRenderInDepthPass\n        &amp;&amp; ShouldIncludeDomainInMeshPass(Material.GetMaterialDomain())\n        &amp;&amp; ShouldIncludeMaterialInDefaultOpaquePass(Material))\n    {\n        const bool bSupportPositionOnlyStream = MeshBatch.VertexFactory-&gt;SupportsPositionOnlyStream();\n        const bool bVFTypeSupportsNullPixelShader = MeshBatch.VertexFactory-&gt;SupportsNullPixelShader();\n        const bool bModifiesMeshPosition = DoMaterialAndPrimitiveModifyMeshPosition(Material, PrimitiveSceneProxy);\n        bool bPositionOnly = false;\n        bool bUseDefaultMaterial = false;\n        if (ShouldRender(Material, bModifiesMeshPosition, bSupportPositionOnlyStream, bVFTypeSupportsNullPixelShader, bUseDefaultMaterial, bPositionOnly))\n        {\n            const FMaterialRenderProxy* EffectiveMaterialRenderProxy = &amp;MaterialRenderProxy;\n            const FMaterial* EffectiveMaterial = &amp;Material;\n            if (bUseDefaultMaterial)\n            {\n                \/\/ Override with the default material\n                EffectiveMaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)-&gt;GetRenderProxy();\n                EffectiveMaterial = EffectiveMaterialRenderProxy-&gt;GetMaterialNoFallback(FeatureLevel);\n                check(EffectiveMaterial);\n            }\n\n            const FMeshDrawingPolicyOverrideSettings OverrideSettings = ComputeMeshOverrideSettings(MeshBatch);\n            const ERasterizerFillMode MeshFillMode = ComputeMeshFillMode(Material, OverrideSettings);\n            const ERasterizerCullMode MeshCullMode = ComputeMeshCullMode(Material, OverrideSettings);\n\n            if (bPositionOnly)\n            {\n                bResult = Process&lt;true&gt;(MeshBatch, BatchElementMask, StaticMeshId, PrimitiveSceneProxy, *EffectiveMaterialRenderProxy, *EffectiveMaterial, MeshFillMode, MeshCullMode);\n            }\n            else\n            {\n                bResult = Process&lt;false&gt;(MeshBatch, BatchElementMask, StaticMeshId, PrimitiveSceneProxy, *EffectiveMaterialRenderProxy, *EffectiveMaterial, MeshFillMode, MeshCullMode);\n            }\n        }\n    }\n\n    return bResult;\n}\n<\/code><\/pre>\n<p>\u5bf9\u4e8eopaque material\uff0c\u76f4\u63a5\u4f7f\u7528\u9ed8\u8ba4\u6750\u8d28\u6e32\u67d3\u8ba1\u7b97\u6df1\u5ea6\uff0c\u907f\u514d\u989d\u5916\u5f00\u9500\u4e0e\u975e\u6a21\u677f\u5316<\/p>\n<\/li>\n<\/ul>\n<h3>GPU\u7aef<\/h3>\n<h4>\u53ea\u5305\u542bPosition\u7684VS Shader<\/h4>\n<pre><code class=\"language-glsl line-numbers\">struct FPositionOnlyVertexFactoryInput\n{\n    float4  Position    : ATTRIBUTE0;\n    VF_GPUSCENE_DECLARE_INPUT_BLOCK(1)\n    VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()\n    VF_MOBILE_MULTI_VIEW_DECLARE_INPUT_BLOCK() \n};\n<\/code><\/pre>\n<pre><code class=\"language-glsl line-numbers\">void Main(\n    FPositionOnlyVertexFactoryInput Input,\n    out INVARIANT_OUTPUT float4 OutPosition : SV_POSITION,\n    out FStereoVSOutput StereoOutput\n#if USE_GLOBAL_CLIP_PLANE\n    , out float OutGlobalClipPlaneDistance : SV_ClipDistance\n#endif\n    )\n{\n    StereoSetupVF(Input, StereoOutput);\n\n    float4 WorldPos = VertexFactoryGetWorldPosition(Input);\n\n    {\n        OutPosition = INVARIANT(mul(WorldPos, ResolvedView.TranslatedWorldToClip));\n    }\n\n#if USE_GLOBAL_CLIP_PLANE\n    OutGlobalClipPlaneDistance = dot(ResolvedView.GlobalClippingPlane, float4(WorldPos.xyz, 1));\n#endif\n}\n<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\u53ea\u8ba1\u7b97\u4e86clip space position<\/p>\n<h4>\u4e0d\u4ec5\u4ec5\u5305\u542bPositon\u7684VS Shader<\/h4>\n<pre><code class=\"language-glsl line-numbers\">struct FDepthOnlyVSToPS\n{\n    INVARIANT_OUTPUT float4 Position : SV_POSITION;\n\n    \/\/ \u975eopaque\u6216pixel depth offset\n    #if !MATERIALBLENDING_SOLID || OUTPUT_PIXEL_DEPTH_OFFSET\n        FVertexFactoryInterpolantsVSToPS FactoryInterpolants;\n        float4 PixelPosition : TEXCOORD6;\n    #endif\n\n    #if USE_RAW_WORLD_POSITION\n        float3 PixelPositionExcludingWPO : TEXCOORD7;\n    #endif\n};\n<\/code><\/pre>\n<pre><code class=\"language-glsl line-numbers\">void Main(\n    FVertexFactoryInput Input,\n    out FDepthOnlyVSOutput Output\n#if USE_GLOBAL_CLIP_PLANE\n    , out float OutGlobalClipPlaneDistance : SV_ClipDistance\n#endif\n    , out FStereoVSOutput StereoOutput\n    )\n{\n#if USE_GLOBAL_CLIP_PLANE\n    OutGlobalClipPlaneDistance = dot(ResolvedView.GlobalClippingPlane, float4(WorldPos.xyz, 1));\n#endif\n\n#if !MATERIALBLENDING_SOLID || OUTPUT_PIXEL_DEPTH_OFFSET\n    \/\/ Masked and transparent materials need texture coords to clip, and tessellated\n    \/\/ materials need texture coords to displace\n    Output.FactoryInterpolants = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);\n\n#endif\n\n#if !MATERIALBLENDING_SOLID || OUTPUT_PIXEL_DEPTH_OFFSET\n    Output.PixelPosition = WorldPos;\n#endif\n\n#if USE_RAW_WORLD_POSITION\n    Output.PixelPositionExcludingWPO = WorldPositionExcludingWPO.xyz;\n#endif\n}\n<\/code><\/pre>\n<ul>\n<li>\u89e3\u5305\uff0c\u51c6\u5907\u6570\u636e\n<pre><code class=\"language-glsl line-numbers\">FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);\nfloat4 WorldPos = VertexFactoryGetWorldPosition(Input, VFIntermediates);\nfloat4 WorldPositionExcludingWPO = WorldPos;\n\nhalf3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);\nFMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPos.xyz, TangentToLocal);\n<\/code><\/pre>\n<\/li>\n<li>\u5e94\u7528WPO\n<pre><code class=\"language-glsl line-numbers\">WorldPos.xyz += GetMaterialWorldPositionOffset(VertexParameters);\n<\/code><\/pre>\n<\/li>\n<li>\u6253\u5305\u9700\u8981\u4f20\u7ed9PS\u63d2\u503c\u7684\u6570\u636e\n<pre><code class=\"language-glsl line-numbers\">#if !MATERIALBLENDING_SOLID || OUTPUT_PIXEL_DEPTH_OFFSET\n\/\/ Masked and transparent materials need texture coords to clip, and tessellated\n\/\/ materials need texture coords to displace\nOutput.FactoryInterpolants = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);\n\n#endif\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h4>Depth Only Pixel Shader<\/h4>\n<ul>\n<li>\u8ba1\u7b97\u6750\u8d28\u53c2\u6570\n<pre><code class=\"language-glsl line-numbers\">FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(FactoryInterpolants, SvPosition);\nFPixelMaterialInputs PixelMaterialInputs;\n\nCalcMaterialParameters(MaterialParameters, PixelMaterialInputs, SvPosition, bIsFrontFace);\n<\/code><\/pre>\n<\/li>\n<li>\u8ba1\u7b97pixel depth offset\n<pre><code class=\"language-glsl line-numbers\">#if OUTPUT_PIXEL_DEPTH_OFFSET\n  #if ALLOW_DEBUG_VIEW_MODES\n  OutDepth = SvPosition.z;\n  if (!ResolvedView.DebugViewModeMask)\n  #endif\n  {\n      ApplyPixelDepthOffsetToMaterialParameters(MaterialParameters, PixelMaterialInputs, OutDepth);\n  }\n\n  #if APPLE_DEPTH_BIAS_HACK\n  OutDepth -= APPLE_DEPTH_BIAS_VALUE;\n  #endif\n#endif\n<\/code><\/pre>\n<\/li>\n<li>\u5254\u9664\u4e0d\u9700\u8981\u7684\u50cf\u7d20\n<pre><code class=\"language-glsl line-numbers\">#if MATERIALBLENDING_TRANSLUCENT\n  clip(MaterialOpacity - GetMaterialOpacityMaskClipValue());\n#elif MATERIALBLENDING_MASKED_USING_COVERAGE\n  OutCoverage = DiscardMaterialWithPixelCoverage(MaterialParameters, PixelMaterialInputs);\n#else\n  GetMaterialCoverageAndClipping(MaterialParameters, PixelMaterialInputs);\n#endif\n<\/code><\/pre>\n<ul>\n<li>\u5254\u9664\u534a\u900f\u660e\uff0c\u534a\u900f\u660e\u4e0d\u5e94\u8be5\u8d70depth only<\/p>\n<\/li>\n<li>\n<p>\u4e3aAlpha To Coverage\u8ba1\u7b97SV_Coverage<\/p>\n<\/li>\n<li>\n<p>Dither Clip<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-glsl line-numbers\">void GetMaterialCoverageAndClipping(FMaterialPixelParameters Parameters, FPixelMaterialInputs PixelMaterialInputs)\n{\n    ClipLODTransition(Parameters);\n\n#if MATERIALBLENDING_MASKED &amp;&amp; !SINGLE_LAYER_WATER_NO_DISCARD\n    clip(GetDitheredMaterialMask(PixelMaterialInputs, Parameters.SvPosition.xy, View.StateFrameIndex));\n#endif\n}\n<\/code><\/pre>\n<pre><code class=\"language-glsl line-numbers\">void ClipLODTransition(float2 SvPosition, float DitherFactor)\n{\n    if (abs(DitherFactor) &gt; .001)\n    {\n        float ArgCos = dot(floor(SvPosition.xy), float2(347.83451793, 3343.28371963));\n\n        float RandCos = cos(ArgCos);\n        float RandomVal = frac(RandCos * 1000.0);\n        half RetVal = (DitherFactor &lt; 0.0) ?\n            (DitherFactor + 1.0 &gt; RandomVal) :\n            (DitherFactor &lt; RandomVal);\n        clip(RetVal - .001);\n    }\n}\n<\/code><\/pre>\n<p><strong>\u5bf9LOD\u50cf\u7d20\u8fdb\u884c\u6296\u52a8\u88c1\u526a<\/strong>\u3002\u8ba9\u7269\u4f53\u5728\u51e0\u5e27\u5185\u9010\u6e10\u663e\u73b0\uff0c\u800c\u4e0d\u662f\u7a81\u7136\u51fa\u73b0\uff0c<strong>\u9632\u6b62\u5207\u6362LOD\u65f6\u786c\u5207<\/strong><\/p>\n<pre><code class=\"language-glsl line-numbers\">float GetDitheredMaterialMask(FPixelMaterialInputs PixelMaterialInputs, uint2 SvPosition, uint FrameIndex)\n{\n    #if MATERIAL_DITHER_OPACITY_MASK\n        \/\/ New dithering based on Blue noise\n        float Noise2  = ViewScalarBlueNoise(SvPosition.xy, FrameIndex);\n        const float LegacyAdjustement = 0.83f; \/\/ This is required to get the same look and empty areas as the legacy one.\n        float Dither = LegacyAdjustement * Noise2;\n\n        return GetMaterialMask(PixelMaterialInputs) + Dither - 0.5f;\n    #else\n        return GetMaterialMask(PixelMaterialInputs);\n    #endif\n}\n<\/code><\/pre>\n<p>\u57fa\u4e8e\u5c4f\u5e55\u7a7a\u95f4 + TAA Dither\uff0c\u9632\u6b62clip(OpacityMask - 0.5)\u9020\u6210\u7684\u8fb9\u7f18\u95ea\u70c1<\/p>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u4ec0\u4e48\u662f Prepass Prepass\uff0c\u5168\u79f0Depth Prepass\uff0c\u4e5f\u5e38\u88ab\u79f0\u4e3a Early-Z Pass \u5b83\u5728\u5f15\u64ce\u771f\u6b63\u5f00\u59cb\u753b\u753b &#8230;<\/p>","protected":false},"author":1,"featured_media":450,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/488"}],"collection":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=488"}],"version-history":[{"count":5,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/488\/revisions"}],"predecessor-version":[{"id":497,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/488\/revisions\/497"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/media\/450"}],"wp:attachment":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=488"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=488"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}