using System; using UnityEngine.Rendering; namespace UnityEngine.PostProcessing { public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer { private AmbientOcclusionComponent.OcclusionSource occlusionSource { get { if (this.context.isGBufferAvailable && !base.model.settings.forceForwardCompatibility) { return AmbientOcclusionComponent.OcclusionSource.GBuffer; } if (base.model.settings.highPrecision && (!this.context.isGBufferAvailable || base.model.settings.forceForwardCompatibility)) { return AmbientOcclusionComponent.OcclusionSource.DepthTexture; } return AmbientOcclusionComponent.OcclusionSource.DepthNormalsTexture; } } private bool ambientOnlySupported { get { return this.context.isHdr && base.model.settings.ambientOnly && this.context.isGBufferAvailable && !base.model.settings.forceForwardCompatibility; } } public override bool active { get { return base.model.enabled && base.model.settings.intensity > 0f && !this.context.interrupted; } } public override DepthTextureMode GetCameraFlags() { DepthTextureMode depthTextureMode = DepthTextureMode.None; if (this.occlusionSource == AmbientOcclusionComponent.OcclusionSource.DepthTexture) { depthTextureMode |= DepthTextureMode.Depth; } if (this.occlusionSource != AmbientOcclusionComponent.OcclusionSource.GBuffer) { depthTextureMode |= DepthTextureMode.DepthNormals; } return depthTextureMode; } public override string GetName() { return "Ambient Occlusion"; } public override CameraEvent GetCameraEvent() { return (!this.ambientOnlySupported || this.context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.AmbientOcclusion)) ? CameraEvent.BeforeImageEffectsOpaque : CameraEvent.BeforeReflections; } public override void PopulateCommandBuffer(CommandBuffer cb) { AmbientOcclusionModel.Settings settings = base.model.settings; Material mat = this.context.materialFactory.Get("Hidden/Post FX/Blit"); Material material = this.context.materialFactory.Get("Hidden/Post FX/Ambient Occlusion"); material.shaderKeywords = null; material.SetFloat(AmbientOcclusionComponent.Uniforms._Intensity, settings.intensity); material.SetFloat(AmbientOcclusionComponent.Uniforms._Radius, settings.radius); material.SetFloat(AmbientOcclusionComponent.Uniforms._Downsample, (!settings.downsampling) ? 1f : 0.5f); material.SetInt(AmbientOcclusionComponent.Uniforms._SampleCount, (int)settings.sampleCount); if (!this.context.isGBufferAvailable && RenderSettings.fog) { material.SetVector(AmbientOcclusionComponent.Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance)); FogMode fogMode = RenderSettings.fogMode; if (fogMode != FogMode.Linear) { if (fogMode != FogMode.Exponential) { if (fogMode == FogMode.ExponentialSquared) { material.EnableKeyword("FOG_EXP2"); } } else { material.EnableKeyword("FOG_EXP"); } } else { material.EnableKeyword("FOG_LINEAR"); } } else { material.EnableKeyword("FOG_OFF"); } int width = this.context.width; int height = this.context.height; int num = (!settings.downsampling) ? 1 : 2; int nameID = AmbientOcclusionComponent.Uniforms._OcclusionTexture1; cb.GetTemporaryRT(nameID, width / num, height / num, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); cb.Blit(null, nameID, material, (int)this.occlusionSource); int occlusionTexture = AmbientOcclusionComponent.Uniforms._OcclusionTexture2; cb.GetTemporaryRT(occlusionTexture, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); cb.SetGlobalTexture(AmbientOcclusionComponent.Uniforms._MainTex, nameID); cb.Blit(nameID, occlusionTexture, material, (this.occlusionSource != AmbientOcclusionComponent.OcclusionSource.GBuffer) ? 3 : 4); cb.ReleaseTemporaryRT(nameID); nameID = AmbientOcclusionComponent.Uniforms._OcclusionTexture; cb.GetTemporaryRT(nameID, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); cb.SetGlobalTexture(AmbientOcclusionComponent.Uniforms._MainTex, occlusionTexture); cb.Blit(occlusionTexture, nameID, material, 5); cb.ReleaseTemporaryRT(occlusionTexture); if (this.context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.AmbientOcclusion)) { cb.SetGlobalTexture(AmbientOcclusionComponent.Uniforms._MainTex, nameID); cb.Blit(nameID, BuiltinRenderTextureType.CameraTarget, material, 8); this.context.Interrupt(); } else if (this.ambientOnlySupported) { cb.SetRenderTarget(this.m_MRT, BuiltinRenderTextureType.CameraTarget); cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7); } else { RenderTextureFormat format = (!this.context.isHdr) ? RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR; int tempRT = AmbientOcclusionComponent.Uniforms._TempRT; cb.GetTemporaryRT(tempRT, this.context.width, this.context.height, 0, FilterMode.Bilinear, format); cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0); cb.SetGlobalTexture(AmbientOcclusionComponent.Uniforms._MainTex, tempRT); cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6); cb.ReleaseTemporaryRT(tempRT); } cb.ReleaseTemporaryRT(nameID); } private const string k_BlitShaderString = "Hidden/Post FX/Blit"; private const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion"; private readonly RenderTargetIdentifier[] m_MRT = new RenderTargetIdentifier[] { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.CameraTarget }; private 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"); } private enum OcclusionSource { DepthTexture, DepthNormalsTexture, GBuffer } } }