Skip to content

Instantly share code, notes, and snippets.

@BlurryLight
Forked from CarlLee/Bloom.shader
Created June 7, 2022 06:40
Show Gist options
  • Save BlurryLight/d8d07fa173c6f37dd5b0fcdaa99964af to your computer and use it in GitHub Desktop.
Save BlurryLight/d8d07fa173c6f37dd5b0fcdaa99964af to your computer and use it in GitHub Desktop.
UE4 bloom for unity
Shader "Hidden/Bloom"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f15
{
float4 uv01 : TEXCOORD0;
float4 uv23 : TEXCOORD1;
float4 uv45 : TEXCOORD2;
float4 uv67 : TEXCOORD3;
float4 uv89 : TEXCOORD4;
float4 uv1011 : TEXCOORD5;
float4 uv1213 : TEXCOORD6;
float4 uv1415 : TEXCOORD7;
float4 vertex : SV_POSITION;
};
struct v2f7
{
float4 uv01 : TEXCOORD0;
float4 uv23 : TEXCOORD1;
float4 uv45 : TEXCOORD2;
float4 uv67 : TEXCOORD3;
float4 vertex : SV_POSITION;
};
// Downsampled texture
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
float4 _MainTex_TexelSize;
TEXTURE2D(_CocTex); SAMPLER(sampler_CocTex);
float2 Circle(float slices, float index, float start)
{
float rad = (3.14159462 * 2.0 * (1.0 / slices)) * (index + start);
return float2(cos(rad), sin(rad));
}
ENDHLSL
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
// 0: 15 taps downsample
Pass
{
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Frag
float _BloomDownScale;
v2f15 Vertex(appdata v)
{
float start = 2.0;
v2f15 o;
o.uv01.xy = v.uv;
o.uv01.zw = v.uv + Circle(14.0, 0.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv23.xy = v.uv + Circle(14.0, 1.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv23.zw = v.uv + Circle(14.0, 2.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv45.xy = v.uv + Circle(14.0, 3.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv45.zw = v.uv + Circle(14.0, 4.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv67.xy = v.uv + Circle(14.0, 5.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv67.zw = v.uv + Circle(14.0, 6.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv89.xy = v.uv + Circle(14.0, 7.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv89.zw = v.uv + Circle(14.0, 8.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1011.xy = v.uv + Circle(14.0, 9.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1011.zw = v.uv + Circle(14.0, 10.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1213.xy = v.uv + Circle(14.0, 11.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1213.zw = v.uv + Circle(14.0, 12.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1415.xy = v.uv + Circle(14.0, 13.0, start) * _MainTex_TexelSize.xy * _BloomDownScale;
o.uv1415.zw = float2(0, 0);
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 Frag (v2f15 i) : SV_Target
{
half w = 1.0 / 15.0;
half3 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv89.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv89.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1011.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1011.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1213.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1213.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1415.xy).rgb * w;
return half4(col, 1.0);
}
ENDHLSL
}
// 1: 7 taps upsample
Pass
{
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Frag
// Upsampled texture
TEXTURE2D(_UpsampleTex); SAMPLER(sampler_UpsampleTex);
float4 _UpsampleTex_TexelSize;
float _BloomUpScaleUpper;
float _BloomUpScaleLower;
v2f15 Vertex(appdata v)
{
float start = 2.0;
v2f15 o;
o.uv01.xy = v.uv;
o.uv01.zw = v.uv + Circle(7.0, 0.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv23.xy = v.uv + Circle(7.0, 1.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv23.zw = v.uv + Circle(7.0, 2.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv45.xy = v.uv + Circle(7.0, 3.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv45.zw = v.uv + Circle(7.0, 4.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv67.xy = v.uv + Circle(7.0, 5.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv67.zw = v.uv + Circle(7.0, 6.0, start) * _MainTex_TexelSize.xy * _BloomUpScaleLower;
o.uv89.xy = v.uv + Circle(7.0, 0.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv89.zw = v.uv + Circle(7.0, 1.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1011.xy = v.uv + Circle(7.0, 2.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1011.zw = v.uv + Circle(7.0, 3.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1213.xy = v.uv + Circle(7.0, 4.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1213.zw = v.uv + Circle(7.0, 5.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1415.xy = v.uv + Circle(7.0, 6.0, start) * _UpsampleTex_TexelSize.xy * _BloomUpScaleUpper;
o.uv1415.zw = float2(0, 0);
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 Frag (v2f15 i) : SV_Target
{
half w = 1.0 / 15.0;
// Taps downsampled texture
half3 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.zw).rgb * w;
// Taps upsampled texture
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv01.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv89.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv89.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv1011.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv1011.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv1213.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv1213.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_UpsampleTex, sampler_UpsampleTex, i.uv1415.xy).rgb * w;
return half4(col, 1.0);
}
ENDHLSL
}
Pass
{
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Frag
TEXTURE2D(_BloomTex); SAMPLER(sampler_BloomTex);
float4 _BloomTex_TexelSize;
float _BloomIntensity;
v2f7 Vertex(appdata v)
{
float start = 2.0;
float Scale = 0.66/2.0;
v2f7 o;
o.uv01.xy = v.uv;
o.uv01.zw = v.uv + Circle(6.0, 0.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv23.xy = v.uv + Circle(6.0, 1.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv23.zw = v.uv + Circle(6.0, 2.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv45.xy = v.uv + Circle(6.0, 3.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv45.zw = v.uv + Circle(6.0, 4.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv67.xy = v.uv + Circle(6.0, 5.0, start) * _BloomTex_TexelSize.xy * Scale;
o.uv67.zw = float2(0.0, 0.0);
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 Frag (v2f7 i) : SV_Target
{
half w = 1.0 / 7.0;
half3 col = SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv01.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv01.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv23.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv23.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv45.xy).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv45.zw).rgb * w;
col += SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv67.xy).rgb * w;
half3 finalcolor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy).rgb;
finalcolor += col * _BloomIntensity;
return half4(finalcolor, 1.0);
}
ENDHLSL
}
}
}
Shader "Hidden/Downsample"
{
Properties
{
_MainTex ("Texture", any) = "" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Frag
#include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 uv01 : TEXCOORD0;
float4 uv23 : TEXCOORD1;
float4 vertex : SV_POSITION;
};
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
TEXTURE2D(_CameraDepthAttachment); SAMPLER(sampler_CameraDepthAttachment);
float4 _MainTex_TexelSize;
float4 _BloomThreshold;
v2f Vertex(appdata v)
{
v2f o;
o.uv01.xy = v.uv + float2(1.0, 1.0) * _MainTex_TexelSize.xy;
o.uv01.zw = v.uv + float2(-1.0, 1.0) * _MainTex_TexelSize.xy;
o.uv23.xy = v.uv + float2(1.0, -1.0) * _MainTex_TexelSize.xy;
o.uv23.zw = v.uv + float2(-1.0, -1.0) * _MainTex_TexelSize.xy;
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 Frag (v2f i) : SV_Target
{
half w = 1.0 / 4.0;
half3 c0 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy).rgb;
half3 c1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw).rgb;
half3 c2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy).rgb;
half3 c3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw).rgb;
half3 col = c0 * w + c1 * w + c2 * w + c3 * w;
col -= _BloomThreshold;
return half4(col, 1.0);
}
ENDHLSL
}
}
}
Shader "Hidden/Combine"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma multi_compile _ _BLOOM_ON
#pragma vertex Vertex
#pragma fragment Frag
#include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
float4 _MainTex_TexelSize;
TEXTURE2D(_BloomTex); SAMPLER(sampler_BloomTex);
float4 _BloomTex_TexelSize;
float _BloomIntensity;
float4 _BloomThreshold;
v2f Vertex(appdata v)
{
v2f o;
o.uv = v.uv;
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 Frag (v2f i) : SV_Target
{
half3 finalcolor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv).rgb;
#ifdef _BLOOM_ON
half3 bloomColor = SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, i.uv).rgb;
finalcolor = 1 - (1 - bloomColor) * (1 - finalcolor);
#endif
return half4(finalcolor, 1.0);
}
ENDHLSL
}
}
}
namespace UnityEngine.Rendering.LWRP
{
internal class ForwardRenderer : ScriptableRenderer
{
const int k_DepthStencilBufferBits = 32;
const string k_CreateCameraTextures = "Create Camera Texture";
DepthOnlyPass m_DepthPrepass;
MainLightShadowCasterPass m_MainLightShadowCasterPass;
AdditionalLightsShadowCasterPass m_AdditionalLightsShadowCasterPass;
ScreenSpaceShadowResolvePass m_ScreenSpaceShadowResolvePass;
RenderOpaqueForwardPass m_RenderOpaqueForwardPass;
DrawSkyboxPass m_DrawSkyboxPass;
CopyDepthPass m_CopyDepthPass;
CopyColorPass m_CopyColorPass;
RenderTransparentForwardPass m_RenderTransparentForwardPass;
FinalBlitPass m_FinalBlitPass;
CapturePass m_CapturePass;
ImageEffectsPass m_ImageeEffectsPass;
#if UNITY_EDITOR
SceneViewDepthCopyPass m_SceneViewDepthCopyPass;
#endif
RenderTargetHandle m_ActiveCameraColorAttachment;
RenderTargetHandle m_ActiveCameraDepthAttachment;
RenderTargetHandle m_CameraColorAttachment;
RenderTargetHandle m_CameraDepthAttachment;
RenderTargetHandle m_DepthTexture;
RenderTargetHandle m_OpaqueColor;
ForwardLights m_ForwardLights;
public ForwardRenderer(ForwardRendererData data) : base(data)
{
Downsampling downsamplingMethod = LightweightRenderPipeline.asset.opaqueDownsampling;
Material blitMaterial = CoreUtils.CreateEngineMaterial(data.blitShader);
Material copyDepthMaterial = CoreUtils.CreateEngineMaterial(data.copyDepthShader);
Material samplingMaterial = CoreUtils.CreateEngineMaterial(data.samplingShader);
Material screenspaceShadowsMaterial = CoreUtils.CreateEngineMaterial(data.screenSpaceShadowShader);
// Note: Since all custom render passes inject first and we have stable sort,
// we inject the builtin passes in the before events.
m_MainLightShadowCasterPass = new MainLightShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
m_AdditionalLightsShadowCasterPass = new AdditionalLightsShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
m_DepthPrepass = new DepthOnlyPass(RenderPassEvent.BeforeRenderingPrepasses, RenderQueueRange.opaque);
m_ScreenSpaceShadowResolvePass = new ScreenSpaceShadowResolvePass(RenderPassEvent.BeforeRenderingPrepasses, screenspaceShadowsMaterial);
m_RenderOpaqueForwardPass = new RenderOpaqueForwardPass(RenderPassEvent.BeforeRenderingOpaques, RenderQueueRange.opaque, data.opaqueLayerMask);
m_CopyDepthPass = new CopyDepthPass(RenderPassEvent.BeforeRenderingOpaques, copyDepthMaterial);
m_DrawSkyboxPass = new DrawSkyboxPass(RenderPassEvent.BeforeRenderingSkybox);
m_CopyColorPass = new CopyColorPass(RenderPassEvent.BeforeRenderingTransparents, samplingMaterial, downsamplingMethod);
m_RenderTransparentForwardPass = new RenderTransparentForwardPass(RenderPassEvent.BeforeRenderingTransparents, RenderQueueRange.transparent, data.transparentLayerMask);
m_CapturePass = new CapturePass(RenderPassEvent.AfterRendering);
m_FinalBlitPass = new FinalBlitPass(RenderPassEvent.AfterRendering, blitMaterial);
m_ImageeEffectsPass = new ImageEffectsPass(RenderPassEvent.AfterRendering);
#if UNITY_EDITOR
m_SceneViewDepthCopyPass = new SceneViewDepthCopyPass(RenderPassEvent.AfterRendering + 9, copyDepthMaterial);
#endif
// RenderTexture format depends on camera and pipeline (HDR, non HDR, etc)
// Samples (MSAA) depend on camera and pipeline
m_CameraColorAttachment.Init("_CameraColorTexture");
m_CameraDepthAttachment.Init("_CameraDepthAttachment");
m_DepthTexture.Init("_CameraDepthTexture");
m_OpaqueColor.Init("_CameraOpaqueTexture");
m_ForwardLights = new ForwardLights();
}
public override void Setup(ScriptableRenderContext context, ref RenderingData renderingData)
{
Camera camera = renderingData.cameraData.camera;
RenderTextureDescriptor cameraTargetDescriptor = renderingData.cameraData.cameraTargetDescriptor;
bool mainLightShadows = m_MainLightShadowCasterPass.Setup(ref renderingData);
bool additionalLightShadows = m_AdditionalLightsShadowCasterPass.Setup(ref renderingData);
bool resolveShadowsInScreenSpace = mainLightShadows && renderingData.shadowData.requiresScreenSpaceShadowResolve;
// Depth prepass is generated in the following cases:
// - We resolve shadows in screen space
// - Scene view camera always requires a depth texture. We do a depth pre-pass to simplify it and it shouldn't matter much for editor.
// - If game or offscreen camera requires it we check if we can copy the depth from the rendering opaques pass and use that instead.
bool requiresDepthPrepass = renderingData.cameraData.isSceneViewCamera ||
(renderingData.cameraData.requiresDepthTexture && (!CanCopyDepth(ref renderingData.cameraData)));
requiresDepthPrepass |= resolveShadowsInScreenSpace;
bool createColorTexture = RequiresIntermediateColorTexture(ref renderingData, cameraTargetDescriptor)
|| rendererFeatures.Count != 0;
// If camera requires depth and there's no depth pre-pass we create a depth texture that can be read
// later by effect requiring it.
bool createDepthTexture = renderingData.cameraData.requiresDepthTexture && !requiresDepthPrepass;
var imageEffects = renderingData.cameraData.camera.GetComponent<ImageEffects>();
bool usesImageEffects = imageEffects != null && imageEffects.enabled;
m_ActiveCameraColorAttachment = (usesImageEffects) ? m_CameraColorAttachment : RenderTargetHandle.CameraTarget;
m_ActiveCameraDepthAttachment = (usesImageEffects) ? m_CameraDepthAttachment : RenderTargetHandle.CameraTarget;
//if (createColorTexture || createDepthTexture)
CreateCameraRenderTarget(context, ref renderingData.cameraData);
ConfigureCameraTarget(m_ActiveCameraColorAttachment.Identifier(), m_ActiveCameraDepthAttachment.Identifier());
for (int i = 0; i < rendererFeatures.Count; ++i)
{
rendererFeatures[i].AddRenderPasses(this, ref renderingData);
}
int count = activeRenderPassQueue.Count;
for (int i = count - 1; i >= 0; i--)
{
if(activeRenderPassQueue[i] == null)
activeRenderPassQueue.RemoveAt(i);
}
bool hasAfterRendering = activeRenderPassQueue.Find(x => x.renderPassEvent == RenderPassEvent.AfterRendering) != null;
if (mainLightShadows)
EnqueuePass(m_MainLightShadowCasterPass);
if (additionalLightShadows)
EnqueuePass(m_AdditionalLightsShadowCasterPass);
if (requiresDepthPrepass)
{
m_DepthPrepass.Setup(cameraTargetDescriptor, m_DepthTexture);
EnqueuePass(m_DepthPrepass);
}
if (resolveShadowsInScreenSpace)
{
m_ScreenSpaceShadowResolvePass.Setup(cameraTargetDescriptor);
EnqueuePass(m_ScreenSpaceShadowResolvePass);
}
EnqueuePass(m_RenderOpaqueForwardPass);
if (camera.clearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null)
EnqueuePass(m_DrawSkyboxPass);
// If a depth texture was created we necessarily need to copy it, otherwise we could have render it to a renderbuffer
if (createDepthTexture)
{
m_CopyDepthPass.Setup(m_ActiveCameraDepthAttachment, m_DepthTexture);
EnqueuePass(m_CopyDepthPass);
}
if (renderingData.cameraData.requiresOpaqueTexture)
{
m_CopyColorPass.Setup(m_ActiveCameraColorAttachment.Identifier(), m_OpaqueColor);
EnqueuePass(m_CopyColorPass);
}
EnqueuePass(m_RenderTransparentForwardPass);
if(usesImageEffects)
{
m_ImageeEffectsPass.Setup(m_ActiveCameraColorAttachment, m_ActiveCameraDepthAttachment);
EnqueuePass(m_ImageeEffectsPass);
}
/*
bool afterRenderExists = renderingData.cameraData.captureActions != null ||
hasAfterRendering;
// if we have additional filters
// we need to stay in a RT
if (afterRenderExists)
{
// perform post with src / dest the same
if (postProcessEnabled)
{
m_PostProcessPass.Setup(cameraTargetDescriptor, m_ActiveCameraColorAttachment, m_ActiveCameraColorAttachment);
EnqueuePass(m_PostProcessPass);
}
//now blit into the final target
if (m_ActiveCameraColorAttachment != RenderTargetHandle.CameraTarget)
{
if (renderingData.cameraData.captureActions != null)
{
m_CapturePass.Setup(m_ActiveCameraColorAttachment);
EnqueuePass(m_CapturePass);
}
m_FinalBlitPass.Setup(cameraTargetDescriptor, m_ActiveCameraColorAttachment);
EnqueuePass(m_FinalBlitPass);
}
}
else
{
if (postProcessEnabled)
{
m_PostProcessPass.Setup(cameraTargetDescriptor, m_ActiveCameraColorAttachment, RenderTargetHandle.CameraTarget);
EnqueuePass(m_PostProcessPass);
}
else if (m_ActiveCameraColorAttachment != RenderTargetHandle.CameraTarget)
{
m_FinalBlitPass.Setup(cameraTargetDescriptor, m_ActiveCameraColorAttachment);
EnqueuePass(m_FinalBlitPass);
}
}
*/
#if UNITY_EDITOR
if (renderingData.cameraData.isSceneViewCamera)
{
m_SceneViewDepthCopyPass.Setup(m_DepthTexture);
EnqueuePass(m_SceneViewDepthCopyPass);
}
#endif
}
public override void SetupLights(ScriptableRenderContext context, ref RenderingData renderingData)
{
m_ForwardLights.Setup(context, ref renderingData);
}
public override void SetupCullingParameters(ref ScriptableCullingParameters cullingParameters,
ref CameraData cameraData)
{
Camera camera = cameraData.camera;
// TODO: PerObjectCulling also affect reflection probes. Enabling it for now.
// if (asset.additionalLightsRenderingMode == LightRenderingMode.Disabled ||
// asset.maxAdditionalLightsCount == 0)
// {
// cullingParameters.cullingOptions |= CullingOptions.DisablePerObjectCulling;
// }
cullingParameters.shadowDistance = Mathf.Min(cameraData.maxShadowDistance, camera.farClipPlane);
}
public override void FinishRendering(CommandBuffer cmd)
{
if (m_ActiveCameraColorAttachment != RenderTargetHandle.CameraTarget)
cmd.ReleaseTemporaryRT(m_ActiveCameraColorAttachment.id);
if (m_ActiveCameraDepthAttachment != RenderTargetHandle.CameraTarget)
cmd.ReleaseTemporaryRT(m_ActiveCameraDepthAttachment.id);
}
void CreateCameraRenderTarget(ScriptableRenderContext context, ref CameraData cameraData)
{
CommandBuffer cmd = CommandBufferPool.Get(k_CreateCameraTextures);
var descriptor = cameraData.cameraTargetDescriptor;
int msaaSamples = descriptor.msaaSamples;
if (m_ActiveCameraColorAttachment != RenderTargetHandle.CameraTarget)
{
bool useDepthRenderBuffer = m_ActiveCameraDepthAttachment == RenderTargetHandle.CameraTarget;
var colorDescriptor = descriptor;
colorDescriptor.depthBufferBits = (useDepthRenderBuffer) ? k_DepthStencilBufferBits : 0;
cmd.GetTemporaryRT(m_ActiveCameraColorAttachment.id, colorDescriptor, FilterMode.Bilinear);
}
if (m_ActiveCameraDepthAttachment != RenderTargetHandle.CameraTarget)
{
var depthDescriptor = descriptor;
depthDescriptor.colorFormat = RenderTextureFormat.Depth;
depthDescriptor.depthBufferBits = k_DepthStencilBufferBits;
depthDescriptor.bindMS = msaaSamples > 1 && !SystemInfo.supportsMultisampleAutoResolve && (SystemInfo.supportsMultisampledTextures != 0);
cmd.GetTemporaryRT(m_ActiveCameraDepthAttachment.id, depthDescriptor, FilterMode.Point);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
bool RequiresIntermediateColorTexture(ref RenderingData renderingData, RenderTextureDescriptor baseDescriptor)
{
ref CameraData cameraData = ref renderingData.cameraData;
int msaaSamples = cameraData.cameraTargetDescriptor.msaaSamples;
bool isScaledRender = !Mathf.Approximately(cameraData.renderScale, 1.0f);
bool isTargetTexture2DArray = baseDescriptor.dimension == TextureDimension.Tex2DArray;
bool requiresExplicitMsaaResolve = msaaSamples > 1 && !SystemInfo.supportsMultisampleAutoResolve;
bool isOffscreenRender = cameraData.camera.targetTexture != null && !cameraData.isSceneViewCamera;
bool isCapturing = cameraData.captureActions != null;
bool requiresBlitForOffscreenCamera = cameraData.requiresOpaqueTexture || requiresExplicitMsaaResolve;
if (isOffscreenRender)
return requiresBlitForOffscreenCamera;
return requiresBlitForOffscreenCamera || cameraData.isSceneViewCamera || isScaledRender || cameraData.isHdrEnabled ||
isTargetTexture2DArray || !cameraData.isDefaultViewport || isCapturing || Display.main.requiresBlitToBackbuffer
|| renderingData.killAlphaInFinalBlit;
}
bool CanCopyDepth(ref CameraData cameraData)
{
bool msaaEnabledForCamera = cameraData.cameraTargetDescriptor.msaaSamples > 1;
bool supportsTextureCopy = SystemInfo.copyTextureSupport != CopyTextureSupport.None;
bool supportsDepthTarget = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.Depth);
bool supportsDepthCopy = !msaaEnabledForCamera && (supportsDepthTarget || supportsTextureCopy);
// TODO: We don't have support to highp Texture2DMS currently and this breaks depth precision.
// currently disabling it until shader changes kick in.
//bool msaaDepthResolve = msaaEnabledForCamera && SystemInfo.supportsMultisampledTextures != 0;
bool msaaDepthResolve = false;
return supportsDepthCopy || msaaDepthResolve;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
public class ImageEffects : MonoBehaviour
{
public Shader boxFilterShader;
public Shader bloomShader;
public Shader combinePassShader;
public bool enableBloom = true;
public Color bloomThreshold = new Color(0.8f, 0.8f, 0.8f);
public float bloomDownsampleScale = 2f;
public float bloomUpsampleScaleLower = 2f;
public float bloomUpsampleScaleUpper = 2f;
public float bloomIntensity = 1.2f;
void OnEnable()
{
InitPassInit();
BloomInit();
CombinePassInit();
}
void OnDisable()
{
BloomRelease();
CombinePassRelese();
}
public void Render(CommandBuffer cmd,
RenderTargetIdentifier colorTexture,
RenderTargetIdentifier depthTexture,
RenderTextureDescriptor cameraTargetDescriptor)
{
cmd.SetGlobalColor("_BloomThreshold", bloomThreshold);
cmd.SetGlobalFloat("_BloomDownScale", bloomDownsampleScale);
cmd.SetGlobalFloat("_BloomUpScaleLower", bloomUpsampleScaleLower);
cmd.SetGlobalFloat("_BloomUpScaleUpper", bloomUpsampleScaleUpper);
cmd.SetGlobalFloat("_BloomIntensity", bloomIntensity);
//Downsample to 1/4 first
InitPass(cmd, colorTexture, depthTexture, cameraTargetDescriptor);
if (enableBloom) RenderBloom(cmd, colorTexture, depthTexture, cameraTargetDescriptor);
CombinePass(cmd, colorTexture, depthTexture, cameraTargetDescriptor);
}
public void CleanUp(CommandBuffer cmd)
{
InitPassCleanUp(cmd);
BloomCleanUp(cmd);
}
private Material downsampleMaterial;
private int downsampleTmpRTId;
private RenderTargetIdentifier downsampleTmpRT;
private void InitPassInit()
{
downsampleMaterial = new Material(boxFilterShader);
downsampleTmpRTId = Shader.PropertyToID("_Downsample4Texture");
downsampleTmpRT = new RenderTargetIdentifier(downsampleTmpRTId);
}
private void InitPassCleanUp(CommandBuffer cmd)
{
cmd.ReleaseTemporaryRT(downsampleTmpRTId);
}
private void InitPass(CommandBuffer cmd,
RenderTargetIdentifier colorTexture,
RenderTargetIdentifier depthTexture,
RenderTextureDescriptor cameraTargetDescriptor)
{
var desc = cameraTargetDescriptor;
desc.width /= 4;
desc.height /= 4;
desc.depthBufferBits = 0;
desc.msaaSamples = 1;
cmd.GetTemporaryRT(downsampleTmpRTId, desc, FilterMode.Bilinear);
cmd.Blit(colorTexture, downsampleTmpRTId, downsampleMaterial, 0);
}
private Material bloomMaterial;
private int[] bloomRTIds;
private RenderTargetIdentifier[] bloomRTIdentifiers;
private void BloomInit()
{
bloomMaterial = new Material(bloomShader);
bloomRTIds = new int[7]
{
Shader.PropertyToID("_BloomDownSampled8"),
Shader.PropertyToID("_BloomDownSampled16"),
Shader.PropertyToID("_BloomDownSampled32"),
Shader.PropertyToID("_BloomDownSampled64"),
Shader.PropertyToID("_BloomUpSampled32"),
Shader.PropertyToID("_BloomUpSampled16"),
Shader.PropertyToID("_BloomUpSampled8"),
};
bloomRTIdentifiers = new RenderTargetIdentifier[7]
{
new RenderTargetIdentifier(bloomRTIds[0]),
new RenderTargetIdentifier(bloomRTIds[1]),
new RenderTargetIdentifier(bloomRTIds[2]),
new RenderTargetIdentifier(bloomRTIds[3]),
new RenderTargetIdentifier(bloomRTIds[4]),
new RenderTargetIdentifier(bloomRTIds[5]),
new RenderTargetIdentifier(bloomRTIds[6]),
};
}
private void BloomCleanUp(CommandBuffer cmd)
{
if (bloomRTIds != null && bloomRTIds.Length > 0)
{
for (int i = 0; i < bloomRTIds.Length; i++)
{
cmd.ReleaseTemporaryRT(bloomRTIds[i]);
}
}
}
private void BloomRelease()
{
bloomMaterial = null;
bloomRTIds = null;
bloomRTIdentifiers = null;
}
private void RenderBloom(CommandBuffer cmd,
RenderTargetIdentifier colorTexture,
RenderTargetIdentifier depthTexture,
RenderTextureDescriptor cameraTargetDescriptor)
{
var desc = cameraTargetDescriptor;
desc.depthBufferBits = 0;
desc.msaaSamples = 1;
desc.width /= 8;
desc.height /= 8;
// 1/8 x 1/8
cmd.GetTemporaryRT(bloomRTIds[0], desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(bloomRTIds[6], desc, FilterMode.Bilinear);
// 1/16 x 1/16
desc.width /= 2;
desc.height /= 2;
cmd.GetTemporaryRT(bloomRTIds[1], desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(bloomRTIds[5], desc, FilterMode.Bilinear);
// 1/32 x 1/32
desc.width /= 2;
desc.height /= 2;
cmd.GetTemporaryRT(bloomRTIds[2], desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(bloomRTIds[4], desc, FilterMode.Bilinear);
// 1/64 x 1/64
desc.width /= 2;
desc.height /= 2;
cmd.GetTemporaryRT(bloomRTIds[3], desc, FilterMode.Bilinear);
// Downsamples
// 1/4 x 1/4 -> 1/8 x 1/8
cmd.Blit(downsampleTmpRTId, bloomRTIds[0], bloomMaterial, 0);
// 1/8 x 1/8 -> 1/16 x 1/16
cmd.Blit(bloomRTIds[0], bloomRTIds[1], bloomMaterial, 0);
// 1/16 x 1/16 -> 1/32 x 1/32
cmd.Blit(bloomRTIds[1], bloomRTIds[2], bloomMaterial, 0);
// 1/32 x 1/32 -> 1/64 x 1/64
cmd.Blit(bloomRTIds[2], bloomRTIds[3], bloomMaterial, 0);
// Upsamples
// 1/64 x 1/64 -> 1/32 x 1/32
cmd.SetGlobalTexture("_UpsampleTex", bloomRTIds[2]);
cmd.Blit(bloomRTIds[3], bloomRTIds[4], bloomMaterial, 1);
// 1/32 x 1/32 -> 1/16 x 1/16
cmd.SetGlobalTexture("_UpsampleTex", bloomRTIds[1]);
cmd.Blit(bloomRTIds[4], bloomRTIds[5], bloomMaterial, 1);
// 1/16 x 1/16 -> 1/8 x 1/8
cmd.SetGlobalTexture("_UpsampleTex", bloomRTIds[0]);
cmd.Blit(bloomRTIds[5], bloomRTIds[6], bloomMaterial, 1);
}
Material combinePassMaterial;
private void CombinePassInit()
{
combinePassMaterial = new Material(combinePassShader);
}
private void CombinePassRelese()
{
combinePassMaterial = null;
}
private void CombinePass(CommandBuffer cmd,
RenderTargetIdentifier colorTexture,
RenderTargetIdentifier depthTexture,
RenderTextureDescriptor cameraTargetDescriptor)
{
if(enableBloom)
{
combinePassMaterial.EnableKeyword("_BLOOM_ON");
cmd.SetGlobalTexture("_BloomTex", bloomRTIds[6]);
}
else
{
combinePassMaterial.DisableKeyword("_BLOOM_ON");
}
cmd.Blit(colorTexture, BuiltinRenderTextureType.CameraTarget, combinePassMaterial, 0);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.LWRP;
public class ImageEffectsPass : ScriptableRenderPass
{
public const string PASS_NAME = "ImageEffectsPass";
private RenderTargetHandle colorHandle;
private RenderTargetHandle depthHandle;
private Stack<ImageEffects> runEffects;
public ImageEffectsPass(RenderPassEvent evnt) : base()
{
renderPassEvent = evnt;
runEffects = new Stack<ImageEffects>();
}
public void Setup(RenderTargetHandle colorHandle, RenderTargetHandle depthHandle)
{
this.colorHandle = colorHandle;
this.depthHandle = depthHandle;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(PASS_NAME);
CoreUtils.SetRenderTarget(cmd, BuiltinRenderTextureType.CameraTarget);
var effects = renderingData.cameraData.camera.GetComponent<ImageEffects>();
if (renderingData.cameraData.isSceneViewCamera || effects == null || !effects.enabled)
{
cmd.Blit(colorHandle.Identifier(), BuiltinRenderTextureType.CameraTarget);
}
else
{
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
effects.Render(cmd, colorHandle.Identifier(), depthHandle.Identifier(), descriptor);
runEffects.Push(effects);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd)
{
//cmd.ReleaseTemporaryRT(tempHandle.id);
while(runEffects.Count > 0)
{
ImageEffects effects = runEffects.Pop();
effects.CleanUp(cmd);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment