using System;
namespace UnityEngine.Rendering.PostProcessing
{
///
/// This class holds settings for the Grain effect.
///
[Serializable]
[PostProcess(typeof(GrainRenderer), "Unity/Grain")]
public sealed class Grain : PostProcessEffectSettings
{
///
/// Set to true to render colored grain, false for grayscale grain.
///
[Tooltip("Enable the use of colored grain.")]
public BoolParameter colored = new BoolParameter { value = true };
///
/// The strength (or visibility) of the Grain effect on screen. Higher values mean more visible grain.
///
[Range(0f, 1f), Tooltip("Grain strength. Higher values mean more visible grain.")]
public FloatParameter intensity = new FloatParameter { value = 0f };
///
/// The size of grain particle on screen.
///
[Range(0.3f, 3f), Tooltip("Grain particle size.")]
public FloatParameter size = new FloatParameter { value = 1f };
///
/// Controls the noisiness response curve based on scene luminance. Lower values mean less noise in dark areas.
///
[Range(0f, 1f), DisplayName("Luminance Contribution"), Tooltip("Controls the noise response curve based on scene luminance. Lower values mean less noise in dark areas.")]
public FloatParameter lumContrib = new FloatParameter { value = 0.8f };
///
/// Returns true if the effect is currently enabled and supported.
///
/// The current post-processing render context
/// true if the effect is currently enabled and supported
public override bool IsEnabledAndSupported(PostProcessRenderContext context)
{
return enabled.value
&& intensity.value > 0f;
}
}
#if POSTFX_DEBUG_STATIC_GRAIN
#pragma warning disable 414
#endif
[UnityEngine.Scripting.Preserve]
internal sealed class GrainRenderer : PostProcessEffectRenderer
{
RenderTexture m_GrainLookupRT;
const int k_SampleCount = 1024;
int m_SampleIndex;
public override void Render(PostProcessRenderContext context)
{
#if POSTFX_DEBUG_STATIC_GRAIN
// Chosen by a fair dice roll
float time = 0.4f;
float rndOffsetX = 0f;
float rndOffsetY = 0f;
#else
float time = Time.realtimeSinceStartup;
float rndOffsetX = HaltonSeq.Get(m_SampleIndex & 1023, 2);
float rndOffsetY = HaltonSeq.Get(m_SampleIndex & 1023, 3);
if (++m_SampleIndex >= k_SampleCount)
m_SampleIndex = 0;
#endif
// Generate the grain lut for the current frame first
if (m_GrainLookupRT == null || !m_GrainLookupRT.IsCreated())
{
RuntimeUtilities.Destroy(m_GrainLookupRT);
m_GrainLookupRT = new RenderTexture(128, 128, 0, GetLookupFormat())
{
filterMode = FilterMode.Bilinear,
wrapMode = TextureWrapMode.Repeat,
anisoLevel = 0,
name = "Grain Lookup Texture"
};
m_GrainLookupRT.Create();
}
var sheet = context.propertySheets.Get(context.resources.shaders.grainBaker);
sheet.properties.Clear();
sheet.properties.SetFloat(ShaderIDs.Phase, time % 10f);
sheet.properties.SetVector(ShaderIDs.GrainNoiseParameters, new Vector3(12.9898f, 78.233f, 43758.5453f));
context.command.BeginSample("GrainLookup");
context.command.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_GrainLookupRT, sheet, settings.colored.value ? 1 : 0);
context.command.EndSample("GrainLookup");
// Send everything to the uber shader
var uberSheet = context.uberSheet;
uberSheet.EnableKeyword("GRAIN");
uberSheet.properties.SetTexture(ShaderIDs.GrainTex, m_GrainLookupRT);
uberSheet.properties.SetVector(ShaderIDs.Grain_Params1, new Vector2(settings.lumContrib.value, settings.intensity.value * 20f));
uberSheet.properties.SetVector(ShaderIDs.Grain_Params2, new Vector4((float)context.width / (float)m_GrainLookupRT.width / settings.size.value, (float)context.height / (float)m_GrainLookupRT.height / settings.size.value, rndOffsetX, rndOffsetY));
}
RenderTextureFormat GetLookupFormat()
{
if (RenderTextureFormat.ARGBHalf.IsSupported())
return RenderTextureFormat.ARGBHalf;
return RenderTextureFormat.ARGB32;
}
public override void Release()
{
RuntimeUtilities.Destroy(m_GrainLookupRT);
m_GrainLookupRT = null;
m_SampleIndex = 0;
}
}
#if POSTFX_DEBUG_STATIC_GRAIN
#pragma warning restore 414
#endif
}