using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class VolumeLight : ScriptableRendererFeature { [Range(0.001f,1)]public float space_sigma=1; [Range(0.001f,1)]public float range_sigma =0.5f; // public Vector3 BoundMin; // public Vector3 BoundMax; [Range(8,16)]public int Precision=10; [Range(0,5)]public float Strength=2; class CustomRenderPass : ScriptableRenderPass { public float space_sigma; public float range_sigma ; private Material mat; //private RTHandle tempRT; // private RTHandle tempRT1; private readonly int temp = Shader.PropertyToID("temp"); private readonly int temp1 = Shader.PropertyToID("temp1"); private readonly int temp2 = Shader.PropertyToID("temp2"); public Vector3 BoundMin; public Vector3 BoundMax; [Range(1,3)]public int Precision; public float Strength; public CustomRenderPass() { if (mat == null) { mat = CoreUtils.CreateEngineMaterial("Unlit/volumeLight"); } } // This method is called before executing the render pass. // It can be used to configure render targets and their clear state. Also to create temporary render target textures. // When empty this render pass will render to the active camera render target. // You should never call CommandBuffer.SetRenderTarget. Instead call ConfigureTarget and ConfigureClear. // The render pipeline will ensure target setup and clearing happens in a performant manner. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { //cmd.GetTemporaryRT(temp,renderingData.cameraData.cameraTargetDescriptor.width,renderingData.cameraData.cameraTargetDescriptor.height); var dp = renderingData.cameraData.cameraTargetDescriptor; dp.msaaSamples = 1; dp.depthBufferBits = 0; //RenderingUtils.ReAllocateIfNeeded(ref tempRT, dp); //RTHandles.Alloc(temp) //RenderingUtils.ReAllocateIfNeeded(ref tempRT1, dp); } // Here you can implement the rendering logic. // Use ScriptableRenderContext to issue drawing commands or execute command buffers // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get("volumeLight"); RenderTextureDescriptor rtDescriptor = renderingData.cameraData.cameraTargetDescriptor; //后处理取消抗锯齿 rtDescriptor.msaaSamples = 1; cmd.GetTemporaryRT(temp,rtDescriptor); //rtDescriptor.width /= 2; //rtDescriptor.height /= 2; cmd.GetTemporaryRT(temp2,rtDescriptor); cmd.GetTemporaryRT(temp1,rtDescriptor); //cmd.SetGlobalVector("_BoundMin",BoundMin); //cmd.SetGlobalVector("_BoundMax",BoundMax); cmd.SetGlobalFloat("_J",Precision); cmd.SetGlobalFloat("_Strength",Strength); //光线步进 //cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget,temp2); cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget,temp1,mat,0); //cmd.Blit(temp2,temp1,mat,0); cmd.SetGlobalFloat("space_sigma",space_sigma); cmd.SetGlobalFloat("range_sigma",range_sigma); //双边过滤 cmd.Blit(temp1,temp2,mat,1); //Blitter.BlitCameraTexture(cmd,tempRT,tempRT1,mat,1); // 快速模糊 //Blitter.BlitCameraTexture(cmd,tempRT,tempRT1,mat,3); cmd.Blit(temp2,temp1,mat,4); cmd.Blit(temp1,temp2,mat,3); //混合 cmd.SetGlobalTexture("_LightMar",temp2); cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget,temp,mat,2); //Blitter.BlitCameraTexture(cmd,renderingData.cameraData.renderer.cameraColorTargetHandle,tempRT1,mat,2); cmd.Blit(temp,renderingData.cameraData.renderer.cameraColorTarget); // Blitter.BlitCameraTexture(cmd,tempRT1,renderingData.cameraData.renderer.cameraColorTargetHandle); cmd.ReleaseTemporaryRT(temp); cmd.ReleaseTemporaryRT(temp1); cmd.ReleaseTemporaryRT(temp2); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } // Cleanup any allocated resources that were created during the execution of this render pass. public override void OnCameraCleanup(CommandBuffer cmd) { } public void Destory() { CoreUtils.Destroy(mat); } } CustomRenderPass m_ScriptablePass; public RenderPassEvent renderPassEvent=RenderPassEvent.AfterRenderingPostProcessing; /// public override void Create() { m_ScriptablePass = new CustomRenderPass(); // Configures where the render pass should be injected. m_ScriptablePass.renderPassEvent = renderPassEvent; } // Here you can inject one or multiple render passes in the renderer. // This method is called when setting up the renderer once per-camera. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { m_ScriptablePass.ConfigureInput(ScriptableRenderPassInput.Depth); m_ScriptablePass.range_sigma = range_sigma; m_ScriptablePass.space_sigma = space_sigma; //m_ScriptablePass.BoundMax = BoundMax; //m_ScriptablePass.BoundMin = BoundMin; m_ScriptablePass.Precision = Precision; m_ScriptablePass.Strength = Strength; renderer.EnqueuePass(m_ScriptablePass); } protected override void Dispose(bool disposing) { base.Dispose(disposing); m_ScriptablePass.Destory(); } }