Last active
August 27, 2024 02:43
-
-
Save CarlLee/4ef88caa0d39c36eda9e3b8e06751bab to your computer and use it in GitHub Desktop.
UE4 bloom for unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
大佬啊。。