SLEAPY_SMURF/Assets/JMO Assets/Cartoon FX Remaster/Demo Assets/Kino Bloom/Bloom.cs

273 lines
7.1 KiB
C#
Raw Normal View History

2023-04-30 11:23:57 +00:00
//
// Kino/Bloom v2 - Bloom filter for Unity
//
// Copyright (C) 2015, 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Modified by Jean Moreno for Cartoon FX Remaster Demo
// - effect previews in SceneView
// - disabled a code warning
using UnityEngine;
namespace Kino
{
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[ImageEffectAllowedInSceneView]
public class Bloom : MonoBehaviour
{
#region Public Properties
/// Prefilter threshold (gamma-encoded)
/// Filters out pixels under this level of brightness.
public float thresholdGamma
{
get { return Mathf.Max(_threshold, 0); }
set { _threshold = value; }
}
/// Prefilter threshold (linearly-encoded)
/// Filters out pixels under this level of brightness.
public float thresholdLinear
{
get { return GammaToLinear(thresholdGamma); }
set { _threshold = LinearToGamma(value); }
}
[SerializeField]
[Tooltip("Filters out pixels under this level of brightness.")]
float _threshold = 0.8f;
/// Soft-knee coefficient
/// Makes transition between under/over-threshold gradual.
public float softKnee
{
get { return _softKnee; }
set { _softKnee = value; }
}
[SerializeField, Range(0, 1)]
[Tooltip("Makes transition between under/over-threshold gradual.")]
float _softKnee = 0.5f;
/// Bloom radius
/// Changes extent of veiling effects in a screen
/// resolution-independent fashion.
public float radius
{
get { return _radius; }
set { _radius = value; }
}
[SerializeField, Range(1, 7)]
[Tooltip("Changes extent of veiling effects\n" +
"in a screen resolution-independent fashion.")]
float _radius = 2.5f;
/// Bloom intensity
/// Blend factor of the result image.
public float intensity
{
get { return Mathf.Max(_intensity, 0); }
set { _intensity = value; }
}
[SerializeField]
[Tooltip("Blend factor of the result image.")]
float _intensity = 0.8f;
/// High quality mode
/// Controls filter quality and buffer resolution.
public bool highQuality
{
get { return _highQuality; }
set { _highQuality = value; }
}
[SerializeField]
[Tooltip("Controls filter quality and buffer resolution.")]
bool _highQuality = true;
/// Anti-flicker filter
/// Reduces flashing noise with an additional filter.
[SerializeField]
[Tooltip("Reduces flashing noise with an additional filter.")]
bool _antiFlicker = true;
public bool antiFlicker
{
get { return _antiFlicker; }
set { _antiFlicker = value; }
}
#endregion
#region Private Members
#pragma warning disable 0649
[SerializeField, HideInInspector]
Shader _shader;
#pragma warning restore 0649
Material _material;
const int kMaxIterations = 16;
RenderTexture[] _blurBuffer1 = new RenderTexture[kMaxIterations];
RenderTexture[] _blurBuffer2 = new RenderTexture[kMaxIterations];
float LinearToGamma(float x)
{
#if UNITY_5_3_OR_NEWER
return Mathf.LinearToGammaSpace(x);
#else
if (x <= 0.0031308f)
return 12.92f * x;
else
return 1.055f * Mathf.Pow(x, 1 / 2.4f) - 0.055f;
#endif
}
float GammaToLinear(float x)
{
#if UNITY_5_3_OR_NEWER
return Mathf.GammaToLinearSpace(x);
#else
if (x <= 0.04045f)
return x / 12.92f;
else
return Mathf.Pow((x + 0.055f) / 1.055f, 2.4f);
#endif
}
#endregion
#region MonoBehaviour Functions
void OnEnable()
{
var shader = _shader ? _shader : Shader.Find("Hidden/Kino/Bloom");
_material = new Material(shader);
_material.hideFlags = HideFlags.DontSave;
}
void OnDisable()
{
DestroyImmediate(_material);
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
var useRGBM = Application.isMobilePlatform;
// source texture size
var tw = source.width;
var th = source.height;
// halve the texture size for the low quality mode
if (!_highQuality)
{
tw /= 2;
th /= 2;
}
// blur buffer format
var rtFormat = useRGBM ?
RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR;
// determine the iteration count
var logh = Mathf.Log(th, 2) + _radius - 8;
var logh_i = (int)logh;
var iterations = Mathf.Clamp(logh_i, 1, kMaxIterations);
// update the shader properties
var lthresh = thresholdLinear;
_material.SetFloat("_Threshold", lthresh);
var knee = lthresh * _softKnee + 1e-5f;
var curve = new Vector3(lthresh - knee, knee * 2, 0.25f / knee);
_material.SetVector("_Curve", curve);
var pfo = !_highQuality && _antiFlicker;
_material.SetFloat("_PrefilterOffs", pfo ? -0.5f : 0.0f);
_material.SetFloat("_SampleScale", 0.5f + logh - logh_i);
_material.SetFloat("_Intensity", intensity);
// prefilter pass
var prefiltered = RenderTexture.GetTemporary(tw, th, 0, rtFormat);
var pass = _antiFlicker ? 1 : 0;
Graphics.Blit(source, prefiltered, _material, pass);
// construct a mip pyramid
var last = prefiltered;
for (var level = 0; level < iterations; level++)
{
_blurBuffer1[level] = RenderTexture.GetTemporary(
last.width / 2, last.height / 2, 0, rtFormat
);
pass = (level == 0) ? (_antiFlicker ? 3 : 2) : 4;
Graphics.Blit(last, _blurBuffer1[level], _material, pass);
last = _blurBuffer1[level];
}
// upsample and combine loop
for (var level = iterations - 2; level >= 0; level--)
{
var basetex = _blurBuffer1[level];
_material.SetTexture("_BaseTex", basetex);
_blurBuffer2[level] = RenderTexture.GetTemporary(
basetex.width, basetex.height, 0, rtFormat
);
pass = _highQuality ? 6 : 5;
Graphics.Blit(last, _blurBuffer2[level], _material, pass);
last = _blurBuffer2[level];
}
// finish process
_material.SetTexture("_BaseTex", source);
pass = _highQuality ? 8 : 7;
Graphics.Blit(last, destination, _material, pass);
// release the temporary buffers
for (var i = 0; i < kMaxIterations; i++)
{
if (_blurBuffer1[i] != null)
RenderTexture.ReleaseTemporary(_blurBuffer1[i]);
if (_blurBuffer2[i] != null)
RenderTexture.ReleaseTemporary(_blurBuffer2[i]);
_blurBuffer1[i] = null;
_blurBuffer2[i] = null;
}
RenderTexture.ReleaseTemporary(prefiltered);
}
#endregion
}
}