| | |
| | | using UnityEngine.Rendering; |
| | | |
| | | namespace UnityEngine.PostProcessing |
| | | { |
| | | using DebugMode = BuiltinDebugViewsModel.Mode; |
| | | |
| | | public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer<AmbientOcclusionModel> |
| | | { |
| | | static class Uniforms |
| | | { |
| | | internal static readonly int _Intensity = Shader.PropertyToID("_Intensity"); |
| | | internal static readonly int _Radius = Shader.PropertyToID("_Radius"); |
| | | internal static readonly int _FogParams = Shader.PropertyToID("_FogParams"); |
| | | internal static readonly int _Downsample = Shader.PropertyToID("_Downsample"); |
| | | internal static readonly int _SampleCount = Shader.PropertyToID("_SampleCount"); |
| | | internal static readonly int _OcclusionTexture1 = Shader.PropertyToID("_OcclusionTexture1"); |
| | | internal static readonly int _OcclusionTexture2 = Shader.PropertyToID("_OcclusionTexture2"); |
| | | internal static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture"); |
| | | internal static readonly int _MainTex = Shader.PropertyToID("_MainTex"); |
| | | internal static readonly int _TempRT = Shader.PropertyToID("_TempRT"); |
| | | } |
| | | |
| | | const string k_BlitShaderString = "Hidden/Post FX/Blit"; |
| | | const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion"; |
| | | |
| | | readonly RenderTargetIdentifier[] m_MRT = |
| | | { |
| | | BuiltinRenderTextureType.GBuffer0, // Albedo, Occ |
| | | BuiltinRenderTextureType.CameraTarget // Ambient |
| | | }; |
| | | |
| | | enum OcclusionSource |
| | | { |
| | | DepthTexture, |
| | | DepthNormalsTexture, |
| | | GBuffer |
| | | } |
| | | |
| | | OcclusionSource occlusionSource |
| | | { |
| | | get |
| | | { |
| | | if (context.isGBufferAvailable && !model.settings.forceForwardCompatibility) |
| | | return OcclusionSource.GBuffer; |
| | | |
| | | if (model.settings.highPrecision && (!context.isGBufferAvailable || model.settings.forceForwardCompatibility)) |
| | | return OcclusionSource.DepthTexture; |
| | | |
| | | return OcclusionSource.DepthNormalsTexture; |
| | | } |
| | | } |
| | | |
| | | bool ambientOnlySupported |
| | | { |
| | | get { return context.isHdr && model.settings.ambientOnly && context.isGBufferAvailable && !model.settings.forceForwardCompatibility; } |
| | | } |
| | | |
| | | public override bool active |
| | | { |
| | | get |
| | | { |
| | | return model.enabled |
| | | && model.settings.intensity > 0f |
| | | && !context.interrupted; |
| | | } |
| | | } |
| | | |
| | | public override DepthTextureMode GetCameraFlags() |
| | | { |
| | | var flags = DepthTextureMode.None; |
| | | |
| | | if (occlusionSource == OcclusionSource.DepthTexture) |
| | | flags |= DepthTextureMode.Depth; |
| | | |
| | | if (occlusionSource != OcclusionSource.GBuffer) |
| | | flags |= DepthTextureMode.DepthNormals; |
| | | |
| | | return flags; |
| | | } |
| | | |
| | | public override string GetName() |
| | | { |
| | | return "Ambient Occlusion"; |
| | | } |
| | | |
| | | public override CameraEvent GetCameraEvent() |
| | | { |
| | | return ambientOnlySupported && !context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion) |
| | | ? CameraEvent.BeforeReflections |
| | | : CameraEvent.BeforeImageEffectsOpaque; |
| | | } |
| | | |
| | | public override void PopulateCommandBuffer(CommandBuffer cb) |
| | | { |
| | | var settings = model.settings; |
| | | |
| | | // Material setup |
| | | var blitMaterial = context.materialFactory.Get(k_BlitShaderString); |
| | | |
| | | var material = context.materialFactory.Get(k_ShaderString); |
| | | material.shaderKeywords = null; |
| | | material.SetFloat(Uniforms._Intensity, settings.intensity); |
| | | material.SetFloat(Uniforms._Radius, settings.radius); |
| | | material.SetFloat(Uniforms._Downsample, settings.downsampling ? 0.5f : 1f); |
| | | material.SetInt(Uniforms._SampleCount, (int)settings.sampleCount); |
| | | |
| | | if (!context.isGBufferAvailable && RenderSettings.fog) |
| | | { |
| | | material.SetVector(Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance)); |
| | | |
| | | switch (RenderSettings.fogMode) |
| | | { |
| | | case FogMode.Linear: |
| | | material.EnableKeyword("FOG_LINEAR"); |
| | | break; |
| | | case FogMode.Exponential: |
| | | material.EnableKeyword("FOG_EXP"); |
| | | break; |
| | | case FogMode.ExponentialSquared: |
| | | material.EnableKeyword("FOG_EXP2"); |
| | | break; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | material.EnableKeyword("FOG_OFF"); |
| | | } |
| | | |
| | | int tw = context.width; |
| | | int th = context.height; |
| | | int ts = settings.downsampling ? 2 : 1; |
| | | const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32; |
| | | const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear; |
| | | const FilterMode kFilter = FilterMode.Bilinear; |
| | | |
| | | // AO buffer |
| | | var rtMask = Uniforms._OcclusionTexture1; |
| | | cb.GetTemporaryRT(rtMask, tw / ts, th / ts, 0, kFilter, kFormat, kRWMode); |
| | | |
| | | // AO estimation |
| | | cb.Blit((Texture)null, rtMask, material, (int)occlusionSource); |
| | | |
| | | // Blur buffer |
| | | var rtBlur = Uniforms._OcclusionTexture2; |
| | | |
| | | // Separable blur (horizontal pass) |
| | | cb.GetTemporaryRT(rtBlur, tw, th, 0, kFilter, kFormat, kRWMode); |
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtMask); |
| | | cb.Blit(rtMask, rtBlur, material, occlusionSource == OcclusionSource.GBuffer ? 4 : 3); |
| | | cb.ReleaseTemporaryRT(rtMask); |
| | | |
| | | // Separable blur (vertical pass) |
| | | rtMask = Uniforms._OcclusionTexture; |
| | | cb.GetTemporaryRT(rtMask, tw, th, 0, kFilter, kFormat, kRWMode); |
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtBlur); |
| | | cb.Blit(rtBlur, rtMask, material, 5); |
| | | cb.ReleaseTemporaryRT(rtBlur); |
| | | |
| | | if (context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion)) |
| | | { |
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtMask); |
| | | cb.Blit(rtMask, BuiltinRenderTextureType.CameraTarget, material, 8); |
| | | context.Interrupt(); |
| | | } |
| | | else if (ambientOnlySupported) |
| | | { |
| | | cb.SetRenderTarget(m_MRT, BuiltinRenderTextureType.CameraTarget); |
| | | cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7); |
| | | } |
| | | else |
| | | { |
| | | var fbFormat = context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default; |
| | | |
| | | int tempRT = Uniforms._TempRT; |
| | | cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear, fbFormat); |
| | | cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, blitMaterial, 0); |
| | | cb.SetGlobalTexture(Uniforms._MainTex, tempRT); |
| | | cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6); |
| | | cb.ReleaseTemporaryRT(tempRT); |
| | | } |
| | | |
| | | cb.ReleaseTemporaryRT(rtMask); |
| | | } |
| | | } |
| | | } |
| | | using UnityEngine.Rendering;
|
| | |
|
| | | namespace UnityEngine.PostProcessing
|
| | | {
|
| | | using DebugMode = BuiltinDebugViewsModel.Mode;
|
| | |
|
| | | public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer<AmbientOcclusionModel>
|
| | | {
|
| | | static class Uniforms
|
| | | {
|
| | | internal static readonly int _Intensity = Shader.PropertyToID("_Intensity");
|
| | | internal static readonly int _Radius = Shader.PropertyToID("_Radius");
|
| | | internal static readonly int _FogParams = Shader.PropertyToID("_FogParams");
|
| | | internal static readonly int _Downsample = Shader.PropertyToID("_Downsample");
|
| | | internal static readonly int _SampleCount = Shader.PropertyToID("_SampleCount");
|
| | | internal static readonly int _OcclusionTexture1 = Shader.PropertyToID("_OcclusionTexture1");
|
| | | internal static readonly int _OcclusionTexture2 = Shader.PropertyToID("_OcclusionTexture2");
|
| | | internal static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture");
|
| | | internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
| | | internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
|
| | | }
|
| | |
|
| | | const string k_BlitShaderString = "Hidden/Post FX/Blit";
|
| | | const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion";
|
| | |
|
| | | readonly RenderTargetIdentifier[] m_MRT =
|
| | | {
|
| | | BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
|
| | | BuiltinRenderTextureType.CameraTarget // Ambient
|
| | | };
|
| | |
|
| | | enum OcclusionSource
|
| | | {
|
| | | DepthTexture,
|
| | | DepthNormalsTexture,
|
| | | GBuffer
|
| | | }
|
| | |
|
| | | OcclusionSource occlusionSource
|
| | | {
|
| | | get
|
| | | {
|
| | | if (context.isGBufferAvailable && !model.settings.forceForwardCompatibility)
|
| | | return OcclusionSource.GBuffer;
|
| | |
|
| | | if (model.settings.highPrecision && (!context.isGBufferAvailable || model.settings.forceForwardCompatibility))
|
| | | return OcclusionSource.DepthTexture;
|
| | |
|
| | | return OcclusionSource.DepthNormalsTexture;
|
| | | }
|
| | | }
|
| | |
|
| | | bool ambientOnlySupported
|
| | | {
|
| | | get { return context.isHdr && model.settings.ambientOnly && context.isGBufferAvailable && !model.settings.forceForwardCompatibility; }
|
| | | }
|
| | |
|
| | | public override bool active
|
| | | {
|
| | | get
|
| | | {
|
| | | return model.enabled
|
| | | && model.settings.intensity > 0f
|
| | | && !context.interrupted;
|
| | | }
|
| | | }
|
| | |
|
| | | public override DepthTextureMode GetCameraFlags()
|
| | | {
|
| | | var flags = DepthTextureMode.None;
|
| | |
|
| | | if (occlusionSource == OcclusionSource.DepthTexture)
|
| | | flags |= DepthTextureMode.Depth;
|
| | |
|
| | | if (occlusionSource != OcclusionSource.GBuffer)
|
| | | flags |= DepthTextureMode.DepthNormals;
|
| | |
|
| | | return flags;
|
| | | }
|
| | |
|
| | | public override string GetName()
|
| | | {
|
| | | return "Ambient Occlusion";
|
| | | }
|
| | |
|
| | | public override CameraEvent GetCameraEvent()
|
| | | {
|
| | | return ambientOnlySupported && !context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion)
|
| | | ? CameraEvent.BeforeReflections
|
| | | : CameraEvent.BeforeImageEffectsOpaque;
|
| | | }
|
| | |
|
| | | public override void PopulateCommandBuffer(CommandBuffer cb)
|
| | | {
|
| | | var settings = model.settings;
|
| | |
|
| | | // Material setup
|
| | | var blitMaterial = context.materialFactory.Get(k_BlitShaderString);
|
| | |
|
| | | var material = context.materialFactory.Get(k_ShaderString);
|
| | | material.shaderKeywords = null;
|
| | | material.SetFloat(Uniforms._Intensity, settings.intensity);
|
| | | material.SetFloat(Uniforms._Radius, settings.radius);
|
| | | material.SetFloat(Uniforms._Downsample, settings.downsampling ? 0.5f : 1f);
|
| | | material.SetInt(Uniforms._SampleCount, (int)settings.sampleCount);
|
| | |
|
| | | if (!context.isGBufferAvailable && RenderSettings.fog)
|
| | | {
|
| | | material.SetVector(Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance));
|
| | |
|
| | | switch (RenderSettings.fogMode)
|
| | | {
|
| | | case FogMode.Linear:
|
| | | material.EnableKeyword("FOG_LINEAR");
|
| | | break;
|
| | | case FogMode.Exponential:
|
| | | material.EnableKeyword("FOG_EXP");
|
| | | break;
|
| | | case FogMode.ExponentialSquared:
|
| | | material.EnableKeyword("FOG_EXP2");
|
| | | break;
|
| | | }
|
| | | }
|
| | | else
|
| | | {
|
| | | material.EnableKeyword("FOG_OFF");
|
| | | }
|
| | |
|
| | | int tw = context.width;
|
| | | int th = context.height;
|
| | | int ts = settings.downsampling ? 2 : 1;
|
| | | const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32;
|
| | | const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear;
|
| | | const FilterMode kFilter = FilterMode.Bilinear;
|
| | |
|
| | | // AO buffer
|
| | | var rtMask = Uniforms._OcclusionTexture1;
|
| | | cb.GetTemporaryRT(rtMask, tw / ts, th / ts, 0, kFilter, kFormat, kRWMode);
|
| | |
|
| | | // AO estimation
|
| | | cb.Blit((Texture)null, rtMask, material, (int)occlusionSource);
|
| | |
|
| | | // Blur buffer
|
| | | var rtBlur = Uniforms._OcclusionTexture2;
|
| | |
|
| | | // Separable blur (horizontal pass)
|
| | | cb.GetTemporaryRT(rtBlur, tw, th, 0, kFilter, kFormat, kRWMode);
|
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
|
| | | cb.Blit(rtMask, rtBlur, material, occlusionSource == OcclusionSource.GBuffer ? 4 : 3);
|
| | | cb.ReleaseTemporaryRT(rtMask);
|
| | |
|
| | | // Separable blur (vertical pass)
|
| | | rtMask = Uniforms._OcclusionTexture;
|
| | | cb.GetTemporaryRT(rtMask, tw, th, 0, kFilter, kFormat, kRWMode);
|
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtBlur);
|
| | | cb.Blit(rtBlur, rtMask, material, 5);
|
| | | cb.ReleaseTemporaryRT(rtBlur);
|
| | |
|
| | | if (context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion))
|
| | | {
|
| | | cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
|
| | | cb.Blit(rtMask, BuiltinRenderTextureType.CameraTarget, material, 8);
|
| | | context.Interrupt();
|
| | | }
|
| | | else if (ambientOnlySupported)
|
| | | {
|
| | | cb.SetRenderTarget(m_MRT, BuiltinRenderTextureType.CameraTarget);
|
| | | cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7);
|
| | | }
|
| | | else
|
| | | {
|
| | | var fbFormat = context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
|
| | |
|
| | | int tempRT = Uniforms._TempRT;
|
| | | cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear, fbFormat);
|
| | | cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, blitMaterial, 0);
|
| | | cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
| | | cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6);
|
| | | cb.ReleaseTemporaryRT(tempRT);
|
| | | }
|
| | |
|
| | | cb.ReleaseTemporaryRT(rtMask);
|
| | | }
|
| | | }
|
| | | }
|