using System; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Experimental.Rendering.Universal; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class WBOITFeature : ScriptableRendererFeature { [Serializable] public class FilterSettings { public RenderQueueType RenderQueueType; public LayerMask LayerMask; public FilterSettings() { RenderQueueType = RenderQueueType.Transparent; LayerMask = 0; } } [Serializable] public class OITSettings { public RenderPassEvent RenderPassEvent = RenderPassEvent.AfterRenderingOpaques; public FilterSettings FilterSettings = new FilterSettings(); public Shader BlendShader; } [SerializeField] OITSettings settings; OITRenderPass pass; public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { var cam = renderingData.cameraData; if (cam.cameraType != CameraType.Game && cam.cameraType != CameraType.SceneView) { return; } renderer.EnqueuePass(pass); } public override void Create() { pass = new OITRenderPass(settings); } protected override void Dispose(bool disposing) { base.Dispose(disposing); pass.Dispose(); } class OITRenderPass : ScriptableRenderPass, IDisposable { private ProfilingSampler profiler; private CommandBuffer commandBuffer; private OITSettings settings; private Material blendMaterial; static readonly int accumTexID = Shader.PropertyToID("_AccumTex"); static readonly int revealageTexID = Shader.PropertyToID("_RevealageTex"); static readonly int mainTexID = Shader.PropertyToID("_MainTex"); RTHandle[] oitRTids = new RTHandle[2]; private ShaderTagId shaderTagId = new ShaderTagId("DoOIT"); public OITRenderPass(OITSettings settings) { this.settings = settings; profiler = new(nameof(OITRenderPass)); commandBuffer = new CommandBuffer(); commandBuffer.name = profiler.name; renderPassEvent = settings.RenderPassEvent; blendMaterial = new Material(settings.BlendShader); } public void Dispose() { oitRTids[0]?.Release(); oitRTids[1]?.Release(); commandBuffer.Release(); GameObject.DestroyImmediate(blendMaterial); } RTHandle destinationRT; public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cmd = commandBuffer; using var scp = new ProfilingScope(cmd, profiler); var rdr = renderingData.cameraData.renderer; var desc = renderingData.cameraData.cameraTargetDescriptor; desc.depthBufferBits = 0; desc.sRGB = false; RenderingUtils.ReAllocateIfNeeded(ref oitRTids[0], desc, filterMode: FilterMode.Bilinear); RenderingUtils.ReAllocateIfNeeded(ref destinationRT, desc, filterMode: FilterMode.Bilinear); cmd.SetRenderTarget(oitRTids[0]); cmd.ClearRenderTarget(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R16_SFloat, FormatUsage.Render) ? GraphicsFormat.R16_SFloat : GraphicsFormat.R32_SFloat; RenderingUtils.ReAllocateIfNeeded(ref oitRTids[1], desc, filterMode: FilterMode.Bilinear); cmd.SetRenderTarget(oitRTids[1]); cmd.ClearRenderTarget(false, true, new Color(1.0f, 1.0f, 1.0f, 1.0f)); RenderQueueRange renderQueueRange = (settings.FilterSettings.RenderQueueType == RenderQueueType.Transparent) ? RenderQueueRange.transparent : RenderQueueRange.opaque; var filteringSettings = new FilteringSettings(renderQueueRange, settings.FilterSettings.LayerMask); var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing); SortingCriteria sortingCriteria = (filteringSettings.renderQueueRange == RenderQueueRange.transparent) ? SortingCriteria.CommonTransparent : renderingData.cameraData.defaultOpaqueSortFlags; DrawingSettings drawSettings = CreateDrawingSettings(shaderTagId, ref renderingData, sortingCriteria); #region Draw Weighted Blended Order-Independent Transparency context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings, ref renderStateBlock); #endregion #region Blend cmd.SetGlobalTexture(accumTexID, oitRTids[0]); cmd.SetGlobalTexture(revealageTexID, oitRTids[1]); cmd.SetGlobalTexture(mainTexID, rdr.cameraColorTargetHandle); cmd.SetRenderTarget(destinationRT, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); cmd.DrawProcedural(Matrix4x4.identity, blendMaterial, 0, MeshTopology.Triangles, 3); if (SystemInfo.copyTextureSupport != CopyTextureSupport.None) { cmd.CopyTexture(destinationRT, rdr.cameraColorTargetHandle); } else { Blit(cmd, destinationRT, rdr.cameraColorTargetHandle); } #endregion context.ExecuteCommandBuffer(cmd); cmd.Clear(); } } }