1004 lines
53 KiB
C#
1004 lines
53 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
using UnityEngine.XR;
|
|
|
|
namespace HorizonBasedAmbientOcclusion.Universal
|
|
{
|
|
public class HBAORendererFeature : ScriptableRendererFeature
|
|
{
|
|
private class HBAORenderPass : ScriptableRenderPass
|
|
{
|
|
public HBAO hbao;
|
|
|
|
private static class Pass
|
|
{
|
|
public const int AO = 0;
|
|
public const int AO_Deinterleaved = 1;
|
|
|
|
public const int Deinterleave_Depth = 2;
|
|
public const int Deinterleave_Normals = 3;
|
|
public const int Atlas_AO_Deinterleaved = 4;
|
|
public const int Reinterleave_AO = 5;
|
|
|
|
public const int Blur = 6;
|
|
|
|
public const int Temporal_Filter = 7;
|
|
|
|
public const int Copy = 8;
|
|
|
|
public const int Composite = 9;
|
|
|
|
public const int Debug_ViewNormals = 10;
|
|
}
|
|
|
|
private static class ShaderProperties
|
|
{
|
|
public static int mainTex;
|
|
public static int inputTex;
|
|
public static int hbaoTex;
|
|
public static int tempTex;
|
|
public static int tempTex2;
|
|
public static int noiseTex;
|
|
public static int depthTex;
|
|
public static int normalsTex;
|
|
public static int ssaoTex;
|
|
public static int[] depthSliceTex;
|
|
public static int[] normalsSliceTex;
|
|
public static int[] aoSliceTex;
|
|
public static int[] deinterleaveOffset;
|
|
public static int atlasOffset;
|
|
public static int jitter;
|
|
public static int uvTransform;
|
|
public static int inputTexelSize;
|
|
public static int aoTexelSize;
|
|
public static int deinterleavedAOTexelSize;
|
|
public static int reinterleavedAOTexelSize;
|
|
public static int uvToView;
|
|
public static int worldToCameraMatrix;
|
|
public static int targetScale;
|
|
public static int radius;
|
|
public static int maxRadiusPixels;
|
|
public static int negInvRadius2;
|
|
public static int angleBias;
|
|
public static int aoMultiplier;
|
|
public static int intensity;
|
|
public static int multiBounceInfluence;
|
|
public static int offscreenSamplesContrib;
|
|
public static int maxDistance;
|
|
public static int distanceFalloff;
|
|
public static int baseColor;
|
|
public static int colorBleedSaturation;
|
|
public static int albedoMultiplier;
|
|
public static int colorBleedBrightnessMask;
|
|
public static int colorBleedBrightnessMaskRange;
|
|
public static int blurDeltaUV;
|
|
public static int blurSharpness;
|
|
public static int temporalParams;
|
|
public static int historyBufferRTHandleScale;
|
|
|
|
static ShaderProperties()
|
|
{
|
|
mainTex = Shader.PropertyToID("_MainTex");
|
|
inputTex = Shader.PropertyToID("_InputTex");
|
|
hbaoTex = Shader.PropertyToID("_HBAOTex");
|
|
tempTex = Shader.PropertyToID("_TempTex");
|
|
tempTex2 = Shader.PropertyToID("_TempTex2");
|
|
noiseTex = Shader.PropertyToID("_NoiseTex");
|
|
depthTex = Shader.PropertyToID("_DepthTex");
|
|
normalsTex = Shader.PropertyToID("_NormalsTex");
|
|
ssaoTex = Shader.PropertyToID("_SSAOTex");
|
|
depthSliceTex = new int[4 * 4];
|
|
normalsSliceTex = new int[4 * 4];
|
|
aoSliceTex = new int[4 * 4];
|
|
for (int i = 0; i < 4 * 4; i++)
|
|
{
|
|
depthSliceTex[i] = Shader.PropertyToID("_DepthSliceTex" + i);
|
|
normalsSliceTex[i] = Shader.PropertyToID("_NormalsSliceTex" + i);
|
|
aoSliceTex[i] = Shader.PropertyToID("_AOSliceTex" + i);
|
|
}
|
|
deinterleaveOffset = new int[] {
|
|
Shader.PropertyToID("_Deinterleave_Offset00"),
|
|
Shader.PropertyToID("_Deinterleave_Offset10"),
|
|
Shader.PropertyToID("_Deinterleave_Offset01"),
|
|
Shader.PropertyToID("_Deinterleave_Offset11")
|
|
};
|
|
atlasOffset = Shader.PropertyToID("_AtlasOffset");
|
|
jitter = Shader.PropertyToID("_Jitter");
|
|
uvTransform = Shader.PropertyToID("_UVTransform");
|
|
inputTexelSize = Shader.PropertyToID("_Input_TexelSize");
|
|
aoTexelSize = Shader.PropertyToID("_AO_TexelSize");
|
|
deinterleavedAOTexelSize = Shader.PropertyToID("_DeinterleavedAO_TexelSize");
|
|
reinterleavedAOTexelSize = Shader.PropertyToID("_ReinterleavedAO_TexelSize");
|
|
uvToView = Shader.PropertyToID("_UVToView");
|
|
worldToCameraMatrix = Shader.PropertyToID("_WorldToCameraMatrix");
|
|
targetScale = Shader.PropertyToID("_TargetScale");
|
|
radius = Shader.PropertyToID("_Radius");
|
|
maxRadiusPixels = Shader.PropertyToID("_MaxRadiusPixels");
|
|
negInvRadius2 = Shader.PropertyToID("_NegInvRadius2");
|
|
angleBias = Shader.PropertyToID("_AngleBias");
|
|
aoMultiplier = Shader.PropertyToID("_AOmultiplier");
|
|
intensity = Shader.PropertyToID("_Intensity");
|
|
multiBounceInfluence = Shader.PropertyToID("_MultiBounceInfluence");
|
|
offscreenSamplesContrib = Shader.PropertyToID("_OffscreenSamplesContrib");
|
|
maxDistance = Shader.PropertyToID("_MaxDistance");
|
|
distanceFalloff = Shader.PropertyToID("_DistanceFalloff");
|
|
baseColor = Shader.PropertyToID("_BaseColor");
|
|
colorBleedSaturation = Shader.PropertyToID("_ColorBleedSaturation");
|
|
albedoMultiplier = Shader.PropertyToID("_AlbedoMultiplier");
|
|
colorBleedBrightnessMask = Shader.PropertyToID("_ColorBleedBrightnessMask");
|
|
colorBleedBrightnessMaskRange = Shader.PropertyToID("_ColorBleedBrightnessMaskRange");
|
|
blurDeltaUV = Shader.PropertyToID("_BlurDeltaUV");
|
|
blurSharpness = Shader.PropertyToID("_BlurSharpness");
|
|
temporalParams = Shader.PropertyToID("_TemporalParams");
|
|
historyBufferRTHandleScale = Shader.PropertyToID("_HistoryBuffer_RTHandleScale");
|
|
}
|
|
|
|
public static string GetOrthographicProjectionKeyword(bool orthographic)
|
|
{
|
|
return orthographic ? "ORTHOGRAPHIC_PROJECTION" : "__";
|
|
}
|
|
|
|
public static string GetQualityKeyword(HBAO.Quality quality)
|
|
{
|
|
switch (quality)
|
|
{
|
|
case HBAO.Quality.Lowest:
|
|
return "QUALITY_LOWEST";
|
|
case HBAO.Quality.Low:
|
|
return "QUALITY_LOW";
|
|
case HBAO.Quality.Medium:
|
|
return "QUALITY_MEDIUM";
|
|
case HBAO.Quality.High:
|
|
return "QUALITY_HIGH";
|
|
case HBAO.Quality.Highest:
|
|
return "QUALITY_HIGHEST";
|
|
default:
|
|
return "QUALITY_MEDIUM";
|
|
}
|
|
}
|
|
|
|
public static string GetNoiseKeyword(HBAO.NoiseType noiseType)
|
|
{
|
|
switch (noiseType)
|
|
{
|
|
case HBAO.NoiseType.InterleavedGradientNoise:
|
|
return "INTERLEAVED_GRADIENT_NOISE";
|
|
case HBAO.NoiseType.Dither:
|
|
case HBAO.NoiseType.SpatialDistribution:
|
|
default:
|
|
return "__";
|
|
}
|
|
}
|
|
|
|
public static string GetDeinterleavingKeyword(HBAO.Deinterleaving deinterleaving)
|
|
{
|
|
switch (deinterleaving)
|
|
{
|
|
case HBAO.Deinterleaving.x4:
|
|
return "DEINTERLEAVED";
|
|
case HBAO.Deinterleaving.Disabled:
|
|
default:
|
|
return "__";
|
|
}
|
|
}
|
|
|
|
public static string GetDebugKeyword(HBAO.DebugMode debugMode)
|
|
{
|
|
switch (debugMode)
|
|
{
|
|
case HBAO.DebugMode.AOOnly:
|
|
return "DEBUG_AO";
|
|
case HBAO.DebugMode.ColorBleedingOnly:
|
|
return "DEBUG_COLORBLEEDING";
|
|
case HBAO.DebugMode.SplitWithoutAOAndWithAO:
|
|
return "DEBUG_NOAO_AO";
|
|
case HBAO.DebugMode.SplitWithAOAndAOOnly:
|
|
return "DEBUG_AO_AOONLY";
|
|
case HBAO.DebugMode.SplitWithoutAOAndAOOnly:
|
|
return "DEBUG_NOAO_AOONLY";
|
|
case HBAO.DebugMode.Disabled:
|
|
default:
|
|
return "__";
|
|
}
|
|
}
|
|
|
|
public static string GetMultibounceKeyword(bool useMultiBounce, bool litAoModeEnabled)
|
|
{
|
|
return useMultiBounce && !litAoModeEnabled ? "MULTIBOUNCE" : "__";
|
|
}
|
|
|
|
public static string GetOffscreenSamplesContributionKeyword(float offscreenSamplesContribution)
|
|
{
|
|
return offscreenSamplesContribution > 0 ? "OFFSCREEN_SAMPLES_CONTRIBUTION" : "__";
|
|
}
|
|
|
|
public static string GetPerPixelNormalsKeyword(HBAO.PerPixelNormals perPixelNormals)
|
|
{
|
|
switch (perPixelNormals)
|
|
{
|
|
case HBAO.PerPixelNormals.Reconstruct4Samples:
|
|
return "NORMALS_RECONSTRUCT4";
|
|
case HBAO.PerPixelNormals.Reconstruct2Samples:
|
|
return "NORMALS_RECONSTRUCT2";
|
|
case HBAO.PerPixelNormals.Camera:
|
|
default:
|
|
return "__";
|
|
}
|
|
}
|
|
|
|
public static string GetBlurRadiusKeyword(HBAO.BlurType blurType)
|
|
{
|
|
switch (blurType)
|
|
{
|
|
case HBAO.BlurType.Narrow:
|
|
return "BLUR_RADIUS_2";
|
|
case HBAO.BlurType.Medium:
|
|
return "BLUR_RADIUS_3";
|
|
case HBAO.BlurType.Wide:
|
|
return "BLUR_RADIUS_4";
|
|
case HBAO.BlurType.ExtraWide:
|
|
return "BLUR_RADIUS_5";
|
|
case HBAO.BlurType.None:
|
|
default:
|
|
return "BLUR_RADIUS_3";
|
|
}
|
|
}
|
|
|
|
public static string GetVarianceClippingKeyword(HBAO.VarianceClipping varianceClipping)
|
|
{
|
|
switch (varianceClipping)
|
|
{
|
|
case HBAO.VarianceClipping._4Tap:
|
|
return "VARIANCE_CLIPPING_4TAP";
|
|
case HBAO.VarianceClipping._8Tap:
|
|
return "VARIANCE_CLIPPING_8TAP";
|
|
case HBAO.VarianceClipping.Disabled:
|
|
default:
|
|
return "__";
|
|
}
|
|
}
|
|
|
|
public static string GetColorBleedingKeyword(bool colorBleedingEnabled, bool litAoModeEnabled)
|
|
{
|
|
return colorBleedingEnabled && !litAoModeEnabled ? "COLOR_BLEEDING" : "__";
|
|
}
|
|
|
|
public static string GetModeKeyword(HBAO.Mode mode)
|
|
{
|
|
return mode == HBAO.Mode.LitAO ? "LIT_AO" : "__";
|
|
}
|
|
}
|
|
|
|
private static class MersenneTwister
|
|
{
|
|
// Mersenne-Twister random numbers in [0,1).
|
|
public static float[] Numbers = new float[] {
|
|
//0.463937f,0.340042f,0.223035f,0.468465f,0.322224f,0.979269f,0.031798f,0.973392f,0.778313f,0.456168f,0.258593f,0.330083f,0.387332f,0.380117f,0.179842f,0.910755f,
|
|
//0.511623f,0.092933f,0.180794f,0.620153f,0.101348f,0.556342f,0.642479f,0.442008f,0.215115f,0.475218f,0.157357f,0.568868f,0.501241f,0.629229f,0.699218f,0.707733f
|
|
0.556725f,0.005520f,0.708315f,0.583199f,0.236644f,0.992380f,0.981091f,0.119804f,0.510866f,0.560499f,0.961497f,0.557862f,0.539955f,0.332871f,0.417807f,0.920779f,
|
|
0.730747f,0.076690f,0.008562f,0.660104f,0.428921f,0.511342f,0.587871f,0.906406f,0.437980f,0.620309f,0.062196f,0.119485f,0.235646f,0.795892f,0.044437f,0.617311f
|
|
};
|
|
}
|
|
|
|
private class CameraHistoryBuffers
|
|
{
|
|
public CameraData cameraData { get; set; }
|
|
public BufferedRTHandleSystem historyRTSystem { get; set; }
|
|
public int frameCount { get; set; }
|
|
public int lastRenderedFrame { get; set; }
|
|
}
|
|
|
|
private enum HistoryBufferType
|
|
{
|
|
AmbientOcclusion,
|
|
ColorBleeding
|
|
}
|
|
|
|
private static readonly Vector2[] s_jitter = new Vector2[4 * 4];
|
|
private static readonly float[] s_temporalRotations = { 60.0f, 300.0f, 180.0f, 240.0f, 120.0f, 0.0f };
|
|
private static readonly float[] s_temporalOffsets = { 0.0f, 0.5f, 0.25f, 0.75f };
|
|
|
|
private Material material { get; set; }
|
|
private RenderTargetIdentifier source { get; set; }
|
|
private CameraData cameraData { get; set; }
|
|
private RenderTextureDescriptor sourceDesc { get; set; }
|
|
private RenderTextureDescriptor aoDesc { get; set; }
|
|
private RenderTextureDescriptor deinterleavedDepthDesc { get; set; }
|
|
private RenderTextureDescriptor deinterleavedNormalsDesc { get; set; }
|
|
private RenderTextureDescriptor deinterleavedAoDesc { get; set; }
|
|
private RenderTextureDescriptor reinterleavedAoDesc { get; set; }
|
|
private RenderTextureFormat colorFormat { get; set; }
|
|
private GraphicsFormat graphicsColorFormat { get; set; }
|
|
private RenderTextureFormat depthFormat { get; set; }
|
|
private RenderTextureFormat normalsFormat { get; set; }
|
|
private bool motionVectorsSupported { get; set; }
|
|
private Texture2D noiseTex { get; set; }
|
|
private int numberOfEyes { get; set; }
|
|
private static bool isLinearColorSpace { get { return QualitySettings.activeColorSpace == ColorSpace.Linear; } }
|
|
private bool renderingInSceneView { get { return cameraData.camera.cameraType == CameraType.SceneView; } }
|
|
|
|
private HBAO.Resolution? m_PreviousResolution;
|
|
private HBAO.NoiseType? m_PreviousNoiseType;
|
|
private bool m_PreviousColorBleedingEnabled;
|
|
private string[] m_ShaderKeywords;
|
|
private RenderTargetIdentifier[] m_RtsDepth = new RenderTargetIdentifier[4];
|
|
private RenderTargetIdentifier[] m_RtsNormals = new RenderTargetIdentifier[4];
|
|
private List<CameraHistoryBuffers> m_CameraHistoryBuffers = new List<CameraHistoryBuffers>();
|
|
|
|
public void FillSupportedRenderTextureFormats()
|
|
{
|
|
colorFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default;
|
|
graphicsColorFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf) ? GraphicsFormat.R16G16B16A16_SFloat : GraphicsFormat.R8G8B8A8_SRGB;
|
|
depthFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RFloat) ? RenderTextureFormat.RFloat : RenderTextureFormat.RHalf;
|
|
normalsFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB2101010) ? RenderTextureFormat.ARGB2101010 : RenderTextureFormat.Default;
|
|
motionVectorsSupported = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf);
|
|
}
|
|
|
|
public void Setup(Shader shader, ScriptableRenderer renderer, RenderingData renderingData)
|
|
{
|
|
if (material == null) material = CoreUtils.CreateEngineMaterial(shader);
|
|
|
|
#if !URP_10_0_0_OR_NEWER
|
|
source = renderer.cameraColorTarget;
|
|
cameraData = renderingData.cameraData;
|
|
|
|
// Configures where the render pass should be injected.
|
|
FetchVolumeComponent();
|
|
renderPassEvent = hbao.debugMode.value == HBAO.DebugMode.Disabled ?
|
|
RenderPassEvent.BeforeRenderingTransparents :
|
|
RenderPassEvent.AfterRenderingTransparents;
|
|
#endif
|
|
}
|
|
|
|
#if URP_10_0_0_OR_NEWER
|
|
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
|
{
|
|
source = renderingData.cameraData.renderer.cameraColorTargetHandle;
|
|
cameraData = renderingData.cameraData;
|
|
|
|
FetchVolumeComponent();
|
|
|
|
var passInput = ScriptableRenderPassInput.Depth;
|
|
if (hbao.perPixelNormals.value == HBAO.PerPixelNormals.Camera)
|
|
passInput |= ScriptableRenderPassInput.Normal;
|
|
#if UNITY_2021_2_OR_NEWER
|
|
if (hbao.temporalFilterEnabled.value)
|
|
passInput |= ScriptableRenderPassInput.Motion;
|
|
#endif
|
|
ConfigureInput(passInput);
|
|
|
|
#if UNITY_2021_2_OR_NEWER
|
|
ConfigureColorStoreAction(RenderBufferStoreAction.DontCare);
|
|
|
|
// 렌더링 순서를 투명 오브젝트 이후로 변경
|
|
renderPassEvent = hbao.debugMode.value == HBAO.DebugMode.Disabled ?
|
|
hbao.mode.value == HBAO.Mode.LitAO ?
|
|
hbao.renderingPath.value == HBAO.RenderingPath.Deferred ? RenderPassEvent.AfterRenderingGbuffer : RenderPassEvent.AfterRenderingTransparents + 1 :
|
|
RenderPassEvent.AfterRenderingTransparents + 1 : RenderPassEvent.AfterRenderingTransparents;
|
|
#else
|
|
// 렌더링 순서를 투명 오브젝트 이후로 변경
|
|
renderPassEvent = hbao.debugMode.value == HBAO.DebugMode.Disabled ?
|
|
hbao.mode.value == HBAO.Mode.LitAO ? RenderPassEvent.AfterRenderingTransparents + 1 : RenderPassEvent.AfterRenderingTransparents + 1 :
|
|
RenderPassEvent.AfterRenderingTransparents;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
// This method is called before executing the render pass.
|
|
// It can be used to configure render targets and their clear state. Also to create temporary render target textures.
|
|
// When empty this render pass will render to the active camera render target.
|
|
// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
|
|
// The render pipeline will ensure target setup and clearing happens in an performance manner.
|
|
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
|
{
|
|
if (material == null) return;
|
|
|
|
FetchVolumeComponent();
|
|
|
|
if (!hbao.IsActive()) return;
|
|
|
|
FetchRenderParameters(cameraTextureDescriptor);
|
|
CheckParameters();
|
|
UpdateMaterialProperties();
|
|
UpdateShaderKeywords();
|
|
}
|
|
|
|
// Here you can implement the rendering logic.
|
|
// Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
|
|
// https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
|
|
// You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
|
{
|
|
if (material == null)
|
|
{
|
|
Debug.LogError("HBAO material has not been correctly initialized...");
|
|
return;
|
|
}
|
|
|
|
if (!hbao.IsActive()) return;
|
|
|
|
#if UNITY_2021_2_OR_NEWER
|
|
var historyBuffers = GetCurrentCameraHistoryBuffers();
|
|
historyBuffers?.historyRTSystem.SwapAndSetReferenceSize(aoDesc.width, aoDesc.height);
|
|
#else
|
|
var historyBuffers = null as CameraHistoryBuffers;
|
|
#endif
|
|
|
|
var cmd = CommandBufferPool.Get("HBAO");
|
|
|
|
if (hbao.mode.value == HBAO.Mode.LitAO)
|
|
{
|
|
#if URP_10_0_0_OR_NEWER
|
|
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.ScreenSpaceOcclusion, true);
|
|
#endif
|
|
cmd.GetTemporaryRT(ShaderProperties.ssaoTex, aoDesc, FilterMode.Bilinear);
|
|
}
|
|
else
|
|
{
|
|
cmd.GetTemporaryRT(ShaderProperties.inputTex, sourceDesc, FilterMode.Point);
|
|
|
|
// Source copy
|
|
CopySource(cmd);
|
|
}
|
|
|
|
// AO
|
|
cmd.SetGlobalVector(ShaderProperties.temporalParams, historyBuffers != null ? new Vector2(s_temporalRotations[historyBuffers.frameCount % 6] / 360.0f, s_temporalOffsets[historyBuffers.frameCount % 4]) : Vector2.zero);
|
|
if (hbao.deinterleaving.value == HBAO.Deinterleaving.Disabled)
|
|
{
|
|
cmd.GetTemporaryRT(ShaderProperties.hbaoTex, aoDesc, FilterMode.Bilinear);
|
|
AO(cmd);
|
|
}
|
|
else
|
|
{
|
|
cmd.GetTemporaryRT(ShaderProperties.hbaoTex, reinterleavedAoDesc, FilterMode.Bilinear);
|
|
DeinterleavedAO(cmd);
|
|
}
|
|
|
|
// Blur
|
|
Blur(cmd);
|
|
|
|
// Temporal Filter
|
|
TemporalFilter(cmd, historyBuffers);
|
|
|
|
// Composite
|
|
Composite(cmd);
|
|
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.hbaoTex);
|
|
if (hbao.mode.value != HBAO.Mode.LitAO) cmd.ReleaseTemporaryRT(ShaderProperties.inputTex);
|
|
|
|
context.ExecuteCommandBuffer(cmd);
|
|
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
/// Cleanup any allocated resources that were created during the execution of this render pass.
|
|
public override void FrameCleanup(CommandBuffer cmd)
|
|
{
|
|
if (hbao.mode.value == HBAO.Mode.LitAO)
|
|
{
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.ssaoTex);
|
|
#if URP_10_0_0_OR_NEWER
|
|
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.ScreenSpaceOcclusion, false);
|
|
#endif
|
|
}
|
|
|
|
// we release any camera history buffers that has not rendered for more than 1 frames
|
|
for (var i = m_CameraHistoryBuffers.Count - 1; i >= 0; i--)
|
|
{
|
|
var buffers = m_CameraHistoryBuffers[i];
|
|
if (Time.frameCount - buffers.lastRenderedFrame > 1)
|
|
ReleaseCameraHistoryBuffers(ref buffers);
|
|
}
|
|
}
|
|
|
|
public void Cleanup()
|
|
{
|
|
for (var i = m_CameraHistoryBuffers.Count - 1; i >= 0; i--)
|
|
{
|
|
var buffers = m_CameraHistoryBuffers[i];
|
|
ReleaseCameraHistoryBuffers(ref buffers);
|
|
}
|
|
|
|
CoreUtils.Destroy(material);
|
|
CoreUtils.Destroy(noiseTex);
|
|
}
|
|
|
|
private void FetchVolumeComponent()
|
|
{
|
|
if (hbao == null)
|
|
hbao = VolumeManager.instance.stack.GetComponent<HBAO>();
|
|
}
|
|
|
|
private void FetchRenderParameters(RenderTextureDescriptor cameraTextureDesc)
|
|
{
|
|
cameraTextureDesc.msaaSamples = 1;
|
|
cameraTextureDesc.depthBufferBits = 0;
|
|
sourceDesc = cameraTextureDesc;
|
|
|
|
var width = cameraTextureDesc.width;
|
|
var height = cameraTextureDesc.height;
|
|
var downsamplingFactor = hbao.resolution.value == HBAO.Resolution.Full ? 1 : hbao.deinterleaving.value == HBAO.Deinterleaving.Disabled ? 2 : 1;
|
|
if (downsamplingFactor > 1)
|
|
{
|
|
width = (width + width % 2) / downsamplingFactor;
|
|
height = (height + height % 2) / downsamplingFactor;
|
|
}
|
|
|
|
aoDesc = GetStereoCompatibleDescriptor(width, height, format: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|
|
|
if (hbao.deinterleaving.value != HBAO.Deinterleaving.Disabled)
|
|
{
|
|
var reinterleavedWidth = cameraTextureDesc.width + (cameraTextureDesc.width % 4 == 0 ? 0 : 4 - (cameraTextureDesc.width % 4));
|
|
var reinterleavedHeight = cameraTextureDesc.height + (cameraTextureDesc.height % 4 == 0 ? 0 : 4 - (cameraTextureDesc.height % 4));
|
|
var deinterleavedWidth = reinterleavedWidth / 4;
|
|
var deinterleavedHeight = reinterleavedHeight / 4;
|
|
|
|
deinterleavedDepthDesc = GetStereoCompatibleDescriptor(deinterleavedWidth, deinterleavedHeight, format: depthFormat, readWrite: RenderTextureReadWrite.Linear);
|
|
deinterleavedNormalsDesc = GetStereoCompatibleDescriptor(deinterleavedWidth, deinterleavedHeight, format: normalsFormat, readWrite: RenderTextureReadWrite.Linear);
|
|
deinterleavedAoDesc = GetStereoCompatibleDescriptor(deinterleavedWidth, deinterleavedHeight, format: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|
reinterleavedAoDesc = GetStereoCompatibleDescriptor(reinterleavedWidth, reinterleavedHeight, format: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|
}
|
|
|
|
numberOfEyes = 1;
|
|
#if ENABLE_VR
|
|
if (XRSettings.enabled)
|
|
numberOfEyes = 2;
|
|
#endif
|
|
}
|
|
|
|
private RTHandle HistoryBufferAllocator(RTHandleSystem rtHandleSystem, int frameIndex)
|
|
{
|
|
return rtHandleSystem.Alloc(Vector2.one, colorFormat: graphicsColorFormat, useDynamicScale: true, name: "HBAO_HistoryBuffer_" + frameIndex);
|
|
}
|
|
|
|
private void AllocCameraHistoryBuffers(ref CameraHistoryBuffers buffers)
|
|
{
|
|
buffers = new CameraHistoryBuffers();
|
|
buffers.cameraData = cameraData;
|
|
buffers.frameCount = 0;
|
|
buffers.historyRTSystem = new BufferedRTHandleSystem(); // https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@12.0/manual/rthandle-system-using.html
|
|
buffers.historyRTSystem.AllocBuffer((int)HistoryBufferType.AmbientOcclusion, HistoryBufferAllocator, 2);
|
|
if (hbao.colorBleedingEnabled.value)
|
|
buffers.historyRTSystem.AllocBuffer((int)HistoryBufferType.ColorBleeding, HistoryBufferAllocator, 2);
|
|
|
|
m_CameraHistoryBuffers.Add(buffers);
|
|
}
|
|
|
|
private void ReleaseCameraHistoryBuffers(ref CameraHistoryBuffers buffers)
|
|
{
|
|
buffers.historyRTSystem.ReleaseAll();
|
|
buffers.historyRTSystem.Dispose();
|
|
|
|
m_CameraHistoryBuffers.Remove(buffers);
|
|
|
|
buffers = null;
|
|
}
|
|
|
|
private CameraHistoryBuffers GetCurrentCameraHistoryBuffers()
|
|
{
|
|
CameraHistoryBuffers buffers = null;
|
|
if (hbao.temporalFilterEnabled.value && !renderingInSceneView)
|
|
{
|
|
for (var i = 0; i < m_CameraHistoryBuffers.Count; i++)
|
|
{
|
|
if (m_CameraHistoryBuffers[i].cameraData.camera == cameraData.camera)
|
|
{
|
|
buffers = m_CameraHistoryBuffers[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((m_PreviousColorBleedingEnabled != hbao.colorBleedingEnabled.value ||
|
|
m_PreviousResolution != hbao.resolution.value)
|
|
&& buffers != null)
|
|
{
|
|
ReleaseCameraHistoryBuffers(ref buffers);
|
|
m_PreviousColorBleedingEnabled = hbao.colorBleedingEnabled.value;
|
|
m_PreviousResolution = hbao.resolution.value;
|
|
}
|
|
|
|
if (buffers == null)
|
|
AllocCameraHistoryBuffers(ref buffers);
|
|
}
|
|
|
|
return buffers;
|
|
}
|
|
|
|
private void CopySource(CommandBuffer cmd)
|
|
{
|
|
BlitFullscreenMesh(cmd, source, ShaderProperties.inputTex, material, Pass.Copy);
|
|
}
|
|
|
|
private void AO(CommandBuffer cmd)
|
|
{
|
|
BlitFullscreenMeshWithClear(cmd, hbao.mode.value == HBAO.Mode.LitAO ? source : ShaderProperties.inputTex, ShaderProperties.hbaoTex, material, new Color(0, 0, 0, 1), Pass.AO);
|
|
}
|
|
|
|
private void DeinterleavedAO(CommandBuffer cmd)
|
|
{
|
|
// Deinterleave depth & normals (4x4)
|
|
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_RtsDepth[0] = ShaderProperties.depthSliceTex[(i << 2) + 0];
|
|
m_RtsDepth[1] = ShaderProperties.depthSliceTex[(i << 2) + 1];
|
|
m_RtsDepth[2] = ShaderProperties.depthSliceTex[(i << 2) + 2];
|
|
m_RtsDepth[3] = ShaderProperties.depthSliceTex[(i << 2) + 3];
|
|
m_RtsNormals[0] = ShaderProperties.normalsSliceTex[(i << 2) + 0];
|
|
m_RtsNormals[1] = ShaderProperties.normalsSliceTex[(i << 2) + 1];
|
|
m_RtsNormals[2] = ShaderProperties.normalsSliceTex[(i << 2) + 2];
|
|
m_RtsNormals[3] = ShaderProperties.normalsSliceTex[(i << 2) + 3];
|
|
|
|
int offsetX = (i & 1) << 1; int offsetY = (i >> 1) << 1;
|
|
cmd.SetGlobalVector(ShaderProperties.deinterleaveOffset[0], new Vector2(offsetX + 0, offsetY + 0));
|
|
cmd.SetGlobalVector(ShaderProperties.deinterleaveOffset[1], new Vector2(offsetX + 1, offsetY + 0));
|
|
cmd.SetGlobalVector(ShaderProperties.deinterleaveOffset[2], new Vector2(offsetX + 0, offsetY + 1));
|
|
cmd.SetGlobalVector(ShaderProperties.deinterleaveOffset[3], new Vector2(offsetX + 1, offsetY + 1));
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
cmd.GetTemporaryRT(ShaderProperties.depthSliceTex[j + 4 * i], deinterleavedDepthDesc, FilterMode.Point);
|
|
cmd.GetTemporaryRT(ShaderProperties.normalsSliceTex[j + 4 * i], deinterleavedNormalsDesc, FilterMode.Point);
|
|
}
|
|
BlitFullscreenMesh(cmd, BuiltinRenderTextureType.CameraTarget, m_RtsDepth, material, Pass.Deinterleave_Depth); // outputs 4 render textures
|
|
BlitFullscreenMesh(cmd, BuiltinRenderTextureType.CameraTarget, m_RtsNormals, material, Pass.Deinterleave_Normals); // outputs 4 render textures
|
|
}
|
|
cmd.SetViewProjectionMatrices(cameraData.camera.worldToCameraMatrix, cameraData.camera.projectionMatrix);
|
|
|
|
// AO on each layer
|
|
for (int i = 0; i < 4 * 4; i++)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.depthTex, ShaderProperties.depthSliceTex[i]);
|
|
cmd.SetGlobalTexture(ShaderProperties.normalsTex, ShaderProperties.normalsSliceTex[i]);
|
|
cmd.SetGlobalVector(ShaderProperties.jitter, s_jitter[i]);
|
|
cmd.GetTemporaryRT(ShaderProperties.aoSliceTex[i], deinterleavedAoDesc, FilterMode.Point);
|
|
BlitFullscreenMeshWithClear(cmd, hbao.mode.value == HBAO.Mode.LitAO ? source : ShaderProperties.inputTex, ShaderProperties.aoSliceTex[i], material, new Color(0, 0, 0, 1), Pass.AO_Deinterleaved); // ao
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.depthSliceTex[i]);
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.normalsSliceTex[i]);
|
|
}
|
|
|
|
// Atlas Deinterleaved AO, 4x4
|
|
cmd.GetTemporaryRT(ShaderProperties.tempTex, reinterleavedAoDesc, FilterMode.Point);
|
|
for (int i = 0; i < 4 * 4; i++)
|
|
{
|
|
cmd.SetGlobalVector(ShaderProperties.atlasOffset, new Vector2(((i & 1) + (((i & 7) >> 2) << 1)) * deinterleavedAoDesc.width, (((i & 3) >> 1) + ((i >> 3) << 1)) * deinterleavedAoDesc.height));
|
|
BlitFullscreenMesh(cmd, ShaderProperties.aoSliceTex[i], ShaderProperties.tempTex, material, Pass.Atlas_AO_Deinterleaved); // atlassing
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.aoSliceTex[i]);
|
|
}
|
|
|
|
// Reinterleave AO
|
|
BlitFullscreenMesh(cmd, ShaderProperties.tempTex, ShaderProperties.hbaoTex, material, Pass.Reinterleave_AO); // reinterleave
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.tempTex);
|
|
}
|
|
|
|
private void Blur(CommandBuffer cmd)
|
|
{
|
|
if (hbao.blurType.value != HBAO.BlurType.None)
|
|
{
|
|
cmd.GetTemporaryRT(ShaderProperties.tempTex, aoDesc, FilterMode.Bilinear);
|
|
cmd.SetGlobalVector(ShaderProperties.blurDeltaUV, new Vector2(1f / sourceDesc.width, 0));
|
|
BlitFullscreenMesh(cmd, ShaderProperties.hbaoTex, ShaderProperties.tempTex, material, Pass.Blur);
|
|
cmd.SetGlobalVector(ShaderProperties.blurDeltaUV, new Vector2(0, 1f / sourceDesc.height));
|
|
BlitFullscreenMesh(cmd, ShaderProperties.tempTex, ShaderProperties.hbaoTex, material, Pass.Blur);
|
|
cmd.ReleaseTemporaryRT(ShaderProperties.tempTex);
|
|
}
|
|
}
|
|
|
|
private void TemporalFilter(CommandBuffer cmd, CameraHistoryBuffers buffers)
|
|
{
|
|
if (hbao.temporalFilterEnabled.value && !renderingInSceneView)
|
|
{
|
|
cmd.SetGlobalVector(ShaderProperties.historyBufferRTHandleScale, buffers.historyRTSystem.rtHandleProperties.rtHandleScale);
|
|
|
|
if (buffers.frameCount == 0)
|
|
{
|
|
// buffers were just allocated this frame, clear them (previous frame RT)
|
|
cmd.SetRenderTarget(buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.AmbientOcclusion, 1));
|
|
cmd.ClearRenderTarget(false, true, Color.white);
|
|
if (hbao.colorBleedingEnabled.value)
|
|
{
|
|
cmd.SetRenderTarget(buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.ColorBleeding, 1));
|
|
cmd.ClearRenderTarget(false, true, new Color(0, 0, 0, 1));
|
|
}
|
|
}
|
|
|
|
var viewportRect = new Rect(Vector2.zero, buffers.historyRTSystem.rtHandleProperties.currentViewportSize);
|
|
|
|
if (hbao.colorBleedingEnabled.value)
|
|
{
|
|
// For Color Bleeding we have 2 history buffers to fill so there are 2 render targets.
|
|
// AO is still contained in Color Bleeding history buffer (alpha channel) so that we
|
|
// can use it as a render texture for the composite pass.
|
|
var currentFrameAORT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.AmbientOcclusion, 0);
|
|
var currentFrameCBRT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.ColorBleeding, 0);
|
|
var previousFrameAORT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.AmbientOcclusion, 1);
|
|
var previousFrameCBRT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.ColorBleeding, 1);
|
|
var rts = new RenderTargetIdentifier[] {
|
|
currentFrameAORT,
|
|
currentFrameCBRT
|
|
};
|
|
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
|
|
cmd.SetGlobalTexture(ShaderProperties.tempTex, previousFrameCBRT);
|
|
BlitFullscreenMesh(cmd, previousFrameAORT, rts, viewportRect, material, Pass.Temporal_Filter);
|
|
cmd.SetViewProjectionMatrices(cameraData.camera.worldToCameraMatrix, cameraData.camera.projectionMatrix);
|
|
cmd.SetGlobalTexture(ShaderProperties.hbaoTex, currentFrameCBRT);
|
|
}
|
|
else
|
|
{
|
|
// AO history buffer contains ao in aplha channel so we can just use history as
|
|
// a render texture for the composite pass.
|
|
var currentFrameRT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.AmbientOcclusion, 0);
|
|
var previousFrameRT = buffers.historyRTSystem.GetFrameRT((int)HistoryBufferType.AmbientOcclusion, 1);
|
|
BlitFullscreenMesh(cmd, previousFrameRT, currentFrameRT, viewportRect, material, Pass.Temporal_Filter);
|
|
cmd.SetGlobalTexture(ShaderProperties.hbaoTex, currentFrameRT);
|
|
}
|
|
|
|
// increment buffers frameCount for next frame, track last buffer use
|
|
buffers.frameCount++;
|
|
buffers.lastRenderedFrame = Time.frameCount;
|
|
}
|
|
else
|
|
cmd.SetGlobalVector(ShaderProperties.historyBufferRTHandleScale, Vector4.one);
|
|
}
|
|
|
|
private void Composite(CommandBuffer cmd)
|
|
{
|
|
// AO 결과를 메인 렌더 타겟에 합성
|
|
BlitFullscreenMesh(cmd,
|
|
hbao.mode.value == HBAO.Mode.LitAO ? source : ShaderProperties.inputTex,
|
|
source,
|
|
material,
|
|
hbao.debugMode.value == HBAO.DebugMode.ViewNormals ? Pass.Debug_ViewNormals : Pass.Composite
|
|
);
|
|
|
|
if (hbao.mode.value == HBAO.Mode.LitAO)
|
|
{
|
|
cmd.SetGlobalTexture("_ScreenSpaceOcclusionTexture", ShaderProperties.ssaoTex);
|
|
cmd.SetGlobalVector("_AmbientOcclusionParam", new Vector4(0f, 0f, 0f, hbao.directLightingStrength.value));
|
|
}
|
|
}
|
|
|
|
private void UpdateMaterialProperties()
|
|
{
|
|
var sourceWidth = cameraData.cameraTargetDescriptor.width;
|
|
var sourceHeight = cameraData.cameraTargetDescriptor.height;
|
|
|
|
//float tanHalfFovY = Mathf.Tan(0.5f * cameraData.camera.fieldOfView * Mathf.Deg2Rad);
|
|
//float invFocalLenX = 1.0f / (1.0f / tanHalfFovY * (sourceHeight / (float)sourceWidth));
|
|
//float invFocalLenY = 1.0f / (1.0f / tanHalfFovY);
|
|
float invFocalLenX = 1.0f / cameraData.camera.projectionMatrix.m00;
|
|
float invFocalLenY = 1.0f / cameraData.camera.projectionMatrix.m11;
|
|
float maxRadInPixels = Mathf.Max(16, hbao.maxRadiusPixels.value * Mathf.Sqrt((sourceWidth * numberOfEyes * sourceHeight) / (1080.0f * 1920.0f)));
|
|
maxRadInPixels /= (hbao.deinterleaving.value == HBAO.Deinterleaving.x4 ? 4 : 1);
|
|
|
|
var targetScale = hbao.deinterleaving.value == HBAO.Deinterleaving.x4 ?
|
|
new Vector4(reinterleavedAoDesc.width / (float)sourceWidth, reinterleavedAoDesc.height / (float)sourceHeight, 1.0f / (reinterleavedAoDesc.width / (float)sourceWidth), 1.0f / (reinterleavedAoDesc.height / (float)sourceHeight)) :
|
|
hbao.resolution.value == HBAO.Resolution.Half /*&& (settings.perPixelNormals.value == HBAO.PerPixelNormals.Reconstruct2Samples || settings.perPixelNormals.value == HBAO.PerPixelNormals.Reconstruct4Samples)*/ ?
|
|
new Vector4((sourceWidth + 0.5f) / sourceWidth, (sourceHeight + 0.5f) / sourceHeight, 1f, 1f) :
|
|
Vector4.one;
|
|
|
|
material.SetTexture(ShaderProperties.noiseTex, noiseTex);
|
|
material.SetVector(ShaderProperties.inputTexelSize, new Vector4(1f / sourceWidth, 1f / sourceHeight, sourceWidth, sourceHeight));
|
|
material.SetVector(ShaderProperties.aoTexelSize, new Vector4(1f / aoDesc.width, 1f / aoDesc.height, aoDesc.width, aoDesc.height));
|
|
material.SetVector(ShaderProperties.deinterleavedAOTexelSize, new Vector4(1.0f / deinterleavedAoDesc.width, 1.0f / deinterleavedAoDesc.height, deinterleavedAoDesc.width, deinterleavedAoDesc.height));
|
|
material.SetVector(ShaderProperties.reinterleavedAOTexelSize, new Vector4(1f / reinterleavedAoDesc.width, 1f / reinterleavedAoDesc.height, reinterleavedAoDesc.width, reinterleavedAoDesc.height));
|
|
material.SetVector(ShaderProperties.targetScale, targetScale);
|
|
material.SetVector(ShaderProperties.uvToView, new Vector4(2.0f * invFocalLenX, -2.0f * invFocalLenY, -1.0f * invFocalLenX, 1.0f * invFocalLenY));
|
|
material.SetMatrix(ShaderProperties.worldToCameraMatrix, cameraData.camera.worldToCameraMatrix);
|
|
//material.SetFloat(ShaderProperties.radius, hbao.radius.value * 0.5f * ((sourceHeight / (hbao.deinterleaving.value == HBAO.Deinterleaving.x4 ? 4 : 1)) / (tanHalfFovY * 2.0f)));
|
|
material.SetFloat(ShaderProperties.radius, hbao.radius.value * 0.5f * ((sourceHeight / (hbao.deinterleaving.value == HBAO.Deinterleaving.x4 ? 4 : 1)) / (invFocalLenY * 2.0f)));
|
|
material.SetFloat(ShaderProperties.maxRadiusPixels, maxRadInPixels);
|
|
material.SetFloat(ShaderProperties.negInvRadius2, -1.0f / (hbao.radius.value * hbao.radius.value));
|
|
material.SetFloat(ShaderProperties.angleBias, hbao.bias.value);
|
|
material.SetFloat(ShaderProperties.aoMultiplier, 2.0f * (1.0f / (1.0f - hbao.bias.value)));
|
|
material.SetFloat(ShaderProperties.intensity, isLinearColorSpace ? hbao.intensity.value : hbao.intensity.value * 0.454545454545455f);
|
|
material.SetFloat(ShaderProperties.multiBounceInfluence, hbao.multiBounceInfluence.value);
|
|
material.SetFloat(ShaderProperties.offscreenSamplesContrib, hbao.offscreenSamplesContribution.value);
|
|
material.SetFloat(ShaderProperties.maxDistance, hbao.maxDistance.value);
|
|
material.SetFloat(ShaderProperties.distanceFalloff, hbao.distanceFalloff.value);
|
|
material.SetColor(ShaderProperties.baseColor, hbao.baseColor.value);
|
|
material.SetFloat(ShaderProperties.blurSharpness, hbao.sharpness.value);
|
|
material.SetFloat(ShaderProperties.colorBleedSaturation, hbao.saturation.value);
|
|
material.SetFloat(ShaderProperties.colorBleedBrightnessMask, hbao.brightnessMask.value);
|
|
material.SetVector(ShaderProperties.colorBleedBrightnessMaskRange, AdjustBrightnessMaskToGammaSpace(new Vector2(Mathf.Pow(hbao.brightnessMaskRange.value.x, 3), Mathf.Pow(hbao.brightnessMaskRange.value.y, 3))));
|
|
}
|
|
|
|
private void UpdateShaderKeywords()
|
|
{
|
|
if (m_ShaderKeywords == null || m_ShaderKeywords.Length != 12) m_ShaderKeywords = new string[12];
|
|
|
|
m_ShaderKeywords[0] = ShaderProperties.GetOrthographicProjectionKeyword(cameraData.camera.orthographic);
|
|
m_ShaderKeywords[1] = ShaderProperties.GetQualityKeyword(hbao.quality.value);
|
|
m_ShaderKeywords[2] = ShaderProperties.GetNoiseKeyword(hbao.noiseType.value);
|
|
m_ShaderKeywords[3] = ShaderProperties.GetDeinterleavingKeyword(hbao.deinterleaving.value);
|
|
m_ShaderKeywords[4] = ShaderProperties.GetDebugKeyword(hbao.debugMode.value);
|
|
m_ShaderKeywords[5] = ShaderProperties.GetMultibounceKeyword(hbao.useMultiBounce.value, hbao.mode.value == HBAO.Mode.LitAO);
|
|
m_ShaderKeywords[6] = ShaderProperties.GetOffscreenSamplesContributionKeyword(hbao.offscreenSamplesContribution.value);
|
|
m_ShaderKeywords[7] = ShaderProperties.GetPerPixelNormalsKeyword(hbao.perPixelNormals.value);
|
|
m_ShaderKeywords[8] = ShaderProperties.GetBlurRadiusKeyword(hbao.blurType.value);
|
|
m_ShaderKeywords[9] = ShaderProperties.GetVarianceClippingKeyword(hbao.varianceClipping.value);
|
|
m_ShaderKeywords[10] = ShaderProperties.GetColorBleedingKeyword(hbao.colorBleedingEnabled.value, hbao.mode.value == HBAO.Mode.LitAO);
|
|
m_ShaderKeywords[11] = ShaderProperties.GetModeKeyword(hbao.mode.value);
|
|
|
|
material.shaderKeywords = m_ShaderKeywords;
|
|
}
|
|
|
|
private void CheckParameters()
|
|
{
|
|
if (hbao.deinterleaving.value != HBAO.Deinterleaving.Disabled && SystemInfo.supportedRenderTargetCount < 4)
|
|
hbao.SetDeinterleaving(HBAO.Deinterleaving.Disabled);
|
|
|
|
if (hbao.temporalFilterEnabled.value && !motionVectorsSupported)
|
|
hbao.EnableTemporalFilter(false);
|
|
|
|
if (hbao.colorBleedingEnabled.value && hbao.temporalFilterEnabled.value && SystemInfo.supportedRenderTargetCount < 2)
|
|
hbao.EnableTemporalFilter(false);
|
|
|
|
if (hbao.colorBleedingEnabled.value && hbao.mode.value == HBAO.Mode.LitAO)
|
|
hbao.EnableColorBleeding(false);
|
|
|
|
// Noise texture
|
|
if (noiseTex == null || m_PreviousNoiseType != hbao.noiseType.value)
|
|
{
|
|
CoreUtils.Destroy(noiseTex);
|
|
|
|
CreateNoiseTexture();
|
|
|
|
m_PreviousNoiseType = hbao.noiseType.value;
|
|
}
|
|
}
|
|
|
|
private RenderTextureDescriptor GetStereoCompatibleDescriptor(int width, int height, RenderTextureFormat format = RenderTextureFormat.Default, int depthBufferBits = 0, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default)
|
|
{
|
|
// Inherit the VR setup from the camera descriptor
|
|
var desc = sourceDesc;
|
|
desc.depthBufferBits = depthBufferBits;
|
|
desc.msaaSamples = 1;
|
|
desc.width = width;
|
|
desc.height = height;
|
|
desc.colorFormat = format;
|
|
|
|
if (readWrite == RenderTextureReadWrite.sRGB)
|
|
desc.sRGB = true;
|
|
else if (readWrite == RenderTextureReadWrite.Linear)
|
|
desc.sRGB = false;
|
|
else if (readWrite == RenderTextureReadWrite.Default)
|
|
desc.sRGB = isLinearColorSpace;
|
|
|
|
return desc;
|
|
}
|
|
|
|
public void BlitFullscreenMesh(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, int passIndex = 0)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|
cmd.SetRenderTarget(destination, 0, CubemapFace.Unknown, -1);
|
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex);
|
|
}
|
|
|
|
public void BlitFullscreenMesh(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Rect viewportRect, Material material, int passIndex = 0)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|
cmd.SetRenderTarget(destination, 0, CubemapFace.Unknown, -1);
|
|
cmd.SetViewport(viewportRect);
|
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex);
|
|
}
|
|
|
|
public void BlitFullscreenMesh(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier[] destinations, Material material, int passIndex = 0)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|
cmd.SetRenderTarget(destinations, destinations[0], 0, CubemapFace.Unknown, -1);
|
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex);
|
|
}
|
|
|
|
public void BlitFullscreenMesh(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier[] destinations, Rect viewportRect, Material material, int passIndex = 0)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|
cmd.SetRenderTarget(destinations, destinations[0], 0, CubemapFace.Unknown, -1);
|
|
cmd.SetViewport(viewportRect);
|
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex);
|
|
}
|
|
|
|
public void BlitFullscreenMeshWithClear(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, Color clearColor, int passIndex = 0)
|
|
{
|
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|
cmd.SetRenderTarget(destination, 0, CubemapFace.Unknown, -1);
|
|
cmd.ClearRenderTarget(false, true, clearColor);
|
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex);
|
|
}
|
|
|
|
private Vector2 AdjustBrightnessMaskToGammaSpace(Vector2 v)
|
|
{
|
|
return isLinearColorSpace ? v : ToGammaSpace(v);
|
|
}
|
|
|
|
private float ToGammaSpace(float v)
|
|
{
|
|
return Mathf.Pow(v, 0.454545454545455f);
|
|
}
|
|
|
|
private Vector2 ToGammaSpace(Vector2 v)
|
|
{
|
|
return new Vector2(ToGammaSpace(v.x), ToGammaSpace(v.y));
|
|
}
|
|
|
|
private void CreateNoiseTexture()
|
|
{
|
|
noiseTex = new Texture2D(4, 4, SystemInfo.SupportsTextureFormat(TextureFormat.RGHalf) ? TextureFormat.RGHalf : TextureFormat.RGB24, false, true);
|
|
noiseTex.filterMode = FilterMode.Point;
|
|
noiseTex.wrapMode = TextureWrapMode.Repeat;
|
|
int z = 0;
|
|
for (int x = 0; x < 4; ++x)
|
|
{
|
|
for (int y = 0; y < 4; ++y)
|
|
{
|
|
float r1 = hbao.noiseType.value != HBAO.NoiseType.Dither ? 0.25f * (0.0625f * ((x + y & 3) << 2) + (x & 3)) : MersenneTwister.Numbers[z++];
|
|
float r2 = hbao.noiseType.value != HBAO.NoiseType.Dither ? 0.25f * ((y - x) & 3) : MersenneTwister.Numbers[z++];
|
|
Color color = new Color(r1, r2, 0);
|
|
noiseTex.SetPixel(x, y, color);
|
|
}
|
|
}
|
|
noiseTex.Apply();
|
|
|
|
for (int i = 0, j = 0; i < s_jitter.Length; ++i)
|
|
{
|
|
float r1 = MersenneTwister.Numbers[j++];
|
|
float r2 = MersenneTwister.Numbers[j++];
|
|
s_jitter[i] = new Vector2(r1, r2);
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField, HideInInspector]
|
|
private Shader shader;
|
|
private HBAORenderPass m_HBAORenderPass;
|
|
|
|
void OnDisable()
|
|
{
|
|
m_HBAORenderPass?.Cleanup();
|
|
}
|
|
|
|
public override void Create()
|
|
{
|
|
if (!isActive)
|
|
{
|
|
m_HBAORenderPass?.Cleanup();
|
|
m_HBAORenderPass = null;
|
|
return;
|
|
}
|
|
|
|
name = "HBAO";
|
|
|
|
m_HBAORenderPass = new HBAORenderPass();
|
|
m_HBAORenderPass.FillSupportedRenderTextureFormats();
|
|
}
|
|
|
|
#if URP_10_0_0_OR_NEWER
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
m_HBAORenderPass?.Cleanup();
|
|
m_HBAORenderPass = null;
|
|
}
|
|
#endif
|
|
|
|
// Here you can inject one or multiple render passes in the renderer.
|
|
// This method is called when setting up the renderer once per-camera.
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
|
{
|
|
shader = Shader.Find("Hidden/Universal Render Pipeline/HBAO");
|
|
if (shader == null)
|
|
{
|
|
Debug.LogWarning("HBAO shader was not found. Please ensure it compiles correctly");
|
|
return;
|
|
}
|
|
|
|
if (renderingData.cameraData.postProcessEnabled)
|
|
{
|
|
m_HBAORenderPass.Setup(shader, renderer, renderingData);
|
|
renderer.EnqueuePass(m_HBAORenderPass);
|
|
}
|
|
}
|
|
}
|
|
}
|