1824 lines
77 KiB
C#
1824 lines
77 KiB
C#
|
using UnityEngine;
|
|||
|
using UnityEngine.Rendering;
|
|||
|
#if ENABLE_VR_MODULE && ENABLE_VR
|
|||
|
using XRSettings = UnityEngine.XR.XRSettings;
|
|||
|
#endif
|
|||
|
#if UNITY_EDITOR
|
|||
|
using UnityEditor;
|
|||
|
#endif
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
|
|||
|
namespace HorizonBasedAmbientOcclusion
|
|||
|
{
|
|||
|
[ExecuteInEditMode, ImageEffectAllowedInSceneView, AddComponentMenu("Image Effects/HBAO")]
|
|||
|
[RequireComponent(typeof(Camera))]
|
|||
|
public class HBAO : MonoBehaviour
|
|||
|
{
|
|||
|
public enum Preset
|
|||
|
{
|
|||
|
FastestPerformance,
|
|||
|
FastPerformance,
|
|||
|
Normal,
|
|||
|
HighQuality,
|
|||
|
HighestQuality,
|
|||
|
Custom
|
|||
|
}
|
|||
|
|
|||
|
public enum PipelineStage
|
|||
|
{
|
|||
|
BeforeImageEffectsOpaque,
|
|||
|
AfterLighting,
|
|||
|
BeforeReflections
|
|||
|
}
|
|||
|
|
|||
|
public enum Quality
|
|||
|
{
|
|||
|
Lowest,
|
|||
|
Low,
|
|||
|
Medium,
|
|||
|
High,
|
|||
|
Highest
|
|||
|
}
|
|||
|
|
|||
|
public enum Resolution
|
|||
|
{
|
|||
|
Full,
|
|||
|
Half
|
|||
|
}
|
|||
|
|
|||
|
public enum NoiseType
|
|||
|
{
|
|||
|
Dither,
|
|||
|
InterleavedGradientNoise,
|
|||
|
SpatialDistribution
|
|||
|
}
|
|||
|
|
|||
|
public enum Deinterleaving
|
|||
|
{
|
|||
|
Disabled,
|
|||
|
x4
|
|||
|
}
|
|||
|
|
|||
|
public enum DebugMode
|
|||
|
{
|
|||
|
Disabled,
|
|||
|
AOOnly,
|
|||
|
ColorBleedingOnly,
|
|||
|
SplitWithoutAOAndWithAO,
|
|||
|
SplitWithAOAndAOOnly,
|
|||
|
SplitWithoutAOAndAOOnly,
|
|||
|
ViewNormals
|
|||
|
}
|
|||
|
|
|||
|
public enum BlurType
|
|||
|
{
|
|||
|
None,
|
|||
|
Narrow,
|
|||
|
Medium,
|
|||
|
Wide,
|
|||
|
ExtraWide
|
|||
|
}
|
|||
|
|
|||
|
public enum PerPixelNormals
|
|||
|
{
|
|||
|
GBuffer,
|
|||
|
Camera,
|
|||
|
Reconstruct
|
|||
|
}
|
|||
|
|
|||
|
public enum VarianceClipping
|
|||
|
{
|
|||
|
Disabled,
|
|||
|
_4Tap,
|
|||
|
_8Tap
|
|||
|
}
|
|||
|
|
|||
|
public Shader hbaoShader;
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct Presets
|
|||
|
{
|
|||
|
public Preset preset;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static Presets defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Presets
|
|||
|
{
|
|||
|
preset = Preset.Normal
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct GeneralSettings
|
|||
|
{
|
|||
|
[Tooltip("The stage the AO is injected into the rendering pipeline.")]
|
|||
|
[Space(6)]
|
|||
|
public PipelineStage pipelineStage;
|
|||
|
|
|||
|
[Tooltip("The quality of the AO.")]
|
|||
|
[Space(10)]
|
|||
|
public Quality quality;
|
|||
|
|
|||
|
[Tooltip("The deinterleaving factor.")]
|
|||
|
public Deinterleaving deinterleaving;
|
|||
|
|
|||
|
[Tooltip("The resolution at which the AO is calculated.")]
|
|||
|
public Resolution resolution;
|
|||
|
|
|||
|
[Tooltip("The type of noise to use.")]
|
|||
|
[Space(10)]
|
|||
|
public NoiseType noiseType;
|
|||
|
|
|||
|
[Tooltip("The debug mode actually displayed on screen.")]
|
|||
|
[Space(10)]
|
|||
|
public DebugMode debugMode;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static GeneralSettings defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new GeneralSettings
|
|||
|
{
|
|||
|
pipelineStage = PipelineStage.BeforeImageEffectsOpaque,
|
|||
|
quality = Quality.Medium,
|
|||
|
deinterleaving = Deinterleaving.Disabled,
|
|||
|
resolution = Resolution.Full,
|
|||
|
noiseType = NoiseType.Dither,
|
|||
|
debugMode = DebugMode.Disabled
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct AOSettings
|
|||
|
{
|
|||
|
[Tooltip("AO radius: this is the distance outside which occluders are ignored.")]
|
|||
|
[Space(6), Range(0.25f, 5f)]
|
|||
|
public float radius;
|
|||
|
|
|||
|
[Tooltip("Maximum radius in pixels: this prevents the radius to grow too much with close-up " +
|
|||
|
"object and impact on performances.")]
|
|||
|
[Range(16, 256)]
|
|||
|
public float maxRadiusPixels;
|
|||
|
|
|||
|
[Tooltip("For low-tessellated geometry, occlusion variations tend to appear at creases and " +
|
|||
|
"ridges, which betray the underlying tessellation. To remove these artifacts, we use " +
|
|||
|
"an angle bias parameter which restricts the hemisphere.")]
|
|||
|
[Range(0, 0.5f)]
|
|||
|
public float bias;
|
|||
|
|
|||
|
[Tooltip("This value allows to scale up the ambient occlusion values.")]
|
|||
|
[Range(0, 4)]
|
|||
|
public float intensity;
|
|||
|
|
|||
|
[Tooltip("Enable/disable MultiBounce approximation.")]
|
|||
|
public bool useMultiBounce;
|
|||
|
|
|||
|
[Tooltip("MultiBounce approximation influence.")]
|
|||
|
[Range(0, 1)]
|
|||
|
public float multiBounceInfluence;
|
|||
|
|
|||
|
[Tooltip("The amount of AO offscreen samples are contributing.")]
|
|||
|
[Range(0, 1)]
|
|||
|
public float offscreenSamplesContribution;
|
|||
|
|
|||
|
[Tooltip("The max distance to display AO.")]
|
|||
|
[Space(10)]
|
|||
|
public float maxDistance;
|
|||
|
|
|||
|
[Tooltip("The distance before max distance at which AO start to decrease.")]
|
|||
|
public float distanceFalloff;
|
|||
|
|
|||
|
[Tooltip("The type of per pixel normals to use.")]
|
|||
|
[Space(10)]
|
|||
|
public PerPixelNormals perPixelNormals;
|
|||
|
|
|||
|
[Tooltip("This setting allow you to set the base color if the AO, the alpha channel value is unused.")]
|
|||
|
[Space(10)]
|
|||
|
public Color baseColor;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static AOSettings defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new AOSettings
|
|||
|
{
|
|||
|
radius = 0.8f,
|
|||
|
maxRadiusPixels = 128f,
|
|||
|
bias = 0.05f,
|
|||
|
intensity = 1f,
|
|||
|
useMultiBounce = false,
|
|||
|
multiBounceInfluence = 1f,
|
|||
|
offscreenSamplesContribution = 0f,
|
|||
|
maxDistance = 150f,
|
|||
|
distanceFalloff = 50f,
|
|||
|
perPixelNormals = PerPixelNormals.GBuffer,
|
|||
|
baseColor = Color.black
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct TemporalFilterSettings
|
|||
|
{
|
|||
|
[Space(6)]
|
|||
|
public bool enabled;
|
|||
|
|
|||
|
[Tooltip("The type of variance clipping to use.")]
|
|||
|
public VarianceClipping varianceClipping;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static TemporalFilterSettings defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new TemporalFilterSettings
|
|||
|
{
|
|||
|
enabled = false,
|
|||
|
varianceClipping = VarianceClipping._4Tap
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct BlurSettings
|
|||
|
{
|
|||
|
[Tooltip("The type of blur to use.")]
|
|||
|
[Space(6)]
|
|||
|
public BlurType type;
|
|||
|
|
|||
|
[Tooltip("This parameter controls the depth-dependent weight of the bilateral filter, to " +
|
|||
|
"avoid bleeding across edges. A zero sharpness is a pure Gaussian blur. Increasing " +
|
|||
|
"the blur sharpness removes bleeding by using lower weights for samples with large " +
|
|||
|
"depth delta from the current pixel.")]
|
|||
|
[Space(10), Range(0, 16)]
|
|||
|
public float sharpness;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static BlurSettings defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new BlurSettings
|
|||
|
{
|
|||
|
type = BlurType.Medium,
|
|||
|
sharpness = 8f
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[Serializable]
|
|||
|
public struct ColorBleedingSettings
|
|||
|
{
|
|||
|
[Space(6)]
|
|||
|
public bool enabled;
|
|||
|
|
|||
|
[Tooltip("This value allows to control the saturation of the color bleeding.")]
|
|||
|
[Space(10), Range(0, 4)]
|
|||
|
public float saturation;
|
|||
|
|
|||
|
[Tooltip("This value allows to scale the contribution of the color bleeding samples.")]
|
|||
|
[Range(0, 32)]
|
|||
|
public float albedoMultiplier;
|
|||
|
|
|||
|
[Tooltip("Use masking on emissive pixels")]
|
|||
|
[Range(0, 1)]
|
|||
|
public float brightnessMask;
|
|||
|
|
|||
|
[Tooltip("Brightness level where masking starts/ends")]
|
|||
|
[MinMaxSlider(0, 2)]
|
|||
|
public Vector2 brightnessMaskRange;
|
|||
|
|
|||
|
[SerializeField]
|
|||
|
public static ColorBleedingSettings defaults
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new ColorBleedingSettings
|
|||
|
{
|
|||
|
enabled = false,
|
|||
|
saturation = 1f,
|
|||
|
albedoMultiplier = 4f,
|
|||
|
brightnessMask = 1f,
|
|||
|
brightnessMaskRange = new Vector2(0.0f, 0.5f)
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[AttributeUsage(AttributeTargets.Field)]
|
|||
|
public class SettingsGroup : Attribute { }
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private Presets m_Presets = Presets.defaults;
|
|||
|
public Presets presets
|
|||
|
{
|
|||
|
get { return m_Presets; }
|
|||
|
set { m_Presets = value; }
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private GeneralSettings m_GeneralSettings = GeneralSettings.defaults;
|
|||
|
public GeneralSettings generalSettings
|
|||
|
{
|
|||
|
get { return m_GeneralSettings; }
|
|||
|
set { m_GeneralSettings = value; }
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private AOSettings m_AOSettings = AOSettings.defaults;
|
|||
|
public AOSettings aoSettings
|
|||
|
{
|
|||
|
get { return m_AOSettings; }
|
|||
|
set { m_AOSettings = value; }
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private TemporalFilterSettings m_TemporalFilterSettings = TemporalFilterSettings.defaults;
|
|||
|
public TemporalFilterSettings temporalFilterSettings
|
|||
|
{
|
|||
|
get { return m_TemporalFilterSettings; }
|
|||
|
set { m_TemporalFilterSettings = value; }
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private BlurSettings m_BlurSettings = BlurSettings.defaults;
|
|||
|
public BlurSettings blurSettings
|
|||
|
{
|
|||
|
get { return m_BlurSettings; }
|
|||
|
set { m_BlurSettings = value; }
|
|||
|
}
|
|||
|
|
|||
|
[SerializeField, SettingsGroup]
|
|||
|
private ColorBleedingSettings m_ColorBleedingSettings = ColorBleedingSettings.defaults;
|
|||
|
public ColorBleedingSettings colorBleedingSettings
|
|||
|
{
|
|||
|
get { return m_ColorBleedingSettings; }
|
|||
|
set { m_ColorBleedingSettings = value; }
|
|||
|
}
|
|||
|
|
|||
|
public class MinMaxSliderAttribute : PropertyAttribute
|
|||
|
{
|
|||
|
public readonly float max;
|
|||
|
public readonly float min;
|
|||
|
|
|||
|
public MinMaxSliderAttribute(float min, float max)
|
|||
|
{
|
|||
|
this.min = min;
|
|||
|
this.max = max;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public Preset GetCurrentPreset()
|
|||
|
{
|
|||
|
return m_Presets.preset;
|
|||
|
}
|
|||
|
|
|||
|
public void ApplyPreset(Preset preset)
|
|||
|
{
|
|||
|
if (preset == Preset.Custom)
|
|||
|
{
|
|||
|
m_Presets.preset = preset;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var debugMode = generalSettings.debugMode;
|
|||
|
|
|||
|
m_GeneralSettings = GeneralSettings.defaults;
|
|||
|
m_AOSettings = AOSettings.defaults;
|
|||
|
m_ColorBleedingSettings = ColorBleedingSettings.defaults;
|
|||
|
m_BlurSettings = BlurSettings.defaults;
|
|||
|
|
|||
|
SetDebugMode(debugMode);
|
|||
|
|
|||
|
switch (preset)
|
|||
|
{
|
|||
|
case Preset.FastestPerformance:
|
|||
|
SetQuality(Quality.Lowest);
|
|||
|
SetAoRadius(0.5f);
|
|||
|
SetAoMaxRadiusPixels(64.0f);
|
|||
|
SetBlurType(BlurType.ExtraWide);
|
|||
|
break;
|
|||
|
case Preset.FastPerformance:
|
|||
|
SetQuality(Quality.Low);
|
|||
|
SetAoRadius(0.5f);
|
|||
|
SetAoMaxRadiusPixels(64.0f);
|
|||
|
SetBlurType(BlurType.Wide);
|
|||
|
break;
|
|||
|
case Preset.HighQuality:
|
|||
|
SetQuality(Quality.High);
|
|||
|
SetAoRadius(1.0f);
|
|||
|
break;
|
|||
|
case Preset.HighestQuality:
|
|||
|
SetQuality(Quality.Highest);
|
|||
|
SetAoRadius(1.2f);
|
|||
|
SetAoMaxRadiusPixels(256.0f);
|
|||
|
SetBlurType(BlurType.Narrow);
|
|||
|
break;
|
|||
|
case Preset.Normal:
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
m_Presets.preset = preset;
|
|||
|
}
|
|||
|
|
|||
|
public PipelineStage GetPipelineStage()
|
|||
|
{
|
|||
|
return m_GeneralSettings.pipelineStage;
|
|||
|
}
|
|||
|
|
|||
|
public void SetPipelineStage(PipelineStage pipelineStage)
|
|||
|
{
|
|||
|
m_GeneralSettings.pipelineStage = pipelineStage;
|
|||
|
}
|
|||
|
|
|||
|
public Quality GetQuality()
|
|||
|
{
|
|||
|
return m_GeneralSettings.quality;
|
|||
|
}
|
|||
|
|
|||
|
public void SetQuality(Quality quality)
|
|||
|
{
|
|||
|
m_GeneralSettings.quality = quality;
|
|||
|
}
|
|||
|
|
|||
|
public Deinterleaving GetDeinterleaving()
|
|||
|
{
|
|||
|
return m_GeneralSettings.deinterleaving;
|
|||
|
}
|
|||
|
|
|||
|
public void SetDeinterleaving(Deinterleaving deinterleaving)
|
|||
|
{
|
|||
|
m_GeneralSettings.deinterleaving = deinterleaving;
|
|||
|
}
|
|||
|
|
|||
|
public Resolution GetResolution()
|
|||
|
{
|
|||
|
return m_GeneralSettings.resolution;
|
|||
|
}
|
|||
|
|
|||
|
public void SetResolution(Resolution resolution)
|
|||
|
{
|
|||
|
m_GeneralSettings.resolution = resolution;
|
|||
|
}
|
|||
|
|
|||
|
public NoiseType GetNoiseType()
|
|||
|
{
|
|||
|
return m_GeneralSettings.noiseType;
|
|||
|
}
|
|||
|
|
|||
|
public void SetNoiseType(NoiseType noiseType)
|
|||
|
{
|
|||
|
m_GeneralSettings.noiseType = noiseType;
|
|||
|
}
|
|||
|
|
|||
|
public DebugMode GetDebugMode()
|
|||
|
{
|
|||
|
return m_GeneralSettings.debugMode;
|
|||
|
}
|
|||
|
|
|||
|
public void SetDebugMode(DebugMode debugMode)
|
|||
|
{
|
|||
|
m_GeneralSettings.debugMode = debugMode;
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoRadius()
|
|||
|
{
|
|||
|
return m_AOSettings.radius;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoRadius(float radius)
|
|||
|
{
|
|||
|
m_AOSettings.radius = Mathf.Clamp(radius, 0.25f, 5);
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoMaxRadiusPixels()
|
|||
|
{
|
|||
|
return m_AOSettings.maxRadiusPixels;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoMaxRadiusPixels(float maxRadiusPixels)
|
|||
|
{
|
|||
|
m_AOSettings.maxRadiusPixels = Mathf.Clamp(maxRadiusPixels, 16, 256);
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoBias()
|
|||
|
{
|
|||
|
return m_AOSettings.bias;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoBias(float bias)
|
|||
|
{
|
|||
|
m_AOSettings.bias = Mathf.Clamp(bias, 0, 0.5f);
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoOffscreenSamplesContribution()
|
|||
|
{
|
|||
|
return m_AOSettings.offscreenSamplesContribution;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoOffscreenSamplesContribution(float contribution)
|
|||
|
{
|
|||
|
m_AOSettings.offscreenSamplesContribution = Mathf.Clamp01(contribution);
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoMaxDistance()
|
|||
|
{
|
|||
|
return m_AOSettings.maxDistance;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoMaxDistance(float maxDistance)
|
|||
|
{
|
|||
|
m_AOSettings.maxDistance = maxDistance;
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoDistanceFalloff()
|
|||
|
{
|
|||
|
return m_AOSettings.distanceFalloff;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoDistanceFalloff(float distanceFalloff)
|
|||
|
{
|
|||
|
m_AOSettings.distanceFalloff = distanceFalloff;
|
|||
|
}
|
|||
|
|
|||
|
public PerPixelNormals GetAoPerPixelNormals()
|
|||
|
{
|
|||
|
return m_AOSettings.perPixelNormals;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoPerPixelNormals(PerPixelNormals perPixelNormals)
|
|||
|
{
|
|||
|
m_AOSettings.perPixelNormals = perPixelNormals;
|
|||
|
}
|
|||
|
|
|||
|
public Color GetAoColor()
|
|||
|
{
|
|||
|
return m_AOSettings.baseColor;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoColor(Color color)
|
|||
|
{
|
|||
|
m_AOSettings.baseColor = color;
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoIntensity()
|
|||
|
{
|
|||
|
return m_AOSettings.intensity;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoIntensity(float intensity)
|
|||
|
{
|
|||
|
m_AOSettings.intensity = Mathf.Clamp(intensity, 0, 4);
|
|||
|
}
|
|||
|
|
|||
|
public bool UseMultiBounce()
|
|||
|
{
|
|||
|
return m_AOSettings.useMultiBounce;
|
|||
|
}
|
|||
|
|
|||
|
public void EnableMultiBounce(bool enabled = true)
|
|||
|
{
|
|||
|
m_AOSettings.useMultiBounce = enabled;
|
|||
|
}
|
|||
|
|
|||
|
public float GetAoMultiBounceInfluence()
|
|||
|
{
|
|||
|
return m_AOSettings.multiBounceInfluence;
|
|||
|
}
|
|||
|
|
|||
|
public void SetAoMultiBounceInfluence(float multiBounceInfluence)
|
|||
|
{
|
|||
|
m_AOSettings.multiBounceInfluence = Mathf.Clamp01(multiBounceInfluence);
|
|||
|
}
|
|||
|
|
|||
|
public bool IsTemporalFilterEnabled()
|
|||
|
{
|
|||
|
return m_TemporalFilterSettings.enabled;
|
|||
|
}
|
|||
|
|
|||
|
public void EnableTemporalFilter(bool enabled = true)
|
|||
|
{
|
|||
|
m_TemporalFilterSettings.enabled = enabled;
|
|||
|
}
|
|||
|
|
|||
|
public VarianceClipping GetTemporalFilterVarianceClipping()
|
|||
|
{
|
|||
|
return m_TemporalFilterSettings.varianceClipping;
|
|||
|
}
|
|||
|
|
|||
|
public void SetTemporalFilterVarianceClipping(VarianceClipping varianceClipping)
|
|||
|
{
|
|||
|
m_TemporalFilterSettings.varianceClipping = varianceClipping;
|
|||
|
}
|
|||
|
|
|||
|
public BlurType GetBlurType()
|
|||
|
{
|
|||
|
return m_BlurSettings.type;
|
|||
|
}
|
|||
|
|
|||
|
public void SetBlurType(BlurType blurType)
|
|||
|
{
|
|||
|
m_BlurSettings.type = blurType;
|
|||
|
}
|
|||
|
|
|||
|
public float GetBlurSharpness()
|
|||
|
{
|
|||
|
return m_BlurSettings.sharpness;
|
|||
|
}
|
|||
|
|
|||
|
public void SetBlurSharpness(float sharpness)
|
|||
|
{
|
|||
|
m_BlurSettings.sharpness = Mathf.Clamp(sharpness, 0, 16);
|
|||
|
}
|
|||
|
|
|||
|
public bool IsColorBleedingEnabled()
|
|||
|
{
|
|||
|
return m_ColorBleedingSettings.enabled;
|
|||
|
}
|
|||
|
|
|||
|
public void EnableColorBleeding(bool enabled = true)
|
|||
|
{
|
|||
|
m_ColorBleedingSettings.enabled = enabled;
|
|||
|
}
|
|||
|
|
|||
|
public float GetColorBleedingSaturation()
|
|||
|
{
|
|||
|
return m_ColorBleedingSettings.saturation;
|
|||
|
}
|
|||
|
|
|||
|
public void SetColorBleedingSaturation(float saturation)
|
|||
|
{
|
|||
|
m_ColorBleedingSettings.saturation = Mathf.Clamp(saturation, 0, 4);
|
|||
|
}
|
|||
|
|
|||
|
public float GetColorBleedingAlbedoMultiplier()
|
|||
|
{
|
|||
|
return m_ColorBleedingSettings.albedoMultiplier;
|
|||
|
}
|
|||
|
|
|||
|
public void SetColorBleedingAlbedoMultiplier(float albedoMultiplier)
|
|||
|
{
|
|||
|
m_ColorBleedingSettings.albedoMultiplier = Mathf.Clamp(albedoMultiplier, 0, 32);
|
|||
|
}
|
|||
|
|
|||
|
public float GetColorBleedingBrightnessMask()
|
|||
|
{
|
|||
|
return m_ColorBleedingSettings.brightnessMask;
|
|||
|
}
|
|||
|
|
|||
|
public void SetColorBleedingBrightnessMask(float brightnessMask)
|
|||
|
{
|
|||
|
m_ColorBleedingSettings.brightnessMask = Mathf.Clamp01(brightnessMask);
|
|||
|
}
|
|||
|
|
|||
|
public Vector2 GetColorBleedingBrightnessMaskRange()
|
|||
|
{
|
|||
|
return m_ColorBleedingSettings.brightnessMaskRange;
|
|||
|
}
|
|||
|
|
|||
|
public void SetColorBleedingBrightnessMaskRange(Vector2 brightnessMaskRange)
|
|||
|
{
|
|||
|
brightnessMaskRange.x = Mathf.Clamp(brightnessMaskRange.x, 0, 2);
|
|||
|
brightnessMaskRange.y = Mathf.Clamp(brightnessMaskRange.y, 0, 2);
|
|||
|
brightnessMaskRange.x = Mathf.Min(brightnessMaskRange.x, brightnessMaskRange.y);
|
|||
|
m_ColorBleedingSettings.brightnessMaskRange = brightnessMaskRange;
|
|||
|
}
|
|||
|
|
|||
|
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 Composite_AfterLighting = 10;
|
|||
|
public const int Composite_BeforeReflections = 11;
|
|||
|
public const int Composite_BlendAO = 12;
|
|||
|
public const int Composite_BlendCB = 13;
|
|||
|
|
|||
|
public const int Debug_ViewNormals = 14;
|
|||
|
}
|
|||
|
|
|||
|
private static class ShaderProperties
|
|||
|
{
|
|||
|
public static int mainTex;
|
|||
|
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[] 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;
|
|||
|
|
|||
|
static ShaderProperties()
|
|||
|
{
|
|||
|
mainTex = Shader.PropertyToID("_MainTex");
|
|||
|
hbaoTex = Shader.PropertyToID("_HBAOTex");
|
|||
|
tempTex = Shader.PropertyToID("_TempTex");
|
|||
|
tempTex2 = Shader.PropertyToID("_TempTex2");
|
|||
|
noiseTex = Shader.PropertyToID("_NoiseTex");
|
|||
|
depthTex = Shader.PropertyToID("_DepthTex");
|
|||
|
normalsTex = Shader.PropertyToID("_NormalsTex");
|
|||
|
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");
|
|||
|
}
|
|||
|
|
|||
|
public static string GetOrthographicOrDeferredKeyword(bool orthographic, GeneralSettings settings)
|
|||
|
{
|
|||
|
// need to check that integrationStage is not BeforeImageEffectOpaque as Gbuffer0 is not available in this case
|
|||
|
return orthographic ? "ORTHOGRAPHIC_PROJECTION" : settings.pipelineStage != PipelineStage.BeforeImageEffectsOpaque ? "DEFERRED_SHADING" : "__";
|
|||
|
}
|
|||
|
|
|||
|
public static string GetQualityKeyword(GeneralSettings settings)
|
|||
|
{
|
|||
|
switch (settings.quality)
|
|||
|
{
|
|||
|
case Quality.Lowest:
|
|||
|
return "QUALITY_LOWEST";
|
|||
|
case Quality.Low:
|
|||
|
return "QUALITY_LOW";
|
|||
|
case Quality.Medium:
|
|||
|
return "QUALITY_MEDIUM";
|
|||
|
case Quality.High:
|
|||
|
return "QUALITY_HIGH";
|
|||
|
case Quality.Highest:
|
|||
|
return "QUALITY_HIGHEST";
|
|||
|
default:
|
|||
|
return "QUALITY_MEDIUM";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetNoiseKeyword(GeneralSettings settings)
|
|||
|
{
|
|||
|
switch (settings.noiseType)
|
|||
|
{
|
|||
|
case NoiseType.InterleavedGradientNoise:
|
|||
|
return "INTERLEAVED_GRADIENT_NOISE";
|
|||
|
case NoiseType.Dither:
|
|||
|
case NoiseType.SpatialDistribution:
|
|||
|
default:
|
|||
|
return "__";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetDeinterleavingKeyword(GeneralSettings settings)
|
|||
|
{
|
|||
|
switch (settings.deinterleaving)
|
|||
|
{
|
|||
|
case Deinterleaving.x4:
|
|||
|
return "DEINTERLEAVED";
|
|||
|
case Deinterleaving.Disabled:
|
|||
|
default:
|
|||
|
return "__";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetDebugKeyword(GeneralSettings settings)
|
|||
|
{
|
|||
|
switch (settings.debugMode)
|
|||
|
{
|
|||
|
case DebugMode.AOOnly:
|
|||
|
return "DEBUG_AO";
|
|||
|
case DebugMode.ColorBleedingOnly:
|
|||
|
return "DEBUG_COLORBLEEDING";
|
|||
|
case DebugMode.SplitWithoutAOAndWithAO:
|
|||
|
return "DEBUG_NOAO_AO";
|
|||
|
case DebugMode.SplitWithAOAndAOOnly:
|
|||
|
return "DEBUG_AO_AOONLY";
|
|||
|
case DebugMode.SplitWithoutAOAndAOOnly:
|
|||
|
return "DEBUG_NOAO_AOONLY";
|
|||
|
case DebugMode.Disabled:
|
|||
|
default:
|
|||
|
return "__";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetMultibounceKeyword(AOSettings settings)
|
|||
|
{
|
|||
|
return settings.useMultiBounce ? "MULTIBOUNCE" : "__";
|
|||
|
}
|
|||
|
|
|||
|
public static string GetOffscreenSamplesContributionKeyword(AOSettings settings)
|
|||
|
{
|
|||
|
return settings.offscreenSamplesContribution > 0 ? "OFFSCREEN_SAMPLES_CONTRIBUTION" : "__";
|
|||
|
}
|
|||
|
|
|||
|
public static string GetPerPixelNormalsKeyword(AOSettings settings)
|
|||
|
{
|
|||
|
switch (settings.perPixelNormals)
|
|||
|
{
|
|||
|
case PerPixelNormals.Camera:
|
|||
|
return "NORMALS_CAMERA";
|
|||
|
case PerPixelNormals.Reconstruct:
|
|||
|
return "NORMALS_RECONSTRUCT";
|
|||
|
case PerPixelNormals.GBuffer:
|
|||
|
default:
|
|||
|
return "__";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetBlurRadiusKeyword(BlurSettings settings)
|
|||
|
{
|
|||
|
switch (settings.type)
|
|||
|
{
|
|||
|
case BlurType.Narrow:
|
|||
|
return "BLUR_RADIUS_2";
|
|||
|
case BlurType.Medium:
|
|||
|
return "BLUR_RADIUS_3";
|
|||
|
case BlurType.Wide:
|
|||
|
return "BLUR_RADIUS_4";
|
|||
|
case BlurType.ExtraWide:
|
|||
|
return "BLUR_RADIUS_5";
|
|||
|
case BlurType.None:
|
|||
|
default:
|
|||
|
return "BLUR_RADIUS_3";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetVarianceClippingKeyword(TemporalFilterSettings settings)
|
|||
|
{
|
|||
|
switch (settings.varianceClipping)
|
|||
|
{
|
|||
|
case VarianceClipping._4Tap:
|
|||
|
return "VARIANCE_CLIPPING_4TAP";
|
|||
|
case VarianceClipping._8Tap:
|
|||
|
return "VARIANCE_CLIPPING_8TAP";
|
|||
|
case VarianceClipping.Disabled:
|
|||
|
default:
|
|||
|
return "__";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string GetColorBleedingKeyword(ColorBleedingSettings settings)
|
|||
|
{
|
|||
|
return settings.enabled ? "COLOR_BLEEDING" : "__";
|
|||
|
}
|
|||
|
|
|||
|
public static string GetLightingLogEncodedKeyword(bool hdr)
|
|||
|
{
|
|||
|
return hdr ? "__" : "LIGHTING_LOG_ENCODED";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public enum StereoRenderingMode
|
|||
|
{
|
|||
|
MultiPass,
|
|||
|
SinglePassInstanced
|
|||
|
};
|
|||
|
|
|||
|
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 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 Camera hbaoCamera { get; set; }
|
|||
|
private CommandBuffer cmdBuffer { get; set; }
|
|||
|
private int width { get; set; }
|
|||
|
private int height { get; set; }
|
|||
|
private bool stereoActive { get; set; }
|
|||
|
private int xrActiveEye { get; set; }
|
|||
|
private StereoRenderingMode stereoRenderingMode { get; set; }
|
|||
|
private int screenWidth { get; set; }
|
|||
|
private int screenHeight { get; set; }
|
|||
|
private int aoWidth { get; set; }
|
|||
|
private int aoHeight { get; set; }
|
|||
|
private int reinterleavedAoWidth { get; set; }
|
|||
|
private int reinterleavedAoHeight { get; set; }
|
|||
|
private int deinterleavedAoWidth { get; set; }
|
|||
|
private int deinterleavedAoHeight { get; set; }
|
|||
|
private int frameCount { get; set; }
|
|||
|
private bool motionVectorsSupported { get; set; }
|
|||
|
private RenderTexture aoHistoryBuffer { get; set; }
|
|||
|
private RenderTexture colorBleedingHistoryBuffer { get; set; }
|
|||
|
private Texture2D noiseTex { get; set; }
|
|||
|
|
|||
|
private Mesh fullscreenTriangle
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (m_FullscreenTriangle != null)
|
|||
|
return m_FullscreenTriangle;
|
|||
|
|
|||
|
m_FullscreenTriangle = new Mesh { name = "Fullscreen Triangle" };
|
|||
|
|
|||
|
// Because we have to support older platforms (GLES2/3, DX9 etc) we can't do all of
|
|||
|
// this directly in the vertex shader using vertex ids :(
|
|||
|
m_FullscreenTriangle.SetVertices(new List<Vector3>
|
|||
|
{
|
|||
|
new Vector3(-1f, -1f, 0f),
|
|||
|
new Vector3(-1f, 3f, 0f),
|
|||
|
new Vector3( 3f, -1f, 0f)
|
|||
|
});
|
|||
|
m_FullscreenTriangle.SetIndices(new[] { 0, 1, 2 }, MeshTopology.Triangles, 0, false);
|
|||
|
m_FullscreenTriangle.UploadMeshData(false);
|
|||
|
|
|||
|
return m_FullscreenTriangle;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private CameraEvent cameraEvent
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
// Forces BeforeImageEffectsOpaque as soon as normal display mode isn't used,
|
|||
|
// the component still display its integration stage but we force it here to ensure
|
|||
|
// all debug modes display correctly.
|
|||
|
if (generalSettings.debugMode != DebugMode.Disabled)
|
|||
|
return CameraEvent.BeforeImageEffectsOpaque;
|
|||
|
|
|||
|
switch (generalSettings.pipelineStage)
|
|||
|
{
|
|||
|
case PipelineStage.BeforeReflections:
|
|||
|
return CameraEvent.BeforeReflections;
|
|||
|
case PipelineStage.AfterLighting:
|
|||
|
return CameraEvent.AfterLighting;
|
|||
|
case PipelineStage.BeforeImageEffectsOpaque:
|
|||
|
default:
|
|||
|
return CameraEvent.BeforeImageEffectsOpaque;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool isCommandBufferDirty
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (m_IsCommandBufferDirty || m_PreviousPipelineStage != generalSettings.pipelineStage || m_PreviousResolution != generalSettings.resolution ||
|
|||
|
m_PreviousDebugMode != generalSettings.debugMode || m_PreviousAllowHDR != hbaoCamera.allowHDR || m_PreviousWidth != width || m_PreviousHeight != height ||
|
|||
|
m_PreviousDeinterleaving != generalSettings.deinterleaving || m_PreviousBlurAmount != blurSettings.type || m_PreviousUseMultibounce != aoSettings.useMultiBounce ||
|
|||
|
m_PreviousColorBleedingEnabled != colorBleedingSettings.enabled || m_PreviousTemporalFilterEnabled != temporalFilterSettings.enabled ||
|
|||
|
m_PreviousRenderingPath != hbaoCamera.actualRenderingPath)
|
|||
|
{
|
|||
|
m_PreviousPipelineStage = generalSettings.pipelineStage;
|
|||
|
m_PreviousResolution = generalSettings.resolution;
|
|||
|
m_PreviousDebugMode = generalSettings.debugMode;
|
|||
|
m_PreviousAllowHDR = hbaoCamera.allowHDR;
|
|||
|
m_PreviousWidth = width;
|
|||
|
m_PreviousHeight = height;
|
|||
|
m_PreviousDeinterleaving = generalSettings.deinterleaving;
|
|||
|
m_PreviousBlurAmount = blurSettings.type;
|
|||
|
m_PreviousUseMultibounce = aoSettings.useMultiBounce;
|
|||
|
m_PreviousColorBleedingEnabled = colorBleedingSettings.enabled;
|
|||
|
m_PreviousTemporalFilterEnabled = temporalFilterSettings.enabled;
|
|||
|
m_PreviousRenderingPath = hbaoCamera.actualRenderingPath;
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
m_IsCommandBufferDirty = value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool isHistoryBufferDirty
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (aoHistoryBuffer == null || (colorBleedingSettings.enabled && colorBleedingHistoryBuffer == null) ||
|
|||
|
m_PreviousTemporalFilterEnabled != temporalFilterSettings.enabled ||
|
|||
|
m_PreviousResolution != generalSettings.resolution ||
|
|||
|
m_PreviousColorBleedingEnabled != colorBleedingSettings.enabled ||
|
|||
|
m_PrevStereoRenderingMode != stereoRenderingMode)
|
|||
|
{
|
|||
|
m_PreviousTemporalFilterEnabled = temporalFilterSettings.enabled;
|
|||
|
m_PreviousResolution = generalSettings.resolution;
|
|||
|
m_PreviousColorBleedingEnabled = colorBleedingSettings.enabled;
|
|||
|
m_PrevStereoRenderingMode = stereoRenderingMode;
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static RenderTextureFormat defaultHDRRenderTextureFormat
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
#if UNITY_ANDROID || UNITY_IPHONE || UNITY_TVOS || UNITY_SWITCH || UNITY_EDITOR
|
|||
|
RenderTextureFormat format = RenderTextureFormat.RGB111110Float;
|
|||
|
#if UNITY_EDITOR
|
|||
|
var target = EditorUserBuildSettings.activeBuildTarget;
|
|||
|
if (target != BuildTarget.Android && target != BuildTarget.iOS && target != BuildTarget.tvOS && target != BuildTarget.Switch)
|
|||
|
return RenderTextureFormat.DefaultHDR;
|
|||
|
#endif // UNITY_EDITOR
|
|||
|
if (SystemInfo.SupportsRenderTextureFormat(format))
|
|||
|
return format;
|
|||
|
#endif // UNITY_ANDROID || UNITY_IPHONE || UNITY_TVOS || UNITY_SWITCH || UNITY_EDITOR
|
|||
|
return RenderTextureFormat.DefaultHDR;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private RenderTextureFormat sourceFormat { get { return hbaoCamera.allowHDR ? defaultHDRRenderTextureFormat : RenderTextureFormat.Default; } }
|
|||
|
//private static RenderTextureFormat colorFormat { get { return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB64) ? RenderTextureFormat.ARGB64 : RenderTextureFormat.ARGB32; } }
|
|||
|
private static RenderTextureFormat colorFormat { get { return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default; } }
|
|||
|
private static RenderTextureFormat depthFormat { get { return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RFloat) ? RenderTextureFormat.RFloat : RenderTextureFormat.RHalf; } }
|
|||
|
private static RenderTextureFormat normalsFormat { get { return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB2101010) ? RenderTextureFormat.ARGB2101010 : RenderTextureFormat.Default; } }
|
|||
|
private static bool isLinearColorSpace { get { return QualitySettings.activeColorSpace == ColorSpace.Linear; } }
|
|||
|
private bool renderingInSceneView { get { return hbaoCamera.cameraType == CameraType.SceneView; } }
|
|||
|
|
|||
|
private RenderTextureDescriptor m_sourceDescriptor;
|
|||
|
private string[] m_ShaderKeywords;
|
|||
|
private Vector4[] m_UVToViewPerEye = new Vector4[2];
|
|||
|
private float[] m_RadiusPerEye = new float[2];
|
|||
|
private bool m_IsCommandBufferDirty;
|
|||
|
private Mesh m_FullscreenTriangle;
|
|||
|
private PipelineStage? m_PreviousPipelineStage;
|
|||
|
private Resolution? m_PreviousResolution;
|
|||
|
private Deinterleaving? m_PreviousDeinterleaving;
|
|||
|
private DebugMode? m_PreviousDebugMode;
|
|||
|
private NoiseType? m_PreviousNoiseType;
|
|||
|
private BlurType? m_PreviousBlurAmount;
|
|||
|
private int m_PreviousWidth;
|
|||
|
private int m_PreviousHeight;
|
|||
|
private bool m_PreviousAllowHDR;
|
|||
|
private bool m_PreviousUseMultibounce;
|
|||
|
private bool m_PreviousColorBleedingEnabled;
|
|||
|
private bool m_PreviousTemporalFilterEnabled;
|
|||
|
private RenderingPath m_PreviousRenderingPath;
|
|||
|
private StereoRenderingMode m_PrevStereoRenderingMode;
|
|||
|
|
|||
|
|
|||
|
void OnEnable()
|
|||
|
{
|
|||
|
if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.Depth))
|
|||
|
{
|
|||
|
Debug.LogWarning("HBAO shader is not supported on this platform.");
|
|||
|
this.enabled = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (hbaoShader == null) hbaoShader = Shader.Find("Hidden/HBAO");
|
|||
|
if (hbaoShader == null)
|
|||
|
{
|
|||
|
Debug.LogError("HBAO shader was not found...");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!hbaoShader.isSupported)
|
|||
|
{
|
|||
|
Debug.LogWarning("HBAO shader is not supported on this platform.");
|
|||
|
this.enabled = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Initialize();
|
|||
|
}
|
|||
|
|
|||
|
void OnDisable()
|
|||
|
{
|
|||
|
ClearCommandBuffer(cmdBuffer);
|
|||
|
|
|||
|
ReleaseHistoryBuffers();
|
|||
|
|
|||
|
if (material != null)
|
|||
|
DestroyImmediate(material);
|
|||
|
if (noiseTex != null)
|
|||
|
DestroyImmediate(noiseTex);
|
|||
|
if (fullscreenTriangle != null)
|
|||
|
DestroyImmediate(fullscreenTriangle);
|
|||
|
}
|
|||
|
|
|||
|
void OnPreRender()
|
|||
|
{
|
|||
|
if (hbaoShader == null || hbaoCamera == null) return;
|
|||
|
|
|||
|
FetchRenderParameters();
|
|||
|
CheckParameters();
|
|||
|
UpdateMaterialProperties();
|
|||
|
UpdateShaderKeywords();
|
|||
|
|
|||
|
if (isCommandBufferDirty)
|
|||
|
{
|
|||
|
ClearCommandBuffer(cmdBuffer);
|
|||
|
BuildCommandBuffer(cmdBuffer, cameraEvent);
|
|||
|
hbaoCamera.AddCommandBuffer(cameraEvent, cmdBuffer);
|
|||
|
isCommandBufferDirty = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void OnPostRender()
|
|||
|
{
|
|||
|
frameCount++;
|
|||
|
}
|
|||
|
|
|||
|
void OnValidate()
|
|||
|
{
|
|||
|
if (hbaoShader == null || hbaoCamera == null) return;
|
|||
|
|
|||
|
CheckParameters();
|
|||
|
}
|
|||
|
|
|||
|
private void Initialize()
|
|||
|
{
|
|||
|
m_sourceDescriptor = new RenderTextureDescriptor(0, 0);
|
|||
|
|
|||
|
hbaoCamera = GetComponent<Camera>();
|
|||
|
hbaoCamera.forceIntoRenderTexture = true;
|
|||
|
|
|||
|
material = new Material(hbaoShader);
|
|||
|
material.hideFlags = HideFlags.HideAndDontSave;
|
|||
|
|
|||
|
// For platforms not supporting motion vectors texture
|
|||
|
// https://docs.unity3d.com/ScriptReference/DepthTextureMode.MotionVectors.html
|
|||
|
motionVectorsSupported = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf);
|
|||
|
|
|||
|
cmdBuffer = new CommandBuffer { name = "HBAO" };
|
|||
|
isCommandBufferDirty = true;
|
|||
|
}
|
|||
|
|
|||
|
private void FetchRenderParameters()
|
|||
|
{
|
|||
|
#if !UNITY_SWITCH && ENABLE_VR_MODULE && ENABLE_VR
|
|||
|
if (hbaoCamera.stereoEnabled)
|
|||
|
{
|
|||
|
var xrDesc = XRSettings.eyeTextureDesc;
|
|||
|
stereoRenderingMode = StereoRenderingMode.MultiPass;
|
|||
|
|
|||
|
#if UNITY_STANDALONE || UNITY_EDITOR || UNITY_PS4 || UNITY_PS5 || UNITY_ANDROID
|
|||
|
if (xrDesc.dimension == TextureDimension.Tex2DArray)
|
|||
|
stereoRenderingMode = StereoRenderingMode.SinglePassInstanced;
|
|||
|
#endif
|
|||
|
|
|||
|
width = xrDesc.width;
|
|||
|
height = xrDesc.height;
|
|||
|
m_sourceDescriptor = xrDesc;
|
|||
|
xrActiveEye = (int)hbaoCamera.stereoActiveEye;
|
|||
|
screenWidth = XRSettings.eyeTextureWidth;
|
|||
|
screenHeight = XRSettings.eyeTextureHeight;
|
|||
|
stereoActive = true;
|
|||
|
}
|
|||
|
else
|
|||
|
#endif
|
|||
|
{
|
|||
|
width = hbaoCamera.pixelWidth;
|
|||
|
height = hbaoCamera.pixelHeight;
|
|||
|
m_sourceDescriptor.width = width;
|
|||
|
m_sourceDescriptor.height = height;
|
|||
|
xrActiveEye = 0;
|
|||
|
screenWidth = width;
|
|||
|
screenHeight = height;
|
|||
|
stereoActive = false;
|
|||
|
}
|
|||
|
|
|||
|
var downsamplingFactor = generalSettings.resolution == Resolution.Full ? 1 : generalSettings.deinterleaving == Deinterleaving.Disabled ? 2 : 1;
|
|||
|
if (downsamplingFactor > 1)
|
|||
|
{
|
|||
|
aoWidth = (width + width % 2) / downsamplingFactor;
|
|||
|
aoHeight = (height + height % 2) / downsamplingFactor;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
aoWidth = width;
|
|||
|
aoHeight = height;
|
|||
|
}
|
|||
|
|
|||
|
reinterleavedAoWidth = width + (width % 4 == 0 ? 0 : 4 - (width % 4));
|
|||
|
reinterleavedAoHeight = height + (height % 4 == 0 ? 0 : 4 - (height % 4));
|
|||
|
deinterleavedAoWidth = reinterleavedAoWidth / 4;
|
|||
|
deinterleavedAoHeight = reinterleavedAoHeight / 4;
|
|||
|
}
|
|||
|
|
|||
|
private void AllocateHistoryBuffers()
|
|||
|
{
|
|||
|
ReleaseHistoryBuffers();
|
|||
|
|
|||
|
aoHistoryBuffer = GetScreenSpaceRT(widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
if (colorBleedingSettings.enabled)
|
|||
|
colorBleedingHistoryBuffer = GetScreenSpaceRT(widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
|
|||
|
// Clear history buffers to default
|
|||
|
var lastActive = RenderTexture.active;
|
|||
|
RenderTexture.active = aoHistoryBuffer;
|
|||
|
GL.Clear(false, true, Color.white);
|
|||
|
if (colorBleedingSettings.enabled)
|
|||
|
{
|
|||
|
RenderTexture.active = colorBleedingHistoryBuffer;
|
|||
|
GL.Clear(false, true, new Color(0, 0, 0, 1));
|
|||
|
}
|
|||
|
RenderTexture.active = lastActive;
|
|||
|
|
|||
|
frameCount = 0;
|
|||
|
}
|
|||
|
|
|||
|
private void ReleaseHistoryBuffers()
|
|||
|
{
|
|||
|
if (aoHistoryBuffer != null)
|
|||
|
aoHistoryBuffer.Release();
|
|||
|
|
|||
|
if (colorBleedingHistoryBuffer != null)
|
|||
|
colorBleedingHistoryBuffer.Release();
|
|||
|
}
|
|||
|
|
|||
|
private void ClearCommandBuffer(CommandBuffer cmd)
|
|||
|
{
|
|||
|
if (cmd != null)
|
|||
|
{
|
|||
|
if (hbaoCamera != null)
|
|||
|
{
|
|||
|
hbaoCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, cmd);
|
|||
|
hbaoCamera.RemoveCommandBuffer(CameraEvent.AfterLighting, cmd);
|
|||
|
hbaoCamera.RemoveCommandBuffer(CameraEvent.BeforeReflections, cmd);
|
|||
|
}
|
|||
|
cmd.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BuildCommandBuffer(CommandBuffer cmd, CameraEvent cameraEvent)
|
|||
|
{
|
|||
|
// AO
|
|||
|
if (generalSettings.deinterleaving == Deinterleaving.Disabled)
|
|||
|
{
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.hbaoTex, widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
AO(cmd);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.hbaoTex, widthOverride: reinterleavedAoWidth, heightOverride: reinterleavedAoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
DeinterleavedAO(cmd);
|
|||
|
}
|
|||
|
|
|||
|
// Blur
|
|||
|
Blur(cmd);
|
|||
|
|
|||
|
// Temporal Filter
|
|||
|
TemporalFilter(cmd);
|
|||
|
|
|||
|
// Composite
|
|||
|
Composite(cmd, cameraEvent);
|
|||
|
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.hbaoTex);
|
|||
|
|
|||
|
//Debug.Log("CommandBuffer has been rebuilt");
|
|||
|
}
|
|||
|
|
|||
|
private void AO(CommandBuffer cmd)
|
|||
|
{
|
|||
|
BlitFullscreenTriangleWithClear(cmd, BuiltinRenderTextureType.CameraTarget, ShaderProperties.hbaoTex, material, new Color(0, 0, 0, 1), Pass.AO);
|
|||
|
}
|
|||
|
|
|||
|
private void DeinterleavedAO(CommandBuffer cmd)
|
|||
|
{
|
|||
|
// Deinterleave depth & normals (4x4)
|
|||
|
for (int i = 0; i < 4; i++)
|
|||
|
{
|
|||
|
var rtsDepth = new RenderTargetIdentifier[] {
|
|||
|
ShaderProperties.depthSliceTex[(i << 2) + 0],
|
|||
|
ShaderProperties.depthSliceTex[(i << 2) + 1],
|
|||
|
ShaderProperties.depthSliceTex[(i << 2) + 2],
|
|||
|
ShaderProperties.depthSliceTex[(i << 2) + 3]
|
|||
|
};
|
|||
|
var rtsNormals = new RenderTargetIdentifier[] {
|
|||
|
ShaderProperties.normalsSliceTex[(i << 2) + 0],
|
|||
|
ShaderProperties.normalsSliceTex[(i << 2) + 1],
|
|||
|
ShaderProperties.normalsSliceTex[(i << 2) + 2],
|
|||
|
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++)
|
|||
|
{
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.depthSliceTex[j + 4 * i], widthOverride: deinterleavedAoWidth, heightOverride: deinterleavedAoHeight, colorFormat: depthFormat, readWrite: RenderTextureReadWrite.Linear, filter: FilterMode.Point);
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.normalsSliceTex[j + 4 * i], widthOverride: deinterleavedAoWidth, heightOverride: deinterleavedAoHeight, colorFormat: normalsFormat, readWrite: RenderTextureReadWrite.Linear, filter: FilterMode.Point);
|
|||
|
}
|
|||
|
BlitFullscreenTriangle(cmd, BuiltinRenderTextureType.CameraTarget, rtsDepth, material, Pass.Deinterleave_Depth); // outputs 4 render textures
|
|||
|
BlitFullscreenTriangle(cmd, BuiltinRenderTextureType.CameraTarget, rtsNormals, material, Pass.Deinterleave_Normals); // outputs 4 render textures
|
|||
|
}
|
|||
|
|
|||
|
// 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]);
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.aoSliceTex[i], widthOverride: deinterleavedAoWidth, heightOverride: deinterleavedAoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear, filter: FilterMode.Point);
|
|||
|
BlitFullscreenTriangleWithClear(cmd, BuiltinRenderTextureType.CameraTarget, ShaderProperties.aoSliceTex[i], material, new Color(0, 0, 0, 1), Pass.AO_Deinterleaved); // ao
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.depthSliceTex[i]);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.normalsSliceTex[i]);
|
|||
|
}
|
|||
|
|
|||
|
// Atlas Deinterleaved AO, 4x4
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, widthOverride: reinterleavedAoWidth, heightOverride: reinterleavedAoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
for (int i = 0; i < 4 * 4; i++)
|
|||
|
{
|
|||
|
cmd.SetGlobalVector(ShaderProperties.atlasOffset, new Vector2(((i & 1) + (((i & 7) >> 2) << 1)) * deinterleavedAoWidth, (((i & 3) >> 1) + ((i >> 3) << 1)) * deinterleavedAoHeight));
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.aoSliceTex[i], ShaderProperties.tempTex, material, Pass.Atlas_AO_Deinterleaved); // atlassing
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.aoSliceTex[i]);
|
|||
|
}
|
|||
|
|
|||
|
// Reinterleave AO
|
|||
|
ApplyFlip(cmd);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex, ShaderProperties.hbaoTex, material, Pass.Reinterleave_AO); // reinterleave
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
}
|
|||
|
|
|||
|
private void Blur(CommandBuffer cmd)
|
|||
|
{
|
|||
|
if (blurSettings.type != BlurType.None)
|
|||
|
{
|
|||
|
float width = aoWidth;
|
|||
|
float height = aoHeight;
|
|||
|
if (hbaoCamera.allowDynamicResolution)
|
|||
|
{
|
|||
|
width *= ScalableBufferManager.widthScaleFactor;
|
|||
|
height *= ScalableBufferManager.heightScaleFactor;
|
|||
|
}
|
|||
|
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
cmd.SetGlobalVector(ShaderProperties.blurDeltaUV, new Vector2(1f / width, 0));
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.hbaoTex, ShaderProperties.tempTex, material, Pass.Blur); // blur X
|
|||
|
cmd.SetGlobalVector(ShaderProperties.blurDeltaUV, new Vector2(0, 1f / height));
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex, ShaderProperties.hbaoTex, material, Pass.Blur); // blur Y
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void TemporalFilter(CommandBuffer cmd)
|
|||
|
{
|
|||
|
if (isHistoryBufferDirty && temporalFilterSettings.enabled)
|
|||
|
AllocateHistoryBuffers();
|
|||
|
|
|||
|
if (temporalFilterSettings.enabled && !renderingInSceneView)
|
|||
|
{
|
|||
|
if (colorBleedingSettings.enabled)
|
|||
|
{
|
|||
|
// 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 rts = new RenderTargetIdentifier[] {
|
|||
|
aoHistoryBuffer,
|
|||
|
colorBleedingHistoryBuffer
|
|||
|
};
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex2, widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
BlitFullscreenTriangle(cmd, aoHistoryBuffer, ShaderProperties.tempTex2, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, colorBleedingHistoryBuffer, ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex2, rts, material, Pass.Temporal_Filter);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex2);
|
|||
|
cmd.SetGlobalTexture(ShaderProperties.hbaoTex, colorBleedingHistoryBuffer);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// AO history buffer contains ao in aplha channel so we can just use history as
|
|||
|
// a render texture for the composite pass.
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, widthOverride: aoWidth, heightOverride: aoHeight, colorFormat: colorFormat, readWrite: RenderTextureReadWrite.Linear);
|
|||
|
BlitFullscreenTriangle(cmd, aoHistoryBuffer, ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex, aoHistoryBuffer, material, Pass.Temporal_Filter);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
cmd.SetGlobalTexture(ShaderProperties.hbaoTex, aoHistoryBuffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void Composite(CommandBuffer cmd, CameraEvent cameraEvent)
|
|||
|
{
|
|||
|
if (generalSettings.debugMode == DebugMode.Disabled)
|
|||
|
{
|
|||
|
if (cameraEvent == CameraEvent.BeforeReflections)
|
|||
|
CompositeBeforeReflections(cmd);
|
|||
|
else if (cameraEvent == CameraEvent.AfterLighting)
|
|||
|
CompositeAfterLighting(cmd);
|
|||
|
else // if (BeforeImageEffectsOpaque)
|
|||
|
CompositeBeforeImageEffectsOpaque(cmd);
|
|||
|
}
|
|||
|
else // debug mode
|
|||
|
CompositeDebug(cmd, generalSettings.debugMode == DebugMode.ViewNormals ? Pass.Debug_ViewNormals : Pass.Composite);
|
|||
|
}
|
|||
|
|
|||
|
// Cases of BeforeReflections & AfterLighting
|
|||
|
// If using HDR there’s no separate rendertarget being created for Emission+lighting buffer (RT3);
|
|||
|
// instead the rendertarget that the Camera renders into (that is, the one that is passed to the image effects) is used as RT3.
|
|||
|
// If non-HDR GBuffer3 texture is available. HDR uses ARGBHalf, non-HDR uses ARGB2101010
|
|||
|
// Emission + lighting buffer(RT3) is logarithmically encoded to provide greater dynamic range than is usually possible with
|
|||
|
// an ARGB32 texture, when the Camera is not using HDR.
|
|||
|
// https://docs.unity3d.com/Manual/RenderTech-DeferredShading.html
|
|||
|
|
|||
|
private void CompositeBeforeReflections(CommandBuffer cmd)
|
|||
|
{
|
|||
|
var hdr = hbaoCamera.allowHDR;
|
|||
|
var rts = new RenderTargetIdentifier[] {
|
|||
|
BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
|
|||
|
hdr ? BuiltinRenderTextureType.CameraTarget : BuiltinRenderTextureType.GBuffer3 // Ambient
|
|||
|
};
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, colorFormat: RenderTextureFormat.ARGB32);
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex2, colorFormat: hdr ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB2101010);
|
|||
|
BlitFullscreenTriangle(cmd, rts[0], ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, rts[1], ShaderProperties.tempTex2, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex2, rts, material, Pass.Composite_BeforeReflections);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex2);
|
|||
|
}
|
|||
|
|
|||
|
private void CompositeAfterLighting(CommandBuffer cmd)
|
|||
|
{
|
|||
|
var hdr = hbaoCamera.allowHDR;
|
|||
|
var rt3 = hdr ? BuiltinRenderTextureType.CameraTarget : BuiltinRenderTextureType.GBuffer3;
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, colorFormat: hdr ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB2101010);
|
|||
|
BlitFullscreenTriangle(cmd, rt3, ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex, rt3, material, Pass.Composite_AfterLighting);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
}
|
|||
|
|
|||
|
private void CompositeBeforeImageEffectsOpaque(CommandBuffer cmd)
|
|||
|
{
|
|||
|
if (aoSettings.useMultiBounce)
|
|||
|
{
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, colorFormat: sourceFormat);
|
|||
|
if (stereoActive && hbaoCamera.actualRenderingPath != RenderingPath.DeferredShading)
|
|||
|
cmd.Blit(BuiltinRenderTextureType.CameraTarget, ShaderProperties.tempTex);
|
|||
|
else
|
|||
|
BlitFullscreenTriangle(cmd, BuiltinRenderTextureType.CameraTarget, ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
}
|
|||
|
|
|||
|
ApplyFlip(cmd, SystemInfo.graphicsUVStartsAtTop);
|
|||
|
BlitFullscreenTriangle(cmd, aoSettings.useMultiBounce ? (RenderTargetIdentifier)ShaderProperties.tempTex : BuiltinRenderTextureType.None, BuiltinRenderTextureType.CameraTarget, material, Pass.Composite_BlendAO);
|
|||
|
if (colorBleedingSettings.enabled)
|
|||
|
BlitFullscreenTriangle(cmd, BuiltinRenderTextureType.None, BuiltinRenderTextureType.CameraTarget, material, Pass.Composite_BlendCB);
|
|||
|
|
|||
|
if (aoSettings.useMultiBounce)
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
}
|
|||
|
|
|||
|
private void CompositeDebug(CommandBuffer cmd, int finalPassId = Pass.Composite)
|
|||
|
{
|
|||
|
GetScreenSpaceTemporaryRT(cmd, ShaderProperties.tempTex, colorFormat: sourceFormat);
|
|||
|
if (stereoActive && hbaoCamera.actualRenderingPath != RenderingPath.DeferredShading)
|
|||
|
cmd.Blit(BuiltinRenderTextureType.CameraTarget, ShaderProperties.tempTex);
|
|||
|
else
|
|||
|
BlitFullscreenTriangle(cmd, BuiltinRenderTextureType.CameraTarget, ShaderProperties.tempTex, material, Pass.Copy);
|
|||
|
ApplyFlip(cmd, SystemInfo.graphicsUVStartsAtTop);
|
|||
|
BlitFullscreenTriangle(cmd, ShaderProperties.tempTex, BuiltinRenderTextureType.CameraTarget, material, finalPassId);
|
|||
|
ReleaseTemporaryRT(cmd, ShaderProperties.tempTex);
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateMaterialProperties()
|
|||
|
{
|
|||
|
int eyeCount = stereoActive && stereoRenderingMode == StereoRenderingMode.SinglePassInstanced && !renderingInSceneView ? 2 : 1;
|
|||
|
for (int viewIndex = 0; viewIndex < eyeCount; viewIndex++)
|
|||
|
{
|
|||
|
var projMatrix = viewIndex == 0 ? hbaoCamera.projectionMatrix : hbaoCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
|
|||
|
float invTanHalfFOVxAR = projMatrix.m00; // m00 => 1.0f / (tanHalfFOV * aspectRatio)
|
|||
|
float invTanHalfFOV = projMatrix.m11; // m11 => 1.0f / tanHalfFOV
|
|||
|
m_UVToViewPerEye[viewIndex == 0 ? xrActiveEye : viewIndex] = new Vector4(2.0f / invTanHalfFOVxAR, -2.0f / invTanHalfFOV, -1.0f / invTanHalfFOVxAR, 1.0f / invTanHalfFOV);
|
|||
|
m_RadiusPerEye[viewIndex == 0 ? xrActiveEye : viewIndex] = aoSettings.radius * 0.5f * (screenHeight / (generalSettings.deinterleaving == Deinterleaving.x4 ? 4 : 1) / (2.0f / invTanHalfFOV));
|
|||
|
}
|
|||
|
|
|||
|
//float tanHalfFovY = Mathf.Tan(0.5f * hbaoCamera.fieldOfView * Mathf.Deg2Rad);
|
|||
|
//float invFocalLenX = 1.0f / (1.0f / tanHalfFovY * (screenHeight / (float)screenWidth));
|
|||
|
//float invFocalLenY = 1.0f / (1.0f / tanHalfFovY);
|
|||
|
float maxRadInPixels = Mathf.Max(16, aoSettings.maxRadiusPixels * Mathf.Sqrt((screenWidth * screenHeight) / (1080.0f * 1920.0f)));
|
|||
|
maxRadInPixels /= (generalSettings.deinterleaving == Deinterleaving.x4 ? 4 : 1);
|
|||
|
|
|||
|
var targetScale = generalSettings.deinterleaving == Deinterleaving.x4 ?
|
|||
|
new Vector4(reinterleavedAoWidth / (float)width, reinterleavedAoHeight / (float)height, 1.0f / (reinterleavedAoWidth / (float)width), 1.0f / (reinterleavedAoHeight / (float)height)) :
|
|||
|
generalSettings.resolution == Resolution.Half /*&& aoSettings.perPixelNormals == PerPixelNormals.Reconstruct*/ ?
|
|||
|
new Vector4((width + 0.5f) / width, (height + 0.5f) / height, 1f, 1f) :
|
|||
|
Vector4.one;
|
|||
|
|
|||
|
material.SetTexture(ShaderProperties.noiseTex, noiseTex);
|
|||
|
material.SetVector(ShaderProperties.inputTexelSize, new Vector4(1f / width, 1f / height, width, height));
|
|||
|
if (hbaoCamera.allowDynamicResolution)
|
|||
|
material.SetVector(ShaderProperties.aoTexelSize, new Vector4(1f / (aoWidth * ScalableBufferManager.widthScaleFactor), 1f / (aoHeight * ScalableBufferManager.heightScaleFactor), aoWidth * ScalableBufferManager.widthScaleFactor, aoHeight * ScalableBufferManager.heightScaleFactor));
|
|||
|
else
|
|||
|
material.SetVector(ShaderProperties.aoTexelSize, new Vector4(1f / aoWidth, 1f / aoHeight, aoWidth, aoHeight));
|
|||
|
material.SetVector(ShaderProperties.deinterleavedAOTexelSize, new Vector4(1.0f / deinterleavedAoWidth, 1.0f / deinterleavedAoHeight, deinterleavedAoWidth, deinterleavedAoHeight));
|
|||
|
material.SetVector(ShaderProperties.reinterleavedAOTexelSize, new Vector4(1f / reinterleavedAoWidth, 1f / reinterleavedAoHeight, reinterleavedAoWidth, reinterleavedAoHeight));
|
|||
|
material.SetVector(ShaderProperties.targetScale, targetScale);
|
|||
|
//material.SetVector(ShaderProperties.uvToView, new Vector4(2.0f * invFocalLenX, -2.0f * invFocalLenY, -1.0f * invFocalLenX, 1.0f * invFocalLenY));
|
|||
|
material.SetVectorArray(ShaderProperties.uvToView, m_UVToViewPerEye);
|
|||
|
//material.SetMatrix(ShaderProperties.worldToCameraMatrix, hbaoCamera.worldToCameraMatrix);
|
|||
|
//material.SetFloat(ShaderProperties.radius, aoSettings.radius * 0.5f * ((screenHeight / (generalSettings.deinterleaving == Deinterleaving.x4 ? 4 : 1)) / (tanHalfFovY * 2.0f)));
|
|||
|
//material.SetFloat(ShaderProperties.radius, aoSettings.radius * 0.5f * ((screenHeight / (generalSettings.deinterleaving == Deinterleaving.x4 ? 4 : 1)) / (invFocalLenY * 2.0f)));
|
|||
|
material.SetFloatArray(ShaderProperties.radius, m_RadiusPerEye);
|
|||
|
material.SetFloat(ShaderProperties.maxRadiusPixels, maxRadInPixels);
|
|||
|
material.SetFloat(ShaderProperties.negInvRadius2, -1.0f / (aoSettings.radius * aoSettings.radius));
|
|||
|
material.SetFloat(ShaderProperties.angleBias, aoSettings.bias);
|
|||
|
material.SetFloat(ShaderProperties.aoMultiplier, 2.0f * (1.0f / (1.0f - aoSettings.bias)));
|
|||
|
material.SetFloat(ShaderProperties.intensity, isLinearColorSpace ? aoSettings.intensity : aoSettings.intensity * 0.454545454545455f);
|
|||
|
material.SetColor(ShaderProperties.baseColor, aoSettings.baseColor);
|
|||
|
material.SetFloat(ShaderProperties.multiBounceInfluence, aoSettings.multiBounceInfluence);
|
|||
|
material.SetFloat(ShaderProperties.offscreenSamplesContrib, aoSettings.offscreenSamplesContribution);
|
|||
|
material.SetFloat(ShaderProperties.maxDistance, aoSettings.maxDistance);
|
|||
|
material.SetFloat(ShaderProperties.distanceFalloff, aoSettings.distanceFalloff);
|
|||
|
material.SetFloat(ShaderProperties.blurSharpness, blurSettings.sharpness);
|
|||
|
material.SetFloat(ShaderProperties.colorBleedSaturation, colorBleedingSettings.saturation);
|
|||
|
material.SetFloat(ShaderProperties.albedoMultiplier, colorBleedingSettings.albedoMultiplier);
|
|||
|
material.SetFloat(ShaderProperties.colorBleedBrightnessMask, colorBleedingSettings.brightnessMask);
|
|||
|
material.SetVector(ShaderProperties.colorBleedBrightnessMaskRange, AdjustBrightnessMaskToGammaSpace(new Vector2(Mathf.Pow(colorBleedingSettings.brightnessMaskRange.x, 3), Mathf.Pow(colorBleedingSettings.brightnessMaskRange.y, 3))));
|
|||
|
material.SetVector(ShaderProperties.temporalParams, temporalFilterSettings.enabled && !renderingInSceneView ? new Vector2(s_temporalRotations[frameCount % 6] / 360.0f, s_temporalOffsets[frameCount % 4]) : Vector2.zero);
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateShaderKeywords()
|
|||
|
{
|
|||
|
if (m_ShaderKeywords == null || m_ShaderKeywords.Length != 12) m_ShaderKeywords = new string[12];
|
|||
|
|
|||
|
m_ShaderKeywords[0] = ShaderProperties.GetOrthographicOrDeferredKeyword(hbaoCamera.orthographic, generalSettings);
|
|||
|
m_ShaderKeywords[1] = ShaderProperties.GetQualityKeyword(generalSettings);
|
|||
|
m_ShaderKeywords[2] = ShaderProperties.GetNoiseKeyword(generalSettings);
|
|||
|
m_ShaderKeywords[3] = ShaderProperties.GetDeinterleavingKeyword(generalSettings);
|
|||
|
m_ShaderKeywords[4] = ShaderProperties.GetDebugKeyword(generalSettings);
|
|||
|
m_ShaderKeywords[5] = ShaderProperties.GetMultibounceKeyword(aoSettings);
|
|||
|
m_ShaderKeywords[6] = ShaderProperties.GetOffscreenSamplesContributionKeyword(aoSettings);
|
|||
|
m_ShaderKeywords[7] = ShaderProperties.GetPerPixelNormalsKeyword(aoSettings);
|
|||
|
m_ShaderKeywords[8] = ShaderProperties.GetBlurRadiusKeyword(blurSettings);
|
|||
|
m_ShaderKeywords[9] = ShaderProperties.GetVarianceClippingKeyword(temporalFilterSettings);
|
|||
|
m_ShaderKeywords[10] = ShaderProperties.GetColorBleedingKeyword(colorBleedingSettings);
|
|||
|
m_ShaderKeywords[11] = ShaderProperties.GetLightingLogEncodedKeyword(hbaoCamera.allowHDR);
|
|||
|
|
|||
|
material.shaderKeywords = m_ShaderKeywords;
|
|||
|
}
|
|||
|
|
|||
|
private void CheckParameters()
|
|||
|
{
|
|||
|
// Camera textures
|
|||
|
hbaoCamera.depthTextureMode |= DepthTextureMode.Depth;
|
|||
|
if (aoSettings.perPixelNormals == PerPixelNormals.Camera)
|
|||
|
hbaoCamera.depthTextureMode |= DepthTextureMode.DepthNormals;
|
|||
|
if (temporalFilterSettings.enabled)
|
|||
|
hbaoCamera.depthTextureMode |= DepthTextureMode.MotionVectors;
|
|||
|
|
|||
|
// Settings to force
|
|||
|
if (hbaoCamera.actualRenderingPath != RenderingPath.DeferredShading && aoSettings.perPixelNormals == PerPixelNormals.GBuffer)
|
|||
|
SetAoPerPixelNormals(PerPixelNormals.Camera);
|
|||
|
|
|||
|
if (generalSettings.deinterleaving != Deinterleaving.Disabled && SystemInfo.supportedRenderTargetCount < 4)
|
|||
|
SetDeinterleaving(Deinterleaving.Disabled);
|
|||
|
|
|||
|
if (generalSettings.pipelineStage != PipelineStage.BeforeImageEffectsOpaque && hbaoCamera.actualRenderingPath != RenderingPath.DeferredShading)
|
|||
|
SetPipelineStage(PipelineStage.BeforeImageEffectsOpaque);
|
|||
|
|
|||
|
if (generalSettings.pipelineStage != PipelineStage.BeforeImageEffectsOpaque && aoSettings.perPixelNormals == PerPixelNormals.Camera)
|
|||
|
SetAoPerPixelNormals(PerPixelNormals.GBuffer);
|
|||
|
|
|||
|
if (stereoActive && hbaoCamera.actualRenderingPath != RenderingPath.DeferredShading && aoSettings.perPixelNormals != PerPixelNormals.Reconstruct)
|
|||
|
SetAoPerPixelNormals(PerPixelNormals.Reconstruct);
|
|||
|
|
|||
|
if (temporalFilterSettings.enabled && !motionVectorsSupported)
|
|||
|
EnableTemporalFilter(false);
|
|||
|
|
|||
|
if (colorBleedingSettings.enabled && temporalFilterSettings.enabled && SystemInfo.supportedRenderTargetCount < 2)
|
|||
|
EnableTemporalFilter(false);
|
|||
|
|
|||
|
// Noise texture
|
|||
|
if (noiseTex == null || m_PreviousNoiseType != generalSettings.noiseType)
|
|||
|
{
|
|||
|
if (noiseTex != null) DestroyImmediate(noiseTex);
|
|||
|
|
|||
|
CreateNoiseTexture();
|
|||
|
|
|||
|
m_PreviousNoiseType = generalSettings.noiseType;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private RenderTextureDescriptor GetDefaultDescriptor(int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default)
|
|||
|
{
|
|||
|
var modifiedDesc = new RenderTextureDescriptor(m_sourceDescriptor.width, m_sourceDescriptor.height,
|
|||
|
m_sourceDescriptor.colorFormat, depthBufferBits);
|
|||
|
modifiedDesc.dimension = m_sourceDescriptor.dimension;
|
|||
|
modifiedDesc.volumeDepth = m_sourceDescriptor.volumeDepth;
|
|||
|
modifiedDesc.vrUsage = m_sourceDescriptor.vrUsage;
|
|||
|
modifiedDesc.msaaSamples = m_sourceDescriptor.msaaSamples;
|
|||
|
modifiedDesc.memoryless = m_sourceDescriptor.memoryless;
|
|||
|
|
|||
|
modifiedDesc.useMipMap = m_sourceDescriptor.useMipMap;
|
|||
|
modifiedDesc.autoGenerateMips = m_sourceDescriptor.autoGenerateMips;
|
|||
|
modifiedDesc.enableRandomWrite = m_sourceDescriptor.enableRandomWrite;
|
|||
|
modifiedDesc.shadowSamplingMode = m_sourceDescriptor.shadowSamplingMode;
|
|||
|
|
|||
|
if (hbaoCamera.allowDynamicResolution)
|
|||
|
modifiedDesc.useDynamicScale = true;
|
|||
|
|
|||
|
if (colorFormat != RenderTextureFormat.Default)
|
|||
|
modifiedDesc.colorFormat = colorFormat;
|
|||
|
|
|||
|
if (readWrite == RenderTextureReadWrite.sRGB)
|
|||
|
modifiedDesc.sRGB = true;
|
|||
|
else if (readWrite == RenderTextureReadWrite.Linear)
|
|||
|
modifiedDesc.sRGB = false;
|
|||
|
else if (readWrite == RenderTextureReadWrite.Default)
|
|||
|
modifiedDesc.sRGB = isLinearColorSpace;
|
|||
|
|
|||
|
return modifiedDesc;
|
|||
|
}
|
|||
|
|
|||
|
private RenderTexture GetScreenSpaceRT(int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default,
|
|||
|
FilterMode filter = FilterMode.Bilinear, int widthOverride = 0, int heightOverride = 0)
|
|||
|
{
|
|||
|
var desc = GetDefaultDescriptor(depthBufferBits, colorFormat, readWrite);
|
|||
|
if (widthOverride > 0)
|
|||
|
desc.width = widthOverride;
|
|||
|
if (heightOverride > 0)
|
|||
|
desc.height = heightOverride;
|
|||
|
|
|||
|
var rt = new RenderTexture(desc);
|
|||
|
rt.filterMode = filter;
|
|||
|
return rt;
|
|||
|
}
|
|||
|
|
|||
|
private void GetScreenSpaceTemporaryRT(CommandBuffer cmd, int nameID,
|
|||
|
int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default,
|
|||
|
FilterMode filter = FilterMode.Bilinear, int widthOverride = 0, int heightOverride = 0)
|
|||
|
{
|
|||
|
var desc = GetDefaultDescriptor(depthBufferBits, colorFormat, readWrite);
|
|||
|
if (widthOverride > 0)
|
|||
|
desc.width = widthOverride;
|
|||
|
if (heightOverride > 0)
|
|||
|
desc.height = heightOverride;
|
|||
|
|
|||
|
cmd.GetTemporaryRT(nameID, desc, filter);
|
|||
|
}
|
|||
|
|
|||
|
private void ReleaseTemporaryRT(CommandBuffer cmd, int nameID)
|
|||
|
{
|
|||
|
cmd.ReleaseTemporaryRT(nameID);
|
|||
|
}
|
|||
|
|
|||
|
private void BlitFullscreenTriangle(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, int pass = 0)
|
|||
|
{
|
|||
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|||
|
cmd.SetRenderTarget(destination, 0, CubemapFace.Unknown, -1);
|
|||
|
cmd.DrawMesh(fullscreenTriangle, Matrix4x4.identity, material, 0, pass);
|
|||
|
}
|
|||
|
|
|||
|
private void BlitFullscreenTriangle(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier[] destinations, Material material, int pass = 0)
|
|||
|
{
|
|||
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|||
|
cmd.SetRenderTarget(destinations, destinations[0], 0, CubemapFace.Unknown, -1);
|
|||
|
cmd.DrawMesh(fullscreenTriangle, Matrix4x4.identity, material, 0, pass);
|
|||
|
}
|
|||
|
|
|||
|
private void BlitFullscreenTriangleWithClear(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, Color clearColor, int pass = 0)
|
|||
|
{
|
|||
|
cmd.SetGlobalTexture(ShaderProperties.mainTex, source);
|
|||
|
cmd.SetRenderTarget(destination, 0, CubemapFace.Unknown, -1);
|
|||
|
cmd.ClearRenderTarget(false, true, clearColor);
|
|||
|
cmd.DrawMesh(fullscreenTriangle, Matrix4x4.identity, material, 0, pass);
|
|||
|
}
|
|||
|
|
|||
|
private static void ApplyFlip(CommandBuffer cmd, bool flip = true)
|
|||
|
{
|
|||
|
if (flip)
|
|||
|
cmd.SetGlobalVector(ShaderProperties.uvTransform, new Vector4(1f, -1f, 0f, 1f));
|
|||
|
else
|
|||
|
cmd.SetGlobalVector(ShaderProperties.uvTransform, new Vector4(1f, 1f, 0f, 0f));
|
|||
|
}
|
|||
|
|
|||
|
private static Vector2 AdjustBrightnessMaskToGammaSpace(Vector2 v)
|
|||
|
{
|
|||
|
return isLinearColorSpace ? v : ToGammaSpace(v);
|
|||
|
}
|
|||
|
|
|||
|
private static float ToGammaSpace(float v)
|
|||
|
{
|
|||
|
return Mathf.Pow(v, 0.454545454545455f);
|
|||
|
}
|
|||
|
|
|||
|
private static 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 = generalSettings.noiseType != NoiseType.Dither ? 0.25f * (0.0625f * ((x + y & 3) << 2) + (x & 3)) : MersenneTwister.Numbers[z++];
|
|||
|
float r2 = generalSettings.noiseType != 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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|