You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
11 KiB
321 lines
11 KiB
3 years ago
|
using UnityEngine;
|
||
|
using UnityEngine.Rendering;
|
||
|
|
||
|
[ExecuteInEditMode]
|
||
|
[RequireComponent(typeof(Camera))]
|
||
|
[AddComponentMenu("KriptoFX/ME_BloomAndDistortion")]
|
||
|
#if UNITY_5_4_OR_NEWER
|
||
|
//[ImageEffectAllowedInSceneView]
|
||
|
#endif
|
||
|
public class ME_DistortionAndBloom : MonoBehaviour
|
||
|
{
|
||
|
public LayerMask CullingMask = ~0;
|
||
|
[Range(0.05f, 1)]
|
||
|
[Tooltip("Camera render texture resolution")]
|
||
|
public float RenderTextureResolutoinFactor = 0.25f;
|
||
|
|
||
|
public bool UseBloom = true;
|
||
|
|
||
|
[Range(0.1f, 3)]
|
||
|
[Tooltip("Filters out pixels under this level of brightness.")]
|
||
|
public float Threshold = 1.2f;
|
||
|
|
||
|
[SerializeField, Range(0, 1)]
|
||
|
[Tooltip("Makes transition between under/over-threshold gradual.")]
|
||
|
public float SoftKnee = 0f;
|
||
|
|
||
|
[Range(1, 7)]
|
||
|
[Tooltip("Changes extent of veiling effects in A screen resolution-independent fashion.")]
|
||
|
public float Radius = 7;
|
||
|
|
||
|
[Tooltip("Blend factor of the result image.")]
|
||
|
public float Intensity = 0.5f;
|
||
|
|
||
|
[Tooltip("Controls filter quality and buffer resolution.")]
|
||
|
public bool HighQuality;
|
||
|
|
||
|
|
||
|
[Tooltip("Reduces flashing noise with an additional filter.")]
|
||
|
public bool AntiFlicker;
|
||
|
|
||
|
const string shaderName = "Hidden/KriptoFX/PostEffects/ME_Bloom";
|
||
|
const string shaderAdditiveName = "Hidden/KriptoFX/PostEffects/ME_BloomAdditive";
|
||
|
const string cameraName = "MobileCamera(Distort_Bloom_Depth)";
|
||
|
|
||
|
RenderTexture source;
|
||
|
RenderTexture depth;
|
||
|
RenderTexture destination;
|
||
|
private int previuosFrameWidth, previuosFrameHeight;
|
||
|
private float previousScale;
|
||
|
private Camera addCamera;
|
||
|
private GameObject tempGO;
|
||
|
private bool HDRSupported;
|
||
|
|
||
|
private Material m_Material;
|
||
|
|
||
|
public Material mat
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (m_Material == null)
|
||
|
m_Material = CheckShaderAndCreateMaterial(Shader.Find(shaderName));
|
||
|
|
||
|
return m_Material;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private Material m_MaterialAdditive;
|
||
|
|
||
|
public Material matAdditive
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (m_MaterialAdditive == null)
|
||
|
{
|
||
|
m_MaterialAdditive = CheckShaderAndCreateMaterial(Shader.Find(shaderAdditiveName));
|
||
|
m_MaterialAdditive.renderQueue = 3900;
|
||
|
}
|
||
|
|
||
|
return m_MaterialAdditive;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static Material CheckShaderAndCreateMaterial(Shader s)
|
||
|
{
|
||
|
if (s == null || !s.isSupported)
|
||
|
return null;
|
||
|
|
||
|
var material = new Material(s);
|
||
|
material.hideFlags = HideFlags.DontSave;
|
||
|
return material;
|
||
|
}
|
||
|
|
||
|
#region Private Members
|
||
|
|
||
|
private const int kMaxIterations = 16;
|
||
|
private readonly RenderTexture[] m_blurBuffer1 = new RenderTexture[kMaxIterations];
|
||
|
private readonly RenderTexture[] m_blurBuffer2 = new RenderTexture[kMaxIterations];
|
||
|
|
||
|
private void OnDisable()
|
||
|
{
|
||
|
if (m_Material != null)
|
||
|
DestroyImmediate(m_Material);
|
||
|
m_Material = null;
|
||
|
|
||
|
if (m_MaterialAdditive != null)
|
||
|
DestroyImmediate(m_MaterialAdditive);
|
||
|
m_MaterialAdditive = null;
|
||
|
|
||
|
if(tempGO != null)
|
||
|
DestroyImmediate(tempGO);
|
||
|
|
||
|
Shader.DisableKeyword("DISTORT_OFF");
|
||
|
Shader.DisableKeyword("_MOBILEDEPTH_ON");
|
||
|
}
|
||
|
|
||
|
//private void OnGUI()
|
||
|
//{
|
||
|
// if (Event.current.type.Equals(EventType.Repaint))
|
||
|
// {
|
||
|
// if (UseBloom && HDRSupported && destination != null) Graphics.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), destination, matAdditive);
|
||
|
// }
|
||
|
// GUI.Label(new Rect(250, 0, 30, 30), "HDR: " + HDRSupported, guiStyleHeader);
|
||
|
//}
|
||
|
//public GUIStyle guiStyleHeader = new GUIStyle();
|
||
|
|
||
|
void Start()
|
||
|
{
|
||
|
InitializeRenderTarget();
|
||
|
}
|
||
|
|
||
|
void LateUpdate()
|
||
|
{
|
||
|
if (previuosFrameWidth != Screen.width || previuosFrameHeight != Screen.height || Mathf.Abs(previousScale - RenderTextureResolutoinFactor) > 0.01f)
|
||
|
{
|
||
|
InitializeRenderTarget();
|
||
|
previuosFrameWidth = Screen.width;
|
||
|
previuosFrameHeight = Screen.height;
|
||
|
previousScale = RenderTextureResolutoinFactor;
|
||
|
}
|
||
|
Shader.EnableKeyword("DISTORT_OFF");
|
||
|
Shader.EnableKeyword("_MOBILEDEPTH_ON");
|
||
|
GrabImage();
|
||
|
if (UseBloom && HDRSupported) UpdateBloom();
|
||
|
Shader.SetGlobalTexture("_GrabTexture", source);
|
||
|
Shader.SetGlobalTexture("_GrabTextureMobile", source);
|
||
|
Shader.SetGlobalTexture("_CameraDepthTexture", depth);
|
||
|
Shader.SetGlobalFloat("_GrabTextureScale", RenderTextureResolutoinFactor);
|
||
|
Shader.SetGlobalFloat("_GrabTextureMobileScale", RenderTextureResolutoinFactor);
|
||
|
Shader.DisableKeyword("DISTORT_OFF");
|
||
|
}
|
||
|
|
||
|
void OnPostRender()
|
||
|
{
|
||
|
Graphics.Blit(destination, null as RenderTexture, matAdditive);
|
||
|
}
|
||
|
|
||
|
private void InitializeRenderTarget()
|
||
|
{
|
||
|
var width = (int)(Screen.width * RenderTextureResolutoinFactor);
|
||
|
var height = (int)(Screen.height * RenderTextureResolutoinFactor);
|
||
|
#if UNITY_5_5_OR_NEWER
|
||
|
RenderTextureFormat optimizedHDRFormat = RenderTextureFormat.RGB111110Float;
|
||
|
#else
|
||
|
RenderTextureFormat optimizedHDRFormat = RenderTextureFormat.DefaultHDR;
|
||
|
#endif
|
||
|
if (SystemInfo.SupportsRenderTextureFormat(optimizedHDRFormat))
|
||
|
{
|
||
|
source = new RenderTexture(width, height, 0, optimizedHDRFormat);
|
||
|
depth = new RenderTexture(width, height, 8, RenderTextureFormat.Depth);
|
||
|
HDRSupported = true;
|
||
|
if (UseBloom) destination = new RenderTexture(RenderTextureResolutoinFactor > 0.99 ? width : width / 2,
|
||
|
RenderTextureResolutoinFactor > 0.99 ? height : height / 2, 0, optimizedHDRFormat);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HDRSupported = false;
|
||
|
source = new RenderTexture(width, height, 0, RenderTextureFormat.RGB565);
|
||
|
depth = new RenderTexture(width, height, 8, RenderTextureFormat.Depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void UpdateBloom()
|
||
|
{
|
||
|
var useRGBM = Application.isMobilePlatform;
|
||
|
if (source == null) return;
|
||
|
// 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 threshold = Mathf.GammaToLinearSpace(Threshold);
|
||
|
|
||
|
mat.SetFloat("_Threshold", threshold);
|
||
|
|
||
|
var knee = threshold * SoftKnee + 1e-5f;
|
||
|
var curve = new Vector3(threshold - knee, knee * 2, 0.25f / knee);
|
||
|
mat.SetVector("_Curve", curve);
|
||
|
|
||
|
var pfo = !HighQuality && AntiFlicker;
|
||
|
mat.SetFloat("_PrefilterOffs", pfo ? -0.5f : 0.0f);
|
||
|
|
||
|
mat.SetFloat("_SampleScale", 0.5f + logh - logh_i);
|
||
|
mat.SetFloat("_Intensity", Mathf.Max(0.0f, Intensity));
|
||
|
|
||
|
var prefiltered = RenderTexture.GetTemporary(tw, th, 0, rtFormat);
|
||
|
|
||
|
Graphics.Blit(source, prefiltered, mat, AntiFlicker ? 1 : 0);
|
||
|
|
||
|
// construct A mip pyramid
|
||
|
var last = prefiltered;
|
||
|
for (var level = 0; level < iterations; level++)
|
||
|
{
|
||
|
m_blurBuffer1[level] = RenderTexture.GetTemporary(last.width / 2, last.height / 2, 0, rtFormat);
|
||
|
Graphics.Blit(last, m_blurBuffer1[level], mat, level == 0 ? (AntiFlicker ? 3 : 2) : 4);
|
||
|
last = m_blurBuffer1[level];
|
||
|
}
|
||
|
|
||
|
// upsample and combine loop
|
||
|
for (var level = iterations - 2; level >= 0; level--)
|
||
|
{
|
||
|
var basetex = m_blurBuffer1[level];
|
||
|
mat.SetTexture("_BaseTex", basetex);
|
||
|
m_blurBuffer2[level] = RenderTexture.GetTemporary(basetex.width, basetex.height, 0, rtFormat);
|
||
|
Graphics.Blit(last, m_blurBuffer2[level], mat, HighQuality ? 6 : 5);
|
||
|
last = m_blurBuffer2[level];
|
||
|
}
|
||
|
|
||
|
destination.DiscardContents();
|
||
|
Graphics.Blit(last, destination, mat, HighQuality ? 8 : 7);
|
||
|
|
||
|
|
||
|
for (var i = 0; i < kMaxIterations; i++)
|
||
|
{
|
||
|
if (m_blurBuffer1[i] != null) RenderTexture.ReleaseTemporary(m_blurBuffer1[i]);
|
||
|
if (m_blurBuffer2[i] != null) RenderTexture.ReleaseTemporary(m_blurBuffer2[i]);
|
||
|
m_blurBuffer1[i] = null;
|
||
|
m_blurBuffer2[i] = null;
|
||
|
}
|
||
|
|
||
|
RenderTexture.ReleaseTemporary(prefiltered);
|
||
|
}
|
||
|
|
||
|
void GrabImage()
|
||
|
{
|
||
|
var cam = Camera.current;
|
||
|
if (cam == null) cam = Camera.main;
|
||
|
|
||
|
if (tempGO == null)
|
||
|
{
|
||
|
tempGO = new GameObject();
|
||
|
tempGO.hideFlags = HideFlags.HideAndDontSave;
|
||
|
tempGO.name = cameraName;
|
||
|
addCamera = tempGO.AddComponent<Camera>();
|
||
|
addCamera.enabled = false;
|
||
|
addCamera.cullingMask = ~(1 << LayerMask.NameToLayer("CustomPostEffectIgnore")) & CullingMask;
|
||
|
// addCamera.transform.parent = cam.transform;
|
||
|
}
|
||
|
else addCamera = tempGO.GetComponent<Camera>();
|
||
|
addCamera.CopyFrom(cam);
|
||
|
addCamera.SetTargetBuffers(source.colorBuffer, depth.depthBuffer);
|
||
|
addCamera.depth--;
|
||
|
//addCamera.targetTexture = source;
|
||
|
addCamera.cullingMask = ~(1 << LayerMask.NameToLayer("CustomPostEffectIgnore")) & CullingMask;
|
||
|
addCamera.Render();
|
||
|
|
||
|
|
||
|
//var cam = Camera.current;
|
||
|
//if (cam != null && Camera.current.name == "SceneCamera")
|
||
|
//{
|
||
|
// tempGO = GameObject.Find("MobileSceneCamera(Distort_Bloom_Depth)");
|
||
|
// if (tempGO == null)
|
||
|
// {
|
||
|
// tempGO = new GameObject();
|
||
|
// //tempGO.hideFlags = HideFlags.HideAndDontSave;
|
||
|
// tempGO.name = "MobileSceneCamera(Distort_Bloom_Depth)";
|
||
|
// addCamera = tempGO.AddComponent<Camera>();
|
||
|
// addCamera.enabled = false;
|
||
|
|
||
|
// }
|
||
|
// else addCamera = tempGO.GetComponent<Camera>();
|
||
|
// addCamera.CopyFrom(cam);
|
||
|
// addCamera.targetTexture = source;
|
||
|
// addCamera.SetTargetBuffers(source.colorBuffer, depth.depthBuffer);
|
||
|
// addCamera.Render();
|
||
|
// return;
|
||
|
//}
|
||
|
|
||
|
|
||
|
//if (tempGO == null)
|
||
|
//{
|
||
|
// tempGO = new GameObject();
|
||
|
// //tempGO.hideFlags = HideFlags.HideAndDontSave;
|
||
|
// tempGO.name = "MobileCamera(Distort_Bloom_Depth)";
|
||
|
// addCamera = tempGO.AddComponent<Camera>();
|
||
|
// addCamera.CopyFrom(Camera.main);
|
||
|
// addCamera.transform.parent = Camera.main.transform;
|
||
|
// addCamera.targetTexture = source;
|
||
|
// addCamera.enabled = false;
|
||
|
//}
|
||
|
//addCamera.SetTargetBuffers(source.colorBuffer, depth.depthBuffer);
|
||
|
//addCamera.Render();
|
||
|
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
}
|