自定義RenderFeature接口流程
URP內部ScriptableRenderPass分析
public、protected屬性
- renderPassEvent :渲染事件發生的時刻
- colorAttachments :渲染的顏色紋理列表 m_ColorAttachments
- colorAttachment :m_ColorAttachments[0];
- depthAttachment :m_DepthAttachment
- colorStoreActions:
RenderBufferStoreAction[]
【Enum】這個 枚舉 描述了當GPU完成渲染到渲染目標時應該在渲染目標上做什么。(與MSAA是否存儲或解析有關) - depthStoreAction :
RenderBufferStoreAction
【Enum】 - input :
ScriptableRenderPassInput
【Enum】- None = 0x0,
- Depth = 0x1,
- Normal = 0x2,
- Color = 0x4,
- Motion = 0x8
- clearFlag :
ClearFlag
【Enum】- None = 0x0,
- Color = 0x1,
- Depth = 0x2,
- Stencil = 0x4,
- DepthStencil = 0x6,
- ColorStencil = 0x5,
- All = 0x7
- clearColor :Color m_ClearColor
private 屬性
internal 屬性(同一命名空間使用)
internal bool overrideCameraTarget { get; set; }internal bool isBlitRenderPass { get; set; }internal bool useNativeRenderPass { get; set; }internal int renderTargetWidth { get; set; }internal int renderTargetHeight { get; set; }internal int renderTargetSampleCount { get; set; }internal bool depthOnly { get; set; }internal bool isLastPass { get; set; }//這個標志每幀更新,以跟蹤哪一幀是當前相機的最后一幀internal int renderPassQueueIndex { get; set; }//索引來跟蹤當前幀中的位置internal NativeArray<int> m_ColorAttachmentIndices;internal NativeArray<int> m_InputAttachmentIndices;internal GraphicsFormat[] renderTargetFormat { get; set; }RenderTargetIdentifier[] m_ColorAttachments = new RenderTargetIdentifier[] { BuiltinRenderTextureType.CameraTarget };internal RenderTargetIdentifier[] m_InputAttachments = new RenderTargetIdentifier[8];internal bool[] m_InputAttachmentIsTransient = new bool[8];RenderTargetIdentifier m_DepthAttachment = BuiltinRenderTextureType.CameraTarget;ScriptableRenderPassInput m_Input = ScriptableRenderPassInput.None;ClearFlag m_ClearFlag = ClearFlag.None;Color m_ClearColor = Color.black;
URP內部ScriptableRenderer分析
ScriptableRenderer 管理所有的ScriptableRenderFeature以及ScriptableRenderPass
static數據
internal static ScriptableRenderer current = null;
private static bool m_UseOptimizedStoreActions = false;
static RenderTargetIdentifier[] m_ActiveColorAttachments = new RenderTargetIdentifier[] { 0, 0, 0, 0, 0, 0, 0, 0 };
static RenderTargetIdentifier m_ActiveDepthAttachment;
static RenderTargetIdentifier[][] m_TrimmedColorAttachmentCopies = new RenderTargetIdentifier[][]
private static Plane[] s_Planes = new Plane[6];
private static Vector4[] s_VectorPlanes = new Vector4[6];
核心數據
List<ScriptableRenderPass> m_ActiveRenderPassQueue = new List<ScriptableRenderPass>(32);
List<ScriptableRendererFeature> m_RendererFeatures = new List<ScriptableRendererFeature>(10);
RenderTargetIdentifier m_CameraColorTarget;//當前渲染管線上一幀結果的Color紋理
RenderTargetIdentifier m_CameraDepthTarget;
RenderTargetIdentifier m_CameraResolveTarget;
其他數據
private StoreActionsOptimization m_StoreActionsOptimizationSetting = StoreActionsOptimization.Auto;
const int k_RenderPassBlockCount = 4;
bool m_FirstTimeCameraColorTargetIsBound = true;
bool m_FirstTimeCameraDepthTargetIsBound = true;
bool m_IsPipelineExecuting = false;
internal bool isCameraColorTargetValid = false;
internal bool disableNativeRenderPassInFeatures = false;
internal bool useRenderPassEnabled = false;
internal bool useDepthPriming { get; set; } = false;
internal bool stripShadowsOffVariants { get; set; } = false;
internal bool stripAdditionalLightOffVariants { get; set; } = false;
首先,當創建實例Pass時調用父類構造函數
public ScriptableRenderPass()
{renderPassEvent = RenderPassEvent.AfterRenderingOpaques;m_ColorAttachments = new RenderTargetIdentifier[] { BuiltinRenderTextureType.CameraTarget, 0, 0, 0, 0, 0, 0, 0 };m_InputAttachments = new RenderTargetIdentifier[] { -1, -1, -1, -1, -1, -1, -1, -1 };m_InputAttachmentIsTransient = new bool[] { false, false, false, false, false, false, false, false };m_DepthAttachment = BuiltinRenderTextureType.CameraTarget;m_ColorStoreActions = new RenderBufferStoreAction[] { RenderBufferStoreAction.Store, 0, 0, 0, 0, 0, 0, 0 };m_DepthStoreAction = RenderBufferStoreAction.Store;m_OverriddenColorStoreActions = new bool[] { false, false, false, false, false, false, false, false };m_OverriddenDepthStoreAction = false;m_ClearFlag = ClearFlag.None;m_ClearColor = Color.black;overrideCameraTarget = false;isBlitRenderPass = false;profilingSampler = new ProfilingSampler($"Unnamed_{nameof(ScriptableRenderPass)}");useNativeRenderPass = true;renderTargetWidth = -1;renderTargetHeight = -1;renderTargetSampleCount = -1;renderPassQueueIndex = -1;renderTargetFormat = new GraphicsFormat[]{GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None,GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None};depthOnly = false;
}
其次、調用AddRenderPasses時,將實例化Pass加入隊列
使用函數
renderer.EnqueuePass(_scannerPass);
將該Pass加入到URP Renderer管線中
public void EnqueuePass(ScriptableRenderPass pass)
{m_ActiveRenderPassQueue.Add(pass);if (disableNativeRenderPassInFeatures)pass.useNativeRenderPass = false;
}
之后、調用OnCameraSetup,設置當前Pass的目標紋理
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{// 將當前攝像機的cameraColorTarget作為該Pass渲染的目標紋理ConfigureTarget(renderingData.cameraData.renderer.cameraColorTarget);
}
最后、調用Execute函數渲染
作為后處理,我們可以通過如下流程
1. 創建著色器屬性名稱唯一標識符
int tempRT = Shader.PropertyToID("標識符名稱,可自定義");
2. 根據當前攝像機的目標紋理設置,創建新的臨時紋理
cmd.GetTemporaryRT(tempRT, renderingData.cameraData.cameraTargetDescriptor);
RenderTextureDescriptor
這個結構體包含了創建RenderTexture所需的所有信息。即renderingData.cameraData.cameraTargetDescriptor
返回的值
3. 對一個紋理做后處理
后處理材質為_material,使用Pass 0;并保存到下一個紋理中。
cmd.Blit(colorAttachment, tempRT, _material, 0);
Blit意思為位塊傳送,即將colorAttachment的所有數據,復制到tempRT中。
而這里,Unity不僅僅做位塊傳輸,而是 使用著色器 將紋理中的像素數據復制到渲染紋理中。
public void Blit(RenderTargetIdentifier source, RenderTargetIdentifier dest, Material mat, int pass)
{// 設置描述如何執行命令緩沖區的意圖的標志。ValidateAgainstExecutionFlags(CommandBufferExecutionFlags.None, CommandBufferExecutionFlags.AsyncCompute);// 位塊傳輸 allSlices---所有位塊Blit_Identifier(ref source, ref dest, mat, pass, new Vector2(1f, 1f), new Vector2(0f, 0f), Texture2DArray.allSlices, 0);
}
內部代碼被封裝,不可見!
4. 將臨時紋理復制給目標
如果不使用自己的material,則使用Unity默認的mat,即只復制結果。
cmd.Blit(tempRT, colorAttachment);
5. 提交命令,釋放命令池
//上下文執行這個CommandBuffer
context.ExecuteCommandBuffer(cmd);
//釋放這個臨時紋理
cmd.ReleaseTemporaryRT(tempRT);
//CommandBuffer池釋放這個cmd
CommandBufferPool.Release(cmd);
Shader中的數據
復制的數據將作為_MainTex錄入。
Properties
{_MainTex("MainTex",2D)= "white"{}
}
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
深度圖需要在UniversalRenderPipelineAsset中勾選Depth Texture。
但是如果未勾選,如果內部渲染有使用到DepthTexture,也可能會生成DepthTexture。
TEXTURE2D(_CameraDepthTexture);
SAMPLER(sampler_CameraDepthTexture);