175 lines
6.9 KiB
C#
175 lines
6.9 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
public class BloomRenderFeature : ScriptableRendererFeature
|
|
{
|
|
[System.Serializable]
|
|
public class BloomSettings
|
|
{
|
|
public RenderPassEvent passEvent = RenderPassEvent.AfterRenderingPostProcessing;
|
|
|
|
public Shader blurShader;
|
|
public Shader compositeShader;
|
|
|
|
[Range(0, 4)]
|
|
public int downsample = 1;
|
|
|
|
[Range(0.0f, 2.0f)]
|
|
public float threshold = 1.0f;
|
|
|
|
[Range(0.0f, 10.0f)]
|
|
public float radius = 1.0f;
|
|
|
|
[Range(0.0f, 10.0f)]
|
|
public float intensity = 1.0f;
|
|
|
|
// x = w2, y = w1, z = w0 (symmetric 5-tap kernel)
|
|
public Vector3 weights = new Vector3(0.2f, 0.4f, 0.8f);
|
|
}
|
|
|
|
BloomPass bloomPass;
|
|
|
|
Material blurMat;
|
|
Material compositeMat;
|
|
|
|
public BloomSettings settings = new BloomSettings();
|
|
|
|
// ────────────────────────────────────────────────────────────────
|
|
// CREATE
|
|
// ────────────────────────────────────────────────────────────────
|
|
public override void Create()
|
|
{
|
|
if (settings.blurShader)
|
|
blurMat = CoreUtils.CreateEngineMaterial(settings.blurShader);
|
|
|
|
if (settings.compositeShader)
|
|
compositeMat = CoreUtils.CreateEngineMaterial(settings.compositeShader);
|
|
|
|
bloomPass = new BloomPass(settings);
|
|
bloomPass.renderPassEvent = settings.passEvent;
|
|
}
|
|
|
|
|
|
// ────────────────────────────────────────────────────────────────
|
|
// ONLY enqueue pass here (NO camera target access!)
|
|
// ────────────────────────────────────────────────────────────────
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
|
{
|
|
if (blurMat == null || compositeMat == null)
|
|
return;
|
|
|
|
// Pass only materials
|
|
bloomPass.Setup(blurMat, compositeMat);
|
|
renderer.EnqueuePass(bloomPass);
|
|
}
|
|
|
|
|
|
|
|
// ======================================================================
|
|
// BLOOM PASS
|
|
// ======================================================================
|
|
|
|
class BloomPass : ScriptableRenderPass
|
|
{
|
|
BloomSettings settings;
|
|
|
|
Material blurMat;
|
|
Material compositeMat;
|
|
|
|
RTHandle rt1;
|
|
RTHandle rt2;
|
|
|
|
// final camera target (RenderTargetIdentifier)
|
|
RenderTargetIdentifier source;
|
|
|
|
string tag = "BloomPass";
|
|
|
|
public BloomPass(BloomSettings settings)
|
|
{
|
|
this.settings = settings;
|
|
}
|
|
|
|
public void Setup(Material blurMat, Material compositeMat)
|
|
{
|
|
this.blurMat = blurMat;
|
|
this.compositeMat = compositeMat;
|
|
}
|
|
|
|
|
|
// ────────────────────────────────────────────────────────────────
|
|
// VALID place to access cameraColorTargetHandle
|
|
// ────────────────────────────────────────────────────────────────
|
|
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
|
{
|
|
// SAFE: this is the correct place to access cameraColorTargetHandle
|
|
source = renderingData.cameraData.renderer.cameraColorTargetHandle;
|
|
|
|
float scale = 1f / (1 << settings.downsample);
|
|
Vector2 scaleFactor = new Vector2(scale, scale);
|
|
|
|
rt1 = RTHandles.Alloc(
|
|
scaleFactor,
|
|
colorFormat: GraphicsFormat.R16G16B16A16_SFloat,
|
|
filterMode: FilterMode.Bilinear,
|
|
name: "_BloomRT1"
|
|
);
|
|
|
|
rt2 = RTHandles.Alloc(
|
|
scaleFactor,
|
|
colorFormat: GraphicsFormat.R16G16B16A16_SFloat,
|
|
filterMode: FilterMode.Bilinear,
|
|
name: "_BloomRT2"
|
|
);
|
|
}
|
|
|
|
|
|
// ────────────────────────────────────────────────────────────────
|
|
// EXECUTE BLOOM EFFECT
|
|
// ────────────────────────────────────────────────────────────────
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
|
{
|
|
if (blurMat == null || compositeMat == null)
|
|
return;
|
|
|
|
CommandBuffer cmd = CommandBufferPool.Get(tag);
|
|
|
|
// Pass parameters
|
|
blurMat.SetFloat("_Threshold", settings.threshold);
|
|
blurMat.SetFloat("_Radius", settings.radius);
|
|
blurMat.SetFloat("_Intensity", settings.intensity);
|
|
blurMat.SetVector("_Weights", new Vector4(settings.weights.x, settings.weights.y, settings.weights.z, 0));
|
|
|
|
|
|
// 1. Extract bright areas
|
|
cmd.Blit(source, rt1, blurMat, 0);
|
|
|
|
// 2. Blur horizontal
|
|
blurMat.SetVector("_Direction", new Vector4(1, 0, 0, 0));
|
|
cmd.Blit(rt1, rt2, blurMat, 1);
|
|
|
|
// 3. Blur vertical
|
|
blurMat.SetVector("_Direction", new Vector4(0, 1, 0, 0));
|
|
cmd.Blit(rt2, rt1, blurMat, 1);
|
|
|
|
// 4. Composite bloom back
|
|
compositeMat.SetFloat("_Intensity", settings.intensity);
|
|
cmd.Blit(rt1, source, compositeMat, 0);
|
|
|
|
context.ExecuteCommandBuffer(cmd);
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
|
|
// ────────────────────────────────────────────────────────────────
|
|
// CLEANUP (Release RTHandles)
|
|
// ────────────────────────────────────────────────────────────────
|
|
public override void OnCameraCleanup(CommandBuffer cmd)
|
|
{
|
|
if (rt1 != null) RTHandles.Release(rt1);
|
|
if (rt2 != null) RTHandles.Release(rt2);
|
|
}
|
|
}
|
|
}
|