源码 / Ch29/OverdrawFeature.cs
Ch29/OverdrawFeature.cs
// 案例 29.5:Overdraw 可视化 Renderer Feature。 // 用 overrideMaterial 把可见物体全部重画一遍到一张 R16 浮点 RT(每层 +1),再用热度图画回相机颜色。 using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace Cookbook.Ch29 { public class OverdrawFeature : ScriptableRendererFeature { [System.Serializable] public class Settings { public Material countMaterial; // Cookbook/Ch29/OverdrawCount public Material heatmapMaterial; // Cookbook/Ch29/OverdrawHeatmap public bool opaque = true; public bool transparent = true; public LayerMask layerMask = -1; } public Settings settings = new Settings(); OverdrawPass m_Pass; public override void Create() { m_Pass = new OverdrawPass(); } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (settings.countMaterial == null || settings.heatmapMaterial == null) return; if (renderingData.cameraData.cameraType == CameraType.Preview) return; m_Pass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; m_Pass.Setup(settings); renderer.EnqueuePass(m_Pass); } public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData) { m_Pass.SetCameraColor(renderer.cameraColorTargetHandle); } protected override void Dispose(bool disposing) { m_Pass?.Dispose(); } class OverdrawPass : ScriptableRenderPass { // 和 URP 自己画不透明/透明物体时用的 LightMode 列表一致 static readonly List<ShaderTagId> s_Tags = new List<ShaderTagId> { new ShaderTagId("UniversalForward"), new ShaderTagId("UniversalForwardOnly"), new ShaderTagId("SRPDefaultUnlit"), new ShaderTagId("LightweightForward"), }; Settings m_Settings; RTHandle m_CameraColor, m_Count; public OverdrawPass() { profilingSampler = new ProfilingSampler("OverdrawView"); } public void Setup(Settings s) { m_Settings = s; } public void SetCameraColor(RTHandle h) { m_CameraColor = h; } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { var desc = renderingData.cameraData.cameraTargetDescriptor; desc.msaaSamples = 1; desc.depthBufferBits = 0; desc.colorFormat = RenderTextureFormat.RHalf; // 计数可能超过 1,要浮点格式 RenderingUtils.ReAllocateIfNeeded(ref m_Count, desc, FilterMode.Point, TextureWrapMode.Clamp, name: "_OverdrawCount"); ConfigureTarget(m_Count); ConfigureClear(ClearFlag.Color, Color.black); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, profilingSampler)) { // ConfigureTarget/ConfigureClear 已经把 m_Count 设为目标并清成 0 context.ExecuteCommandBuffer(cmd); cmd.Clear(); if (m_Settings.opaque) Draw(context, ref renderingData, RenderQueueRange.opaque, SortingCriteria.CommonOpaque); if (m_Settings.transparent) Draw(context, ref renderingData, RenderQueueRange.transparent, SortingCriteria.CommonTransparent); Blitter.BlitCameraTexture(cmd, m_Count, m_CameraColor, m_Settings.heatmapMaterial, 0); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } void Draw(ScriptableRenderContext context, ref RenderingData renderingData, RenderQueueRange range, SortingCriteria sort) { var drawing = CreateDrawingSettings(s_Tags, ref renderingData, sort); drawing.overrideMaterial = m_Settings.countMaterial; // 所有物体都用计数材质画 drawing.overrideMaterialPassIndex = 0; var filtering = new FilteringSettings(range, m_Settings.layerMask); context.DrawRenderers(renderingData.cullResults, ref drawing, ref filtering); } public void Dispose() { m_Count?.Release(); } } } }