948 lines
29 KiB
C#
948 lines
29 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
[AddComponentMenu("")]
|
|
public class AmplifyOcclusionBase : MonoBehaviour
|
|
{
|
|
public enum ApplicationMethod
|
|
{
|
|
PostEffect = 0,
|
|
Deferred = 1,
|
|
Debug = 2
|
|
}
|
|
|
|
public enum PerPixelNormalSource
|
|
{
|
|
None = 0,
|
|
Camera = 1,
|
|
GBuffer = 2,
|
|
GBufferOctaEncoded = 3
|
|
}
|
|
|
|
public enum SampleCountLevel
|
|
{
|
|
Low = 0,
|
|
Medium = 1,
|
|
High = 2,
|
|
VeryHigh = 3
|
|
}
|
|
|
|
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 != PerPixelNormalSource.None && 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, false, 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), 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));
|
|
m_depthTargets[k] = m_depthLayerRT[num3];
|
|
m_normalTargets[k] = 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);
|
|
m_applyDeferredTargets[0] = BuiltinRenderTextureType.GBuffer0;
|
|
m_applyDeferredTargets[1] = ((!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();
|
|
}
|
|
}
|