diff options
Diffstat (limited to 'AmplifyOcclusionBase.cs')
-rw-r--r-- | AmplifyOcclusionBase.cs | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/AmplifyOcclusionBase.cs b/AmplifyOcclusionBase.cs new file mode 100644 index 0000000..e429102 --- /dev/null +++ b/AmplifyOcclusionBase.cs @@ -0,0 +1,951 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +[AddComponentMenu("")] +public class AmplifyOcclusionBase : MonoBehaviour +{ + public enum ApplicationMethod + { + PostEffect, + Deferred, + Debug + } + + public enum PerPixelNormalSource + { + None, + Camera, + GBuffer, + GBufferOctaEncoded + } + + public enum SampleCountLevel + { + Low, + Medium, + High, + VeryHigh + } + + private static class ShaderPass + { + public const int FullDepth = 0; + + public const int FullNormal_None = 1; + + public const int FullNormal_Camera = 2; + + public const int FullNormal_GBuffer = 3; + + public const int FullNormal_GBufferOctaEncoded = 4; + + public const int DeinterleaveDepth1 = 5; + + public const int DeinterleaveNormal1_None = 6; + + public const int DeinterleaveNormal1_Camera = 7; + + public const int DeinterleaveNormal1_GBuffer = 8; + + public const int DeinterleaveNormal1_GBufferOctaEncoded = 9; + + public const int DeinterleaveDepth4 = 10; + + public const int DeinterleaveNormal4_None = 11; + + public const int DeinterleaveNormal4_Camera = 12; + + public const int DeinterleaveNormal4_GBuffer = 13; + + public const int DeinterleaveNormal4_GBufferOctaEncoded = 14; + + public const int OcclusionCache_Low = 15; + + public const int OcclusionCache_Medium = 16; + + public const int OcclusionCache_High = 17; + + public const int OcclusionCache_VeryHigh = 18; + + public const int Reinterleave = 19; + + public const int OcclusionLow_None = 20; + + public const int OcclusionLow_Camera = 21; + + public const int OcclusionLow_GBuffer = 22; + + public const int OcclusionLow_GBufferOctaEncoded = 23; + + public const int OcclusionMedium_None = 24; + + public const int OcclusionMedium_Camera = 25; + + public const int OcclusionMedium_GBuffer = 26; + + public const int OcclusionMedium_GBufferOctaEncoded = 27; + + public const int OcclusionHigh_None = 28; + + public const int OcclusionHigh_Camera = 29; + + public const int OcclusionHigh_GBuffer = 30; + + public const int OcclusionHigh_GBufferOctaEncoded = 31; + + public const int OcclusionVeryHigh_None = 32; + + public const int OcclusionVeryHigh_Camera = 33; + + public const int OcclusionVeryHigh_GBuffer = 34; + + public const int OcclusionVeryHigh_GBufferNormalEncoded = 35; + + public const int ApplyDebug = 36; + + public const int ApplyDeferred = 37; + + public const int ApplyDeferredLog = 38; + + public const int ApplyPostEffect = 39; + + public const int ApplyPostEffectLog = 40; + + public const int CombineDownsampledOcclusionDepth = 41; + + public const int BlurHorizontal1 = 0; + + public const int BlurVertical1 = 1; + + public const int BlurHorizontal2 = 2; + + public const int BlurVertical2 = 3; + + public const int BlurHorizontal3 = 4; + + public const int BlurVertical3 = 5; + + public const int BlurHorizontal4 = 6; + + public const int BlurVertical4 = 7; + + public const int Copy = 0; + } + + private struct TargetDesc + { + public int fullWidth; + + public int fullHeight; + + public RenderTextureFormat format; + + public int width; + + public int height; + + public int quarterWidth; + + public int quarterHeight; + + public float padRatioWidth; + + public float padRatioHeight; + } + + [Header("Ambient Occlusion")] + public ApplicationMethod ApplyMethod; + + public SampleCountLevel SampleCount = SampleCountLevel.Medium; + + public PerPixelNormalSource PerPixelNormals; + + [Range(0f, 1f)] + public float Intensity = 1f; + + public Color Tint = Color.black; + + [Range(0f, 16f)] + public float Radius = 1f; + + [Range(0f, 16f)] + public float PowerExponent = 1.8f; + + [Range(0f, 0.99f)] + public float Bias = 0.05f; + + public bool CacheAware; + + public bool Downsample; + + [Header("Distance Fade")] + public bool FadeEnabled; + + public float FadeStart = 100f; + + public float FadeLength = 50f; + + [Range(0f, 1f)] + public float FadeToIntensity = 1f; + + [Range(0f, 16f)] + public float FadeToRadius = 1f; + + [Range(0f, 16f)] + public float FadeToPowerExponent = 1.8f; + + [Header("Bilateral Blur")] + public bool BlurEnabled = true; + + [Range(1f, 4f)] + public int BlurRadius = 2; + + [Range(1f, 4f)] + public int BlurPasses = 1; + + [Range(0f, 20f)] + public float BlurSharpness = 10f; + + private const int PerPixelNormalSourceCount = 4; + + private int prevScreenWidth; + + private int prevScreenHeight; + + private bool prevHDR; + + private ApplicationMethod prevApplyMethod; + + private SampleCountLevel prevSampleCount; + + private PerPixelNormalSource prevPerPixelNormals; + + private bool prevCacheAware; + + private bool prevDownscale; + + private bool prevFadeEnabled; + + private float prevFadeToIntensity; + + private float prevFadeToRadius; + + private float prevFadeToPowerExponent; + + private float prevFadeStart; + + private float prevFadeLength; + + private bool prevBlurEnabled; + + private int prevBlurRadius; + + private int prevBlurPasses; + + private Camera m_camera; + + private Material m_occlusionMat; + + private Material m_blurMat; + + private Material m_copyMat; + + private const int RandomSize = 4; + + private const int DirectionCount = 8; + + private Color[] m_randomData; + + private Texture2D m_randomTex; + + private string[] m_layerOffsetNames; + + private string[] m_layerRandomNames; + + private string[] m_layerDepthNames; + + private string[] m_layerNormalNames; + + private string[] m_layerOcclusionNames; + + private RenderTextureFormat m_depthRTFormat = RenderTextureFormat.RFloat; + + private RenderTextureFormat m_normalRTFormat = RenderTextureFormat.ARGB2101010; + + private RenderTextureFormat m_occlusionRTFormat = RenderTextureFormat.RGHalf; + + private RenderTexture m_occlusionRT; + + private int[] m_depthLayerRT; + + private int[] m_normalLayerRT; + + private int[] m_occlusionLayerRT; + + private int m_mrtCount; + + private RenderTargetIdentifier[] m_depthTargets; + + private RenderTargetIdentifier[] m_normalTargets; + + private int m_deinterleaveDepthPass; + + private int m_deinterleaveNormalPass; + + private RenderTargetIdentifier[] m_applyDeferredTargets; + + private Mesh m_blitMesh; + + private TargetDesc m_target = default(TargetDesc); + + private Dictionary<CameraEvent, CommandBuffer> m_registeredCommandBuffers = new Dictionary<CameraEvent, CommandBuffer>(); + + private bool CheckParamsChanged() + { + return prevScreenWidth != m_camera.pixelWidth || prevScreenHeight != m_camera.pixelHeight || prevHDR != m_camera.allowHDR || prevApplyMethod != ApplyMethod || prevSampleCount != SampleCount || prevPerPixelNormals != PerPixelNormals || prevCacheAware != CacheAware || prevDownscale != Downsample || prevFadeEnabled != FadeEnabled || prevFadeToIntensity != FadeToIntensity || prevFadeToRadius != FadeToRadius || prevFadeToPowerExponent != FadeToPowerExponent || prevFadeStart != FadeStart || prevFadeLength != FadeLength || prevBlurEnabled != BlurEnabled || prevBlurRadius != BlurRadius || prevBlurPasses != BlurPasses; + } + + private void UpdateParams() + { + prevScreenWidth = m_camera.pixelWidth; + prevScreenHeight = m_camera.pixelHeight; + prevHDR = m_camera.allowHDR; + prevApplyMethod = ApplyMethod; + prevSampleCount = SampleCount; + prevPerPixelNormals = PerPixelNormals; + prevCacheAware = CacheAware; + prevDownscale = Downsample; + prevFadeEnabled = FadeEnabled; + prevFadeToIntensity = FadeToIntensity; + prevFadeToRadius = FadeToRadius; + prevFadeToPowerExponent = FadeToPowerExponent; + prevFadeStart = FadeStart; + prevFadeLength = FadeLength; + prevBlurEnabled = BlurEnabled; + prevBlurRadius = BlurRadius; + prevBlurPasses = BlurPasses; + } + + private void Warmup() + { + CheckMaterial(); + CheckRandomData(); + m_depthLayerRT = new int[16]; + m_normalLayerRT = new int[16]; + m_occlusionLayerRT = new int[16]; + m_mrtCount = Mathf.Min(SystemInfo.supportedRenderTargetCount, 4); + m_layerOffsetNames = new string[m_mrtCount]; + m_layerRandomNames = new string[m_mrtCount]; + for (int i = 0; i < m_mrtCount; i++) + { + m_layerOffsetNames[i] = "_AO_LayerOffset" + i; + m_layerRandomNames[i] = "_AO_LayerRandom" + i; + } + m_layerDepthNames = new string[16]; + m_layerNormalNames = new string[16]; + m_layerOcclusionNames = new string[16]; + for (int j = 0; j < 16; j++) + { + m_layerDepthNames[j] = "_AO_DepthLayer" + j; + m_layerNormalNames[j] = "_AO_NormalLayer" + j; + m_layerOcclusionNames[j] = "_AO_OcclusionLayer" + j; + } + m_depthTargets = new RenderTargetIdentifier[m_mrtCount]; + m_normalTargets = new RenderTargetIdentifier[m_mrtCount]; + int mrtCount = m_mrtCount; + if (mrtCount == 4) + { + m_deinterleaveDepthPass = 10; + m_deinterleaveNormalPass = 11; + } + else + { + m_deinterleaveDepthPass = 5; + m_deinterleaveNormalPass = 6; + } + m_applyDeferredTargets = new RenderTargetIdentifier[2]; + if (m_blitMesh != null) + { + UnityEngine.Object.DestroyImmediate(m_blitMesh); + } + m_blitMesh = new Mesh(); + m_blitMesh.vertices = new Vector3[4] + { + new Vector3(0f, 0f, 0f), + new Vector3(0f, 1f, 0f), + new Vector3(1f, 1f, 0f), + new Vector3(1f, 0f, 0f) + }; + m_blitMesh.uv = new Vector2[4] + { + new Vector2(0f, 0f), + new Vector2(0f, 1f), + new Vector2(1f, 1f), + new Vector2(1f, 0f) + }; + m_blitMesh.triangles = new int[6] { 0, 1, 2, 0, 2, 3 }; + } + + private void Shutdown() + { + CommandBuffer_UnregisterAll(); + SafeReleaseRT(ref m_occlusionRT); + if (m_occlusionMat != null) + { + UnityEngine.Object.DestroyImmediate(m_occlusionMat); + } + if (m_blurMat != null) + { + UnityEngine.Object.DestroyImmediate(m_blurMat); + } + if (m_copyMat != null) + { + UnityEngine.Object.DestroyImmediate(m_copyMat); + } + if (m_blitMesh != null) + { + UnityEngine.Object.DestroyImmediate(m_blitMesh); + } + } + + private bool CheckRenderTextureFormats() + { + if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32) && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) + { + m_depthRTFormat = RenderTextureFormat.RFloat; + if (!SystemInfo.SupportsRenderTextureFormat(m_depthRTFormat)) + { + m_depthRTFormat = RenderTextureFormat.RHalf; + if (!SystemInfo.SupportsRenderTextureFormat(m_depthRTFormat)) + { + m_depthRTFormat = RenderTextureFormat.ARGBHalf; + } + } + m_normalRTFormat = RenderTextureFormat.ARGB2101010; + if (!SystemInfo.SupportsRenderTextureFormat(m_normalRTFormat)) + { + m_normalRTFormat = RenderTextureFormat.ARGB32; + } + m_occlusionRTFormat = RenderTextureFormat.RGHalf; + if (!SystemInfo.SupportsRenderTextureFormat(m_occlusionRTFormat)) + { + m_occlusionRTFormat = RenderTextureFormat.RGFloat; + if (!SystemInfo.SupportsRenderTextureFormat(m_occlusionRTFormat)) + { + m_occlusionRTFormat = RenderTextureFormat.ARGBHalf; + } + } + return true; + } + return false; + } + + private void OnEnable() + { + if (!CheckRenderTextureFormats()) + { + Debug.LogError("[AmplifyOcclusion] Target platform does not meet the minimum requirements for this effect to work properly."); + base.enabled = false; + } + else + { + m_camera = GetComponent<Camera>(); + Warmup(); + CommandBuffer_UnregisterAll(); + } + } + + private void OnDisable() + { + Shutdown(); + } + + private void OnDestroy() + { + Shutdown(); + } + + private void Update() + { + if (m_camera.actualRenderingPath != RenderingPath.DeferredShading) + { + if (PerPixelNormals != 0 && PerPixelNormals != PerPixelNormalSource.Camera) + { + PerPixelNormals = PerPixelNormalSource.Camera; + Debug.LogWarning("[AmplifyOcclusion] GBuffer Normals only available in Camera Deferred Shading mode. Switched to Camera source."); + } + if (ApplyMethod == ApplicationMethod.Deferred) + { + ApplyMethod = ApplicationMethod.PostEffect; + Debug.LogWarning("[AmplifyOcclusion] Deferred Method requires a Deferred Shading path. Switching to Post Effect Method."); + } + } + if (ApplyMethod == ApplicationMethod.Deferred && PerPixelNormals == PerPixelNormalSource.Camera) + { + PerPixelNormals = PerPixelNormalSource.GBuffer; + Debug.LogWarning("[AmplifyOcclusion] Camera Normals not supported for Deferred Method. Switching to GBuffer Normals."); + } + if ((m_camera.depthTextureMode & DepthTextureMode.Depth) == 0) + { + m_camera.depthTextureMode |= DepthTextureMode.Depth; + } + if (PerPixelNormals == PerPixelNormalSource.Camera && (m_camera.depthTextureMode & DepthTextureMode.DepthNormals) == 0) + { + m_camera.depthTextureMode |= DepthTextureMode.DepthNormals; + } + CheckMaterial(); + CheckRandomData(); + } + + private void CheckMaterial() + { + if (m_occlusionMat == null) + { + m_occlusionMat = new Material(Shader.Find("Hidden/Amplify Occlusion/Occlusion")) + { + hideFlags = HideFlags.DontSave + }; + } + if (m_blurMat == null) + { + m_blurMat = new Material(Shader.Find("Hidden/Amplify Occlusion/Blur")) + { + hideFlags = HideFlags.DontSave + }; + } + if (m_copyMat == null) + { + m_copyMat = new Material(Shader.Find("Hidden/Amplify Occlusion/Copy")) + { + hideFlags = HideFlags.DontSave + }; + } + } + + private void CheckRandomData() + { + if (m_randomData == null) + { + m_randomData = GenerateRandomizationData(); + } + if (m_randomTex == null) + { + m_randomTex = Resources.Load<Texture2D>("Random4x4"); + } + } + + public static Color[] GenerateRandomizationData() + { + Color[] array = new Color[16]; + int i = 0; + int num = 0; + for (; i < 16; i++) + { + float num2 = RandomTable.Values[num++]; + float b = RandomTable.Values[num++]; + float f = (float)Math.PI * 2f * num2 / 8f; + array[i].r = Mathf.Cos(f); + array[i].g = Mathf.Sin(f); + array[i].b = b; + array[i].a = 0f; + } + return array; + } + + public static Texture2D GenerateRandomizationTexture(Color[] randomPixels) + { + Texture2D texture2D = new Texture2D(4, 4, TextureFormat.ARGB32, mipmap: false, linear: true); + texture2D.hideFlags = HideFlags.DontSave; + Texture2D texture2D2 = texture2D; + texture2D2.name = "RandomTexture"; + texture2D2.filterMode = FilterMode.Point; + texture2D2.wrapMode = TextureWrapMode.Repeat; + texture2D2.SetPixels(randomPixels); + texture2D2.Apply(); + return texture2D2; + } + + private RenderTexture SafeAllocateRT(string name, int width, int height, RenderTextureFormat format, RenderTextureReadWrite readWrite) + { + width = Mathf.Max(width, 1); + height = Mathf.Max(height, 1); + RenderTexture renderTexture = new RenderTexture(width, height, 0, format, readWrite); + renderTexture.hideFlags = HideFlags.DontSave; + RenderTexture renderTexture2 = renderTexture; + renderTexture2.name = name; + renderTexture2.filterMode = FilterMode.Point; + renderTexture2.wrapMode = TextureWrapMode.Clamp; + renderTexture2.Create(); + return renderTexture2; + } + + private void SafeReleaseRT(ref RenderTexture rt) + { + if (rt != null) + { + RenderTexture.active = null; + rt.Release(); + UnityEngine.Object.DestroyImmediate(rt); + rt = null; + } + } + + private int SafeAllocateTemporaryRT(CommandBuffer cb, string propertyName, int width, int height, RenderTextureFormat format = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default, FilterMode filterMode = FilterMode.Point) + { + int num = Shader.PropertyToID(propertyName); + cb.GetTemporaryRT(num, width, height, 0, filterMode, format, readWrite); + return num; + } + + private void SafeReleaseTemporaryRT(CommandBuffer cb, int id) + { + cb.ReleaseTemporaryRT(id); + } + + private void SetBlitTarget(CommandBuffer cb, RenderTargetIdentifier[] targets, int targetWidth, int targetHeight) + { + cb.SetGlobalVector("_AO_Target_TexelSize", new Vector4(1f / (float)targetWidth, 1f / (float)targetHeight, targetWidth, targetHeight)); + cb.SetGlobalVector("_AO_Target_Position", Vector2.zero); + cb.SetRenderTarget(targets, targets[0]); + } + + private void SetBlitTarget(CommandBuffer cb, RenderTargetIdentifier target, int targetWidth, int targetHeight) + { + cb.SetGlobalVector("_AO_Target_TexelSize", new Vector4(1f / (float)targetWidth, 1f / (float)targetHeight, targetWidth, targetHeight)); + cb.SetRenderTarget(target); + } + + private void PerformBlit(CommandBuffer cb, Material mat, int pass) + { + cb.DrawMesh(m_blitMesh, Matrix4x4.identity, mat, 0, pass); + } + + private void PerformBlit(CommandBuffer cb, Material mat, int pass, int x, int y) + { + cb.SetGlobalVector("_AO_Target_Position", new Vector2(x, y)); + PerformBlit(cb, mat, pass); + } + + private void PerformBlit(CommandBuffer cb, RenderTargetIdentifier source, int sourceWidth, int sourceHeight, Material mat, int pass) + { + cb.SetGlobalTexture("_AO_Source", source); + cb.SetGlobalVector("_AO_Source_TexelSize", new Vector4(1f / (float)sourceWidth, 1f / (float)sourceHeight, sourceWidth, sourceHeight)); + PerformBlit(cb, mat, pass); + } + + private void PerformBlit(CommandBuffer cb, RenderTargetIdentifier source, int sourceWidth, int sourceHeight, Material mat, int pass, int x, int y) + { + cb.SetGlobalVector("_AO_Target_Position", new Vector2(x, y)); + PerformBlit(cb, source, sourceWidth, sourceHeight, mat, pass); + } + + private CommandBuffer CommandBuffer_Allocate(string name) + { + CommandBuffer commandBuffer = new CommandBuffer(); + commandBuffer.name = name; + return commandBuffer; + } + + private void CommandBuffer_Register(CameraEvent cameraEvent, CommandBuffer commandBuffer) + { + m_camera.AddCommandBuffer(cameraEvent, commandBuffer); + m_registeredCommandBuffers.Add(cameraEvent, commandBuffer); + } + + private void CommandBuffer_Unregister(CameraEvent cameraEvent, CommandBuffer commandBuffer) + { + if (!(m_camera != null)) + { + return; + } + CommandBuffer[] commandBuffers = m_camera.GetCommandBuffers(cameraEvent); + CommandBuffer[] array = commandBuffers; + foreach (CommandBuffer commandBuffer2 in array) + { + if (commandBuffer2.name == commandBuffer.name) + { + m_camera.RemoveCommandBuffer(cameraEvent, commandBuffer2); + } + } + } + + private CommandBuffer CommandBuffer_AllocateRegister(CameraEvent cameraEvent) + { + string text = string.Empty; + switch (cameraEvent) + { + case CameraEvent.BeforeReflections: + text = "AO-BeforeRefl"; + break; + case CameraEvent.AfterLighting: + text = "AO-AfterLighting"; + break; + case CameraEvent.BeforeImageEffectsOpaque: + text = "AO-BeforePostOpaque"; + break; + default: + Debug.LogError("[AmplifyOcclusion] Unsupported CameraEvent. Please contact support."); + break; + } + CommandBuffer commandBuffer = CommandBuffer_Allocate(text); + CommandBuffer_Register(cameraEvent, commandBuffer); + return commandBuffer; + } + + private void CommandBuffer_UnregisterAll() + { + foreach (KeyValuePair<CameraEvent, CommandBuffer> registeredCommandBuffer in m_registeredCommandBuffers) + { + CommandBuffer_Unregister(registeredCommandBuffer.Key, registeredCommandBuffer.Value); + } + m_registeredCommandBuffers.Clear(); + } + + private void UpdateLocalMaterialConstants() + { + if (m_occlusionMat != null) + { + m_occlusionMat.SetTexture("_AO_RandomTexture", m_randomTex); + } + } + + private void UpdateGlobalShaderConstants(TargetDesc target) + { + float num = m_camera.fieldOfView * ((float)Math.PI / 180f); + Vector2 vector = new Vector2(1f / Mathf.Tan(num * 0.5f) * ((float)target.height / (float)target.width), 1f / Mathf.Tan(num * 0.5f)); + Vector2 vector2 = new Vector2(1f / vector.x, 1f / vector.y); + float num2 = ((!m_camera.orthographic) ? ((float)target.height / (Mathf.Tan(num * 0.5f) * 2f)) : ((float)target.height / m_camera.orthographicSize)); + float num3 = Mathf.Clamp(Bias, 0f, 1f); + FadeStart = Mathf.Max(0f, FadeStart); + FadeLength = Mathf.Max(0.01f, FadeLength); + float y = ((!FadeEnabled) ? 0f : (1f / FadeLength)); + Shader.SetGlobalMatrix("_AO_CameraProj", GL.GetGPUProjectionMatrix(Matrix4x4.Ortho(0f, 1f, 0f, 1f, -1f, 100f), renderIntoTexture: false)); + Shader.SetGlobalMatrix("_AO_CameraView", m_camera.worldToCameraMatrix); + Shader.SetGlobalVector("_AO_UVToView", new Vector4(2f * vector2.x, -2f * vector2.y, -1f * vector2.x, 1f * vector2.y)); + Shader.SetGlobalFloat("_AO_HalfProjScale", 0.5f * num2); + Shader.SetGlobalFloat("_AO_Radius", Radius); + Shader.SetGlobalFloat("_AO_PowExponent", PowerExponent); + Shader.SetGlobalFloat("_AO_Bias", num3); + Shader.SetGlobalFloat("_AO_Multiplier", 1f / (1f - num3)); + Shader.SetGlobalFloat("_AO_BlurSharpness", BlurSharpness); + Shader.SetGlobalColor("_AO_Levels", new Color(Tint.r, Tint.g, Tint.b, Intensity)); + Shader.SetGlobalVector("_AO_FadeParams", new Vector2(FadeStart, y)); + Shader.SetGlobalVector("_AO_FadeValues", new Vector3(FadeToIntensity, FadeToRadius, FadeToPowerExponent)); + } + + private void CommandBuffer_FillComputeOcclusion(CommandBuffer cb, TargetDesc target) + { + CheckMaterial(); + CheckRandomData(); + cb.SetGlobalVector("_AO_Buffer_PadScale", new Vector4(target.padRatioWidth, target.padRatioHeight, 1f / target.padRatioWidth, 1f / target.padRatioHeight)); + cb.SetGlobalVector("_AO_Buffer_TexelSize", new Vector4(1f / (float)target.width, 1f / (float)target.height, target.width, target.height)); + cb.SetGlobalVector("_AO_QuarterBuffer_TexelSize", new Vector4(1f / (float)target.quarterWidth, 1f / (float)target.quarterHeight, target.quarterWidth, target.quarterHeight)); + cb.SetGlobalFloat("_AO_MaxRadiusPixels", Mathf.Min(target.width, target.height)); + if (m_occlusionRT == null || m_occlusionRT.width != target.width || m_occlusionRT.height != target.height || !m_occlusionRT.IsCreated()) + { + SafeReleaseRT(ref m_occlusionRT); + m_occlusionRT = SafeAllocateRT("_AO_OcclusionTexture", target.width, target.height, m_occlusionRTFormat, RenderTextureReadWrite.Linear); + } + int num = -1; + if (Downsample) + { + num = SafeAllocateTemporaryRT(cb, "_AO_SmallOcclusionTexture", target.width / 2, target.height / 2, m_occlusionRTFormat, RenderTextureReadWrite.Linear, FilterMode.Bilinear); + } + if (CacheAware && !Downsample) + { + int num2 = SafeAllocateTemporaryRT(cb, "_AO_OcclusionAtlas", target.width, target.height, m_occlusionRTFormat, RenderTextureReadWrite.Linear); + for (int i = 0; i < 16; i++) + { + m_depthLayerRT[i] = SafeAllocateTemporaryRT(cb, m_layerDepthNames[i], target.quarterWidth, target.quarterHeight, m_depthRTFormat, RenderTextureReadWrite.Linear); + m_normalLayerRT[i] = SafeAllocateTemporaryRT(cb, m_layerNormalNames[i], target.quarterWidth, target.quarterHeight, m_normalRTFormat, RenderTextureReadWrite.Linear); + m_occlusionLayerRT[i] = SafeAllocateTemporaryRT(cb, m_layerOcclusionNames[i], target.quarterWidth, target.quarterHeight, m_occlusionRTFormat, RenderTextureReadWrite.Linear); + } + for (int j = 0; j < 16; j += m_mrtCount) + { + for (int k = 0; k < m_mrtCount; k++) + { + int num3 = k + j; + int num4 = num3 & 3; + int num5 = num3 >> 2; + cb.SetGlobalVector(m_layerOffsetNames[k], new Vector2((float)num4 + 0.5f, (float)num5 + 0.5f)); + ref RenderTargetIdentifier reference = ref m_depthTargets[k]; + reference = m_depthLayerRT[num3]; + ref RenderTargetIdentifier reference2 = ref m_normalTargets[k]; + reference2 = m_normalLayerRT[num3]; + } + SetBlitTarget(cb, m_depthTargets, target.quarterWidth, target.quarterHeight); + PerformBlit(cb, m_occlusionMat, m_deinterleaveDepthPass); + SetBlitTarget(cb, m_normalTargets, target.quarterWidth, target.quarterHeight); + PerformBlit(cb, m_occlusionMat, (int)(m_deinterleaveNormalPass + PerPixelNormals)); + } + for (int l = 0; l < 16; l++) + { + cb.SetGlobalVector("_AO_LayerOffset", new Vector2((float)(l & 3) + 0.5f, (float)(l >> 2) + 0.5f)); + cb.SetGlobalVector("_AO_LayerRandom", m_randomData[l]); + cb.SetGlobalTexture("_AO_NormalTexture", m_normalLayerRT[l]); + cb.SetGlobalTexture("_AO_DepthTexture", m_depthLayerRT[l]); + SetBlitTarget(cb, m_occlusionLayerRT[l], target.quarterWidth, target.quarterHeight); + PerformBlit(cb, m_occlusionMat, (int)(15 + SampleCount)); + } + SetBlitTarget(cb, num2, target.width, target.height); + for (int m = 0; m < 16; m++) + { + int x = (m & 3) * target.quarterWidth; + int y = (m >> 2) * target.quarterHeight; + PerformBlit(cb, m_occlusionLayerRT[m], target.quarterWidth, target.quarterHeight, m_copyMat, 0, x, y); + } + cb.SetGlobalTexture("_AO_OcclusionAtlas", num2); + SetBlitTarget(cb, m_occlusionRT, target.width, target.height); + PerformBlit(cb, m_occlusionMat, 19); + for (int n = 0; n < 16; n++) + { + SafeReleaseTemporaryRT(cb, m_occlusionLayerRT[n]); + SafeReleaseTemporaryRT(cb, m_normalLayerRT[n]); + SafeReleaseTemporaryRT(cb, m_depthLayerRT[n]); + } + SafeReleaseTemporaryRT(cb, num2); + } + else + { + int pass = (int)(20 + (int)SampleCount * 4 + PerPixelNormals); + if (Downsample) + { + cb.Blit(null, new RenderTargetIdentifier(num), m_occlusionMat, pass); + SetBlitTarget(cb, m_occlusionRT, target.width, target.height); + PerformBlit(cb, num, target.width / 2, target.height / 2, m_occlusionMat, 41); + } + else + { + cb.Blit(null, m_occlusionRT, m_occlusionMat, pass); + } + } + if (BlurEnabled) + { + int num6 = SafeAllocateTemporaryRT(cb, "_AO_TEMP", target.width, target.height, m_occlusionRTFormat, RenderTextureReadWrite.Linear); + for (int num7 = 0; num7 < BlurPasses; num7++) + { + SetBlitTarget(cb, num6, target.width, target.height); + PerformBlit(cb, m_occlusionRT, target.width, target.height, m_blurMat, (BlurRadius - 1) * 2); + SetBlitTarget(cb, m_occlusionRT, target.width, target.height); + PerformBlit(cb, num6, target.width, target.height, m_blurMat, 1 + (BlurRadius - 1) * 2); + } + SafeReleaseTemporaryRT(cb, num6); + } + if (Downsample && num >= 0) + { + SafeReleaseTemporaryRT(cb, num); + } + cb.SetRenderTarget((Texture)null); + } + + private void CommandBuffer_FillApplyDeferred(CommandBuffer cb, TargetDesc target, bool logTarget) + { + cb.SetGlobalTexture("_AO_OcclusionTexture", m_occlusionRT); + ref RenderTargetIdentifier reference = ref m_applyDeferredTargets[0]; + reference = BuiltinRenderTextureType.GBuffer0; + ref RenderTargetIdentifier reference2 = ref m_applyDeferredTargets[1]; + reference2 = ((!logTarget) ? BuiltinRenderTextureType.CameraTarget : BuiltinRenderTextureType.GBuffer3); + if (!logTarget) + { + SetBlitTarget(cb, m_applyDeferredTargets, target.fullWidth, target.fullHeight); + PerformBlit(cb, m_occlusionMat, 37); + } + else + { + int num = SafeAllocateTemporaryRT(cb, "_AO_GBufferAlbedo", target.fullWidth, target.fullHeight, RenderTextureFormat.ARGB32); + int num2 = SafeAllocateTemporaryRT(cb, "_AO_GBufferEmission", target.fullWidth, target.fullHeight, RenderTextureFormat.ARGB32); + cb.Blit(m_applyDeferredTargets[0], num); + cb.Blit(m_applyDeferredTargets[1], num2); + cb.SetGlobalTexture("_AO_GBufferAlbedo", num); + cb.SetGlobalTexture("_AO_GBufferEmission", num2); + SetBlitTarget(cb, m_applyDeferredTargets, target.fullWidth, target.fullHeight); + PerformBlit(cb, m_occlusionMat, 38); + SafeReleaseTemporaryRT(cb, num); + SafeReleaseTemporaryRT(cb, num2); + } + cb.SetRenderTarget((Texture)null); + } + + private void CommandBuffer_FillApplyPostEffect(CommandBuffer cb, TargetDesc target, bool logTarget) + { + cb.SetGlobalTexture("_AO_OcclusionTexture", m_occlusionRT); + if (!logTarget) + { + SetBlitTarget(cb, BuiltinRenderTextureType.CameraTarget, target.fullWidth, target.fullHeight); + PerformBlit(cb, m_occlusionMat, 39); + } + else + { + int num = SafeAllocateTemporaryRT(cb, "_AO_GBufferEmission", target.fullWidth, target.fullHeight, RenderTextureFormat.ARGB32); + cb.Blit(BuiltinRenderTextureType.GBuffer3, num); + cb.SetGlobalTexture("_AO_GBufferEmission", num); + SetBlitTarget(cb, BuiltinRenderTextureType.GBuffer3, target.fullWidth, target.fullHeight); + PerformBlit(cb, m_occlusionMat, 40); + SafeReleaseTemporaryRT(cb, num); + } + cb.SetRenderTarget((Texture)null); + } + + private void CommandBuffer_FillApplyDebug(CommandBuffer cb, TargetDesc target) + { + cb.SetGlobalTexture("_AO_OcclusionTexture", m_occlusionRT); + SetBlitTarget(cb, BuiltinRenderTextureType.CameraTarget, target.fullWidth, target.fullHeight); + PerformBlit(cb, m_occlusionMat, 36); + cb.SetRenderTarget((Texture)null); + } + + private void CommandBuffer_Rebuild(TargetDesc target) + { + bool flag = PerPixelNormals == PerPixelNormalSource.GBuffer || PerPixelNormals == PerPixelNormalSource.GBufferOctaEncoded; + CommandBuffer commandBuffer = null; + CameraEvent cameraEvent = ((!flag) ? CameraEvent.BeforeImageEffectsOpaque : CameraEvent.AfterLighting); + if (ApplyMethod == ApplicationMethod.Debug) + { + commandBuffer = CommandBuffer_AllocateRegister(cameraEvent); + CommandBuffer_FillComputeOcclusion(commandBuffer, target); + CommandBuffer_FillApplyDebug(commandBuffer, target); + return; + } + bool logTarget = !m_camera.allowHDR && flag; + cameraEvent = ((ApplyMethod != ApplicationMethod.Deferred) ? cameraEvent : CameraEvent.BeforeReflections); + commandBuffer = CommandBuffer_AllocateRegister(cameraEvent); + CommandBuffer_FillComputeOcclusion(commandBuffer, target); + if (ApplyMethod == ApplicationMethod.PostEffect) + { + CommandBuffer_FillApplyPostEffect(commandBuffer, target, logTarget); + } + else if (ApplyMethod == ApplicationMethod.Deferred) + { + CommandBuffer_FillApplyDeferred(commandBuffer, target, logTarget); + } + } + + private void OnPreRender() + { + bool allowHDR = m_camera.allowHDR; + m_target.fullWidth = m_camera.pixelWidth; + m_target.fullHeight = m_camera.pixelHeight; + m_target.format = (allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32); + m_target.width = ((!CacheAware) ? m_target.fullWidth : ((m_target.fullWidth + 3) & -4)); + m_target.height = ((!CacheAware) ? m_target.fullHeight : ((m_target.fullHeight + 3) & -4)); + m_target.quarterWidth = m_target.width / 4; + m_target.quarterHeight = m_target.height / 4; + m_target.padRatioWidth = (float)m_target.width / (float)m_target.fullWidth; + m_target.padRatioHeight = (float)m_target.height / (float)m_target.fullHeight; + UpdateLocalMaterialConstants(); + UpdateGlobalShaderConstants(m_target); + if (CheckParamsChanged() || m_registeredCommandBuffers.Count == 0) + { + CommandBuffer_UnregisterAll(); + CommandBuffer_Rebuild(m_target); + UpdateParams(); + } + } + + private void OnPostRender() + { + m_occlusionRT.MarkRestoreExpected(); + } +} |