Files
2026-02-21 16:45:37 +08:00

228 lines
6.1 KiB
C#

using UnityEngine;
namespace UnityStandardAssets.ImageEffects
{
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[AddComponentMenu("Image Effects/Color Adjustments/Tonemapping")]
public class Tonemapping : PostEffectsBase
{
public enum TonemapperType
{
SimpleReinhard = 0,
UserCurve = 1,
Hable = 2,
Photographic = 3,
OptimizedHejiDawson = 4,
AdaptiveReinhard = 5,
AdaptiveReinhardAutoWhite = 6
}
public enum AdaptiveTexSize
{
Square16 = 0x10,
Square32 = 0x20,
Square64 = 0x40,
Square128 = 0x80,
Square256 = 0x100,
Square512 = 0x200,
Square1024 = 0x400
}
public TonemapperType type = TonemapperType.Photographic;
public AdaptiveTexSize adaptiveTextureSize = AdaptiveTexSize.Square256;
public AnimationCurve remapCurve;
private Texture2D curveTex;
public float exposureAdjustment = 1.5f;
public float middleGrey = 0.4f;
public float white = 2f;
public float adaptionSpeed = 1.5f;
public Shader tonemapper;
public bool validRenderTextureFormat = true;
private Material tonemapMaterial;
private RenderTexture rt;
private RenderTextureFormat rtFormat = RenderTextureFormat.ARGBHalf;
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 float UpdateCurve()
{
float num = 1f;
if (remapCurve.keys.Length < 1)
{
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;
}
private void OnDisable()
{
if ((bool)rt)
{
Object.DestroyImmediate(rt);
rt = null;
}
if ((bool)tonemapMaterial)
{
Object.DestroyImmediate(tonemapMaterial);
tonemapMaterial = null;
}
if ((bool)curveTex)
{
Object.DestroyImmediate(curveTex);
curveTex = null;
}
}
private bool CreateInternalRenderTexture()
{
if ((bool)rt)
{
return false;
}
rtFormat = ((!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf)) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.RGHalf);
rt = new RenderTexture(1, 1, 0, rtFormat);
rt.hideFlags = HideFlags.DontSave;
return true;
}
[ImageEffectTransformsToLDR]
private 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, rtFormat);
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, rtFormat);
num2 *= 2;
}
RenderTexture source2 = array[num - 1];
Graphics.Blit(temporary, array[0], tonemapMaterial, 1);
if (type == TonemapperType.AdaptiveReinhardAutoWhite)
{
for (int j = 0; j < num - 1; j++)
{
Graphics.Blit(array[j], array[j + 1], tonemapMaterial, 9);
source2 = array[j + 1];
}
}
else if (type == TonemapperType.AdaptiveReinhard)
{
for (int k = 0; k < num - 1; k++)
{
Graphics.Blit(array[k], array[k + 1]);
source2 = array[k + 1];
}
}
adaptionSpeed = ((!(adaptionSpeed < 0.001f)) ? adaptionSpeed : 0.001f);
tonemapMaterial.SetFloat("_AdaptionSpeed", adaptionSpeed);
rt.MarkRestoreExpected();
Graphics.Blit(source2, rt, tonemapMaterial, (!flag) ? 2 : 3);
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 l = 0; l < num; l++)
{
RenderTexture.ReleaseTemporary(array[l]);
}
RenderTexture.ReleaseTemporary(temporary);
}
}
}