using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.RenderGraphModule.Util; using UnityEngine.Rendering.Universal; public class CRTRendererFeature : ScriptableRendererFeature { [System.Serializable] public class CRTSettings { public bool EffectEnabled = true; public RenderPassEvent PassEvent = RenderPassEvent.AfterRenderingPostProcessing; public Shader CRTShader; [Range(0f, 1f)] public float Intensity = 0.65f; [Range(0f, 2f)] public float ScanlineDensity = 1.2f; [Range(0f, 1f)] public float ScanlineStrength = 0.18f; [Range(0f, 0.2f)] public float Curvature = 0.04f; [Range(0f, 1f)] public float VignetteStrength = 0.28f; [Range(0f, 0.05f)] public float ChromaticAberration = 0.004f; [Range(0f, 0.2f)] public float NoiseStrength = 0.03f; [Range(0f, 0.1f)] public float FlickerStrength = 0.015f; } class CRTPass : ScriptableRenderPass { private readonly ProfilingSampler m_ProfilingSampler = new("CRT Effect"); private Material m_Material; private CRTSettings m_Settings; private RTHandle m_TempColorTexture; public void Setup(Material material, CRTSettings settings) { m_Material = material; m_Settings = settings; renderPassEvent = settings.PassEvent; requiresIntermediateTexture = true; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { if (m_Material == null || m_Settings == null || !m_Settings.EffectEnabled) { return; } UniversalResourceData resourceData = frameData.Get(); if (resourceData.isActiveTargetBackBuffer) { return; } m_Material.SetFloat("_Intensity", m_Settings.Intensity); m_Material.SetFloat("_ScanlineDensity", m_Settings.ScanlineDensity); m_Material.SetFloat("_ScanlineStrength", m_Settings.ScanlineStrength); m_Material.SetFloat("_Curvature", m_Settings.Curvature); m_Material.SetFloat("_VignetteStrength", m_Settings.VignetteStrength); m_Material.SetFloat("_ChromaticAberration", m_Settings.ChromaticAberration); m_Material.SetFloat("_NoiseStrength", m_Settings.NoiseStrength); m_Material.SetFloat("_FlickerStrength", m_Settings.FlickerStrength); TextureHandle source = resourceData.activeColorTexture; TextureDesc destinationDesc = renderGraph.GetTextureDesc(source); destinationDesc.name = "CameraColor-CRT"; destinationDesc.clearBuffer = false; TextureHandle destination = renderGraph.CreateTexture(destinationDesc); RenderGraphUtils.BlitMaterialParameters blitParams = new(source, destination, m_Material, 0); renderGraph.AddBlitPass(blitParams, "CRT Effect"); resourceData.cameraColor = destination; } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { cameraTextureDescriptor.depthBufferBits = 0; RenderingUtils.ReAllocateHandleIfNeeded( ref m_TempColorTexture, cameraTextureDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_CRTTempColorTexture" ); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (m_Material == null || m_Settings == null || !m_Settings.EffectEnabled) { return; } if (renderingData.cameraData.isSceneViewCamera) { return; } CommandBuffer cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, m_ProfilingSampler)) { m_Material.SetFloat("_Intensity", m_Settings.Intensity); m_Material.SetFloat("_ScanlineDensity", m_Settings.ScanlineDensity); m_Material.SetFloat("_ScanlineStrength", m_Settings.ScanlineStrength); m_Material.SetFloat("_Curvature", m_Settings.Curvature); m_Material.SetFloat("_VignetteStrength", m_Settings.VignetteStrength); m_Material.SetFloat("_ChromaticAberration", m_Settings.ChromaticAberration); m_Material.SetFloat("_NoiseStrength", m_Settings.NoiseStrength); m_Material.SetFloat("_FlickerStrength", m_Settings.FlickerStrength); RTHandle source = renderingData.cameraData.renderer.cameraColorTargetHandle; Blitter.BlitCameraTexture(cmd, source, m_TempColorTexture, m_Material, 0); Blitter.BlitCameraTexture(cmd, m_TempColorTexture, source); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } public void Dispose() { m_TempColorTexture?.Release(); m_TempColorTexture = null; } } public CRTSettings Settings = new(); private CRTPass m_Pass; private Material m_Material; public override void Create() { if (Settings.CRTShader == null) { Settings.CRTShader = Shader.Find("Hidden/HeadlessHazard/CRT"); } if (Settings.CRTShader != null) { m_Material = CoreUtils.CreateEngineMaterial(Settings.CRTShader); } m_Pass ??= new CRTPass(); } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (m_Material == null || !Settings.EffectEnabled) { return; } if (renderingData.cameraData.cameraType != CameraType.Game) { return; } m_Pass.Setup(m_Material, Settings); renderer.EnqueuePass(m_Pass); } protected override void Dispose(bool disposing) { m_Pass?.Dispose(); m_Pass = null; CoreUtils.Destroy(m_Material); m_Material = null; } }