Files
tools/Unity C++脚本/shader/Render/GrabPassFeature.cs
T
2026-03-10 20:36:07 +08:00

93 lines
3.4 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
/// <summary>
/// Grab Pass 特性:将当前颜色缓冲绑定为 _CameraColorAttachmentA 供热扭曲等效果使用
/// </summary>
public class GrabPassFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
public string shaderTagName = "Grab";
public LayerMask layerMask = -1;
[Header("性能设置")]
[Tooltip("采样分辨率缩放(1.0 = 全分辨率,0.5 = 半分辨率)")]
[Range(0.25f, 1f)]
public float resolutionScale = 1f;
}
public Settings settings = new Settings();
private GrabPass grabPass;
public override void Create()
{
grabPass = new GrabPass(settings);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(grabPass);
}
protected override void Dispose(bool disposing)
{
grabPass?.Dispose();
}
class GrabPass : ScriptableRenderPass
{
private readonly ShaderTagId shaderTagId;
private FilteringSettings filteringSettings;
private readonly Settings settings;
private RTHandle tempColorTarget;
public GrabPass(Settings settings)
{
this.settings = settings;
renderPassEvent = settings.renderPassEvent;
shaderTagId = new ShaderTagId(settings.shaderTagName);
filteringSettings = new FilteringSettings(RenderQueueRange.transparent, settings.layerMask);
ConfigureInput(ScriptableRenderPassInput.Color);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
descriptor.width = Mathf.Max(1, Mathf.CeilToInt(descriptor.width * settings.resolutionScale));
descriptor.height = Mathf.Max(1, Mathf.CeilToInt(descriptor.height * settings.resolutionScale));
descriptor.depthBufferBits = 0;
descriptor.msaaSamples = 1;
RenderingUtils.ReAllocateIfNeeded(ref tempColorTarget, descriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_GrabPassTemp");
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
if (tempColorTarget == null) return;
var cmd = CommandBufferPool.Get("Grab Pass");
var sourceColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
cmd.Blit(sourceColorTarget.nameID, tempColorTarget.nameID);
cmd.SetGlobalTexture("_CameraColorAttachmentA", tempColorTarget.nameID);
cmd.SetRenderTarget(sourceColorTarget, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
var drawingSettings = CreateDrawingSettings(shaderTagId, ref renderingData, SortingCriteria.CommonTransparent);
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings);
CommandBufferPool.Release(cmd);
}
public void Dispose()
{
tempColorTarget?.Release();
}
}
}