4 namespace UnityStandardAssets.ImageEffects
7 [RequireComponent(typeof (Camera))]
8 [AddComponentMenu(
"Image Effects/Color Adjustments/Tonemapping")]
11 public enum TonemapperType
19 AdaptiveReinhardAutoWhite,
22 public enum AdaptiveTexSize
33 public TonemapperType type = TonemapperType.Photographic;
34 public AdaptiveTexSize adaptiveTextureSize = AdaptiveTexSize.Square256;
37 public AnimationCurve remapCurve;
38 private Texture2D curveTex = null;
41 public float exposureAdjustment = 1.5f;
44 public float middleGrey = 0.4f;
45 public float white = 2.0f;
46 public float adaptionSpeed = 1.5f;
49 public Shader tonemapper = null;
50 public bool validRenderTextureFormat =
true;
51 private Material tonemapMaterial = null;
52 private RenderTexture rt = null;
53 private RenderTextureFormat rtFormat = RenderTextureFormat.ARGBHalf;
56 public override bool CheckResources()
58 CheckSupport(
false,
true);
60 tonemapMaterial = CheckShaderAndCreateMaterial(tonemapper, tonemapMaterial);
61 if (!curveTex && type == TonemapperType.UserCurve)
63 curveTex =
new Texture2D(256, 1, TextureFormat.ARGB32,
false,
true);
64 curveTex.filterMode = FilterMode.Bilinear;
65 curveTex.wrapMode = TextureWrapMode.Clamp;
66 curveTex.hideFlags = HideFlags.DontSave;
75 public float UpdateCurve()
78 if (remapCurve.keys.Length < 1)
79 remapCurve =
new AnimationCurve(
new Keyframe(0, 0),
new Keyframe(2, 1));
80 if (remapCurve != null)
82 if (remapCurve.length > 0)
83 range = remapCurve[remapCurve.length - 1].time;
84 for (
float i = 0.0f; i <= 1.0f; i += 1.0f/255.0f)
86 float c = remapCurve.Evaluate(i*1.0f*range);
87 curveTex.SetPixel((int) Mathf.Floor(i*255.0f), 0,
new Color(c, c, c));
95 private void OnDisable()
104 DestroyImmediate(tonemapMaterial);
105 tonemapMaterial = null;
109 DestroyImmediate(curveTex);
115 private bool CreateInternalRenderTexture()
121 rtFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf) ? RenderTextureFormat.RGHalf : RenderTextureFormat.ARGBHalf;
122 rt =
new RenderTexture(1, 1, 0, rtFormat);
123 rt.hideFlags = HideFlags.DontSave;
129 [ImageEffectTransformsToLDR]
130 private void OnRenderImage(RenderTexture source, RenderTexture destination)
132 if (CheckResources() ==
false)
134 Graphics.Blit(source, destination);
139 validRenderTextureFormat =
true;
140 if (source.format != RenderTextureFormat.ARGBHalf)
142 validRenderTextureFormat =
false;
148 exposureAdjustment = exposureAdjustment < 0.001f ? 0.001f : exposureAdjustment;
152 if (type == TonemapperType.UserCurve)
154 float rangeScale = UpdateCurve();
155 tonemapMaterial.SetFloat(
"_RangeScale", rangeScale);
156 tonemapMaterial.SetTexture(
"_Curve", curveTex);
157 Graphics.Blit(source, destination, tonemapMaterial, 4);
161 if (type == TonemapperType.SimpleReinhard)
163 tonemapMaterial.SetFloat(
"_ExposureAdjustment", exposureAdjustment);
164 Graphics.Blit(source, destination, tonemapMaterial, 6);
168 if (type == TonemapperType.Hable)
170 tonemapMaterial.SetFloat(
"_ExposureAdjustment", exposureAdjustment);
171 Graphics.Blit(source, destination, tonemapMaterial, 5);
175 if (type == TonemapperType.Photographic)
177 tonemapMaterial.SetFloat(
"_ExposureAdjustment", exposureAdjustment);
178 Graphics.Blit(source, destination, tonemapMaterial, 8);
182 if (type == TonemapperType.OptimizedHejiDawson)
184 tonemapMaterial.SetFloat(
"_ExposureAdjustment", 0.5f*exposureAdjustment);
185 Graphics.Blit(source, destination, tonemapMaterial, 7);
196 bool freshlyBrewedInternalRt = CreateInternalRenderTexture();
198 RenderTexture rtSquared = RenderTexture.GetTemporary((int) adaptiveTextureSize, (
int) adaptiveTextureSize, 0, rtFormat);
199 Graphics.Blit(source, rtSquared);
201 int downsample = (int) Mathf.Log(rtSquared.width*1.0f, 2);
204 var rts =
new RenderTexture[downsample];
205 for (
int i = 0; i < downsample; i++)
207 rts[i] = RenderTexture.GetTemporary(rtSquared.width/div, rtSquared.width/div, 0, rtFormat);
213 var lumRt = rts[downsample - 1];
214 Graphics.Blit(rtSquared, rts[0], tonemapMaterial, 1);
215 if (type == TonemapperType.AdaptiveReinhardAutoWhite)
217 for (
int i = 0; i < downsample - 1; i++)
219 Graphics.Blit(rts[i], rts[i + 1], tonemapMaterial, 9);
223 else if (type == TonemapperType.AdaptiveReinhard)
225 for (
int i = 0; i < downsample - 1; i++)
227 Graphics.Blit(rts[i], rts[i + 1]);
234 adaptionSpeed = adaptionSpeed < 0.001f ? 0.001f : adaptionSpeed;
235 tonemapMaterial.SetFloat(
"_AdaptionSpeed", adaptionSpeed);
237 rt.MarkRestoreExpected();
240 if (Application.isPlaying && !freshlyBrewedInternalRt)
241 Graphics.Blit(lumRt, rt, tonemapMaterial, 2);
243 Graphics.Blit(lumRt, rt, tonemapMaterial, 3);
245 Graphics.Blit (lumRt, rt, tonemapMaterial, freshlyBrewedInternalRt ? 3 : 2);
248 middleGrey = middleGrey < 0.001f ? 0.001f : middleGrey;
249 tonemapMaterial.SetVector(
"_HdrParams",
new Vector4(middleGrey, middleGrey, middleGrey, white*white));
250 tonemapMaterial.SetTexture(
"_SmallTex", rt);
251 if (type == TonemapperType.AdaptiveReinhard)
253 Graphics.Blit(source, destination, tonemapMaterial, 0);
255 else if (type == TonemapperType.AdaptiveReinhardAutoWhite)
257 Graphics.Blit(source, destination, tonemapMaterial, 10);
261 Debug.LogError(
"No valid adaptive tonemapper type found!");
262 Graphics.Blit(source, destination);
267 for (
int i = 0; i < downsample; i++)
269 RenderTexture.ReleaseTemporary(rts[i]);
271 RenderTexture.ReleaseTemporary(rtSquared);