Files
2026-05-23 14:12:25 +02:00

239 lines
6.0 KiB
C#

using System;
using UnityEngine;
[Serializable]
[AddComponentMenu("Image Effects/Tonemapping")]
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class Tonemapping : PostEffectsBase
{
[Serializable]
public enum TonemapperType
{
SimpleReinhard = 0,
UserCurve = 1,
Hable = 2,
Photographic = 3,
OptimizedHejiDawson = 4,
AdaptiveReinhard = 5,
AdaptiveReinhardAutoWhite = 6
}
[Serializable]
public enum AdaptiveTexSize
{
Square16 = 0x10,
Square32 = 0x20,
Square64 = 0x40,
Square128 = 0x80,
Square256 = 0x100,
Square512 = 0x200,
Square1024 = 0x400
}
public TonemapperType type;
public AdaptiveTexSize adaptiveTextureSize;
public AnimationCurve remapCurve;
private Texture2D curveTex;
public float exposureAdjustment;
public float middleGrey;
public float white;
public float adaptionSpeed;
public Shader tonemapper;
public bool validRenderTextureFormat;
private Material tonemapMaterial;
private RenderTexture rt;
public Tonemapping()
{
type = TonemapperType.SimpleReinhard;
adaptiveTextureSize = AdaptiveTexSize.Square256;
exposureAdjustment = 1.5f;
middleGrey = 0.4f;
white = 2f;
adaptionSpeed = 1.5f;
validRenderTextureFormat = true;
}
public virtual void OnDisable()
{
if ((bool)tonemapMaterial)
{
UnityEngine.Object.DestroyImmediate(tonemapMaterial);
}
}
public override bool CheckResources()
{
CheckSupport(false, true);
tonemapMaterial = CheckShaderAndCreateMaterial(tonemapper, tonemapMaterial);
if (!curveTex && type == TonemapperType.UserCurve)
{
curveTex = new Texture2D(256, 1, TextureFormat.ARGB32, false, true);
curveTex.filterMode = FilterMode.Bilinear;
curveTex.wrapMode = TextureWrapMode.Clamp;
curveTex.hideFlags = HideFlags.DontSave;
}
if (!isSupported)
{
ReportAutoDisable();
}
return isSupported;
}
public virtual float UpdateCurve()
{
float num = 1f;
if (remapCurve == null)
{
remapCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(2f, 1f));
}
if (remapCurve != null)
{
if (remapCurve.length != 0)
{
num = remapCurve[remapCurve.length - 1].time;
}
for (float num2 = 0f; num2 <= 1f; num2 += 0.003921569f)
{
float num3 = remapCurve.Evaluate(num2 * 1f * num);
curveTex.SetPixel((int)Mathf.Floor(num2 * 255f), 0, new Color(num3, num3, num3));
}
curveTex.Apply();
}
return 1f / num;
}
public virtual bool CreateInternalRenderTexture()
{
int result;
if ((bool)rt)
{
result = 0;
}
else
{
rt = new RenderTexture(1, 1, 0, RenderTextureFormat.ARGBHalf);
RenderTexture renderTexture = RenderTexture.active;
RenderTexture.active = rt;
GL.Clear(false, true, Color.white);
rt.hideFlags = HideFlags.DontSave;
RenderTexture.active = renderTexture;
result = 1;
}
return (byte)result != 0;
}
[ImageEffectTransformsToLDR]
public virtual void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (!CheckResources())
{
Graphics.Blit(source, destination);
return;
}
exposureAdjustment = ((exposureAdjustment >= 0.001f) ? exposureAdjustment : 0.001f);
if (type == TonemapperType.UserCurve)
{
float value = UpdateCurve();
tonemapMaterial.SetFloat("_RangeScale", value);
tonemapMaterial.SetTexture("_Curve", curveTex);
Graphics.Blit(source, destination, tonemapMaterial, 4);
return;
}
if (type == TonemapperType.SimpleReinhard)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 6);
return;
}
if (type == TonemapperType.Hable)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 5);
return;
}
if (type == TonemapperType.Photographic)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 8);
return;
}
if (type == TonemapperType.OptimizedHejiDawson)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", 0.5f * exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 7);
return;
}
bool flag = CreateInternalRenderTexture();
RenderTexture temporary = RenderTexture.GetTemporary((int)adaptiveTextureSize, (int)adaptiveTextureSize, 0, RenderTextureFormat.ARGBHalf);
Graphics.Blit(source, temporary);
int num = (int)Mathf.Log((float)temporary.width * 1f, 2f);
int num2 = 2;
RenderTexture[] array = new RenderTexture[num];
for (int i = 0; i < num; i++)
{
array[i] = RenderTexture.GetTemporary(temporary.width / num2, temporary.width / num2, 0, RenderTextureFormat.ARGBHalf);
num2 *= 2;
}
float num3 = (float)source.width * 1f / ((float)source.height * 1f);
RenderTexture source2 = array[num - 1];
Graphics.Blit(temporary, array[0], tonemapMaterial, 1);
if (type == TonemapperType.AdaptiveReinhardAutoWhite)
{
for (int i = 0; i < num - 1; i++)
{
Graphics.Blit(array[i], array[i + 1], tonemapMaterial, 9);
source2 = array[i + 1];
}
}
else if (type == TonemapperType.AdaptiveReinhard)
{
for (int i = 0; i < num - 1; i++)
{
Graphics.Blit(array[i], array[i + 1]);
source2 = array[i + 1];
}
}
adaptionSpeed = ((adaptionSpeed >= 0.001f) ? adaptionSpeed : 0.001f);
tonemapMaterial.SetFloat("_AdaptionSpeed", adaptionSpeed);
Graphics.Blit(source2, rt, tonemapMaterial, 2);
middleGrey = ((middleGrey >= 0.001f) ? middleGrey : 0.001f);
tonemapMaterial.SetVector("_HdrParams", new Vector4(middleGrey, middleGrey, middleGrey, white * white));
tonemapMaterial.SetTexture("_SmallTex", rt);
if (type == TonemapperType.AdaptiveReinhard)
{
Graphics.Blit(source, destination, tonemapMaterial, 0);
}
else if (type == TonemapperType.AdaptiveReinhardAutoWhite)
{
Graphics.Blit(source, destination, tonemapMaterial, 10);
}
else
{
Debug.LogError("No valid adaptive tonemapper type found!");
Graphics.Blit(source, destination);
}
for (int i = 0; i < num; i++)
{
RenderTexture.ReleaseTemporary(array[i]);
}
RenderTexture.ReleaseTemporary(temporary);
}
public override void Main()
{
}
}