ColorGradingComponent.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. using System;
  2. namespace UnityEngine.PostProcessing
  3. {
  4. public sealed class ColorGradingComponent : PostProcessingComponentRenderTexture<ColorGradingModel>
  5. {
  6. public override bool active
  7. {
  8. get
  9. {
  10. return base.model.enabled && !this.context.interrupted;
  11. }
  12. }
  13. private float StandardIlluminantY(float x)
  14. {
  15. return 2.87f * x - 3f * x * x - 0.275095075f;
  16. }
  17. private Vector3 CIExyToLMS(float x, float y)
  18. {
  19. float num = 1f;
  20. float num2 = num * x / y;
  21. float num3 = num * (1f - x - y) / y;
  22. float x2 = 0.7328f * num2 + 0.4296f * num - 0.1624f * num3;
  23. float y2 = -0.7036f * num2 + 1.6975f * num + 0.0061f * num3;
  24. float z = 0.003f * num2 + 0.0136f * num + 0.9834f * num3;
  25. return new Vector3(x2, y2, z);
  26. }
  27. private Vector3 CalculateColorBalance(float temperature, float tint)
  28. {
  29. float num = temperature / 55f;
  30. float num2 = tint / 55f;
  31. float x = 0.31271f - num * ((num >= 0f) ? 0.05f : 0.1f);
  32. float y = this.StandardIlluminantY(x) + num2 * 0.05f;
  33. Vector3 vector = new Vector3(0.949237f, 1.03542f, 1.08728f);
  34. Vector3 vector2 = this.CIExyToLMS(x, y);
  35. return new Vector3(vector.x / vector2.x, vector.y / vector2.y, vector.z / vector2.z);
  36. }
  37. private static Color NormalizeColor(Color c)
  38. {
  39. float num = (c.r + c.g + c.b) / 3f;
  40. if (Mathf.Approximately(num, 0f))
  41. {
  42. return new Color(1f, 1f, 1f, c.a);
  43. }
  44. return new Color
  45. {
  46. r = c.r / num,
  47. g = c.g / num,
  48. b = c.b / num,
  49. a = c.a
  50. };
  51. }
  52. private static Vector3 ClampVector(Vector3 v, float min, float max)
  53. {
  54. return new Vector3(Mathf.Clamp(v.x, min, max), Mathf.Clamp(v.y, min, max), Mathf.Clamp(v.z, min, max));
  55. }
  56. public static Vector3 GetLiftValue(Color lift)
  57. {
  58. Color color = ColorGradingComponent.NormalizeColor(lift);
  59. float num = (color.r + color.g + color.b) / 3f;
  60. float x = (color.r - num) * 0.1f + lift.a;
  61. float y = (color.g - num) * 0.1f + lift.a;
  62. float z = (color.b - num) * 0.1f + lift.a;
  63. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), -1f, 1f);
  64. }
  65. public static Vector3 GetGammaValue(Color gamma)
  66. {
  67. Color color = ColorGradingComponent.NormalizeColor(gamma);
  68. float num = (color.r + color.g + color.b) / 3f;
  69. gamma.a *= ((gamma.a >= 0f) ? 5f : 0.8f);
  70. float b = Mathf.Pow(2f, (color.r - num) * 0.5f) + gamma.a;
  71. float b2 = Mathf.Pow(2f, (color.g - num) * 0.5f) + gamma.a;
  72. float b3 = Mathf.Pow(2f, (color.b - num) * 0.5f) + gamma.a;
  73. float x = 1f / Mathf.Max(0.01f, b);
  74. float y = 1f / Mathf.Max(0.01f, b2);
  75. float z = 1f / Mathf.Max(0.01f, b3);
  76. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), 0f, 5f);
  77. }
  78. public static Vector3 GetGainValue(Color gain)
  79. {
  80. Color color = ColorGradingComponent.NormalizeColor(gain);
  81. float num = (color.r + color.g + color.b) / 3f;
  82. gain.a *= ((gain.a <= 0f) ? 1f : 3f);
  83. float x = Mathf.Pow(2f, (color.r - num) * 0.5f) + gain.a;
  84. float y = Mathf.Pow(2f, (color.g - num) * 0.5f) + gain.a;
  85. float z = Mathf.Pow(2f, (color.b - num) * 0.5f) + gain.a;
  86. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), 0f, 4f);
  87. }
  88. public static void CalculateLiftGammaGain(Color lift, Color gamma, Color gain, out Vector3 outLift, out Vector3 outGamma, out Vector3 outGain)
  89. {
  90. outLift = ColorGradingComponent.GetLiftValue(lift);
  91. outGamma = ColorGradingComponent.GetGammaValue(gamma);
  92. outGain = ColorGradingComponent.GetGainValue(gain);
  93. }
  94. public static Vector3 GetSlopeValue(Color slope)
  95. {
  96. Color color = ColorGradingComponent.NormalizeColor(slope);
  97. float num = (color.r + color.g + color.b) / 3f;
  98. slope.a *= 0.5f;
  99. float x = (color.r - num) * 0.1f + slope.a + 1f;
  100. float y = (color.g - num) * 0.1f + slope.a + 1f;
  101. float z = (color.b - num) * 0.1f + slope.a + 1f;
  102. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), 0f, 2f);
  103. }
  104. public static Vector3 GetPowerValue(Color power)
  105. {
  106. Color color = ColorGradingComponent.NormalizeColor(power);
  107. float num = (color.r + color.g + color.b) / 3f;
  108. power.a *= 0.5f;
  109. float b = (color.r - num) * 0.1f + power.a + 1f;
  110. float b2 = (color.g - num) * 0.1f + power.a + 1f;
  111. float b3 = (color.b - num) * 0.1f + power.a + 1f;
  112. float x = 1f / Mathf.Max(0.01f, b);
  113. float y = 1f / Mathf.Max(0.01f, b2);
  114. float z = 1f / Mathf.Max(0.01f, b3);
  115. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), 0.5f, 2.5f);
  116. }
  117. public static Vector3 GetOffsetValue(Color offset)
  118. {
  119. Color color = ColorGradingComponent.NormalizeColor(offset);
  120. float num = (color.r + color.g + color.b) / 3f;
  121. offset.a *= 0.5f;
  122. float x = (color.r - num) * 0.05f + offset.a;
  123. float y = (color.g - num) * 0.05f + offset.a;
  124. float z = (color.b - num) * 0.05f + offset.a;
  125. return ColorGradingComponent.ClampVector(new Vector3(x, y, z), -0.8f, 0.8f);
  126. }
  127. public static void CalculateSlopePowerOffset(Color slope, Color power, Color offset, out Vector3 outSlope, out Vector3 outPower, out Vector3 outOffset)
  128. {
  129. outSlope = ColorGradingComponent.GetSlopeValue(slope);
  130. outPower = ColorGradingComponent.GetPowerValue(power);
  131. outOffset = ColorGradingComponent.GetOffsetValue(offset);
  132. }
  133. private TextureFormat GetCurveFormat()
  134. {
  135. if (SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf))
  136. {
  137. return TextureFormat.RGBAHalf;
  138. }
  139. return TextureFormat.RGBA32;
  140. }
  141. private Texture2D GetCurveTexture()
  142. {
  143. if (this.m_GradingCurves == null)
  144. {
  145. this.m_GradingCurves = new Texture2D(128, 2, this.GetCurveFormat(), false, true)
  146. {
  147. name = "Internal Curves Texture",
  148. hideFlags = HideFlags.DontSave,
  149. anisoLevel = 0,
  150. wrapMode = TextureWrapMode.Clamp,
  151. filterMode = FilterMode.Bilinear
  152. };
  153. }
  154. ColorGradingModel.CurvesSettings curves = base.model.settings.curves;
  155. curves.hueVShue.Cache();
  156. curves.hueVSsat.Cache();
  157. for (int i = 0; i < 128; i++)
  158. {
  159. float t = (float)i * 0.0078125f;
  160. float r = curves.hueVShue.Evaluate(t);
  161. float g = curves.hueVSsat.Evaluate(t);
  162. float b = curves.satVSsat.Evaluate(t);
  163. float a = curves.lumVSsat.Evaluate(t);
  164. this.m_pixels[i] = new Color(r, g, b, a);
  165. float a2 = curves.master.Evaluate(t);
  166. float r2 = curves.red.Evaluate(t);
  167. float g2 = curves.green.Evaluate(t);
  168. float b2 = curves.blue.Evaluate(t);
  169. this.m_pixels[i + 128] = new Color(r2, g2, b2, a2);
  170. }
  171. this.m_GradingCurves.SetPixels(this.m_pixels);
  172. this.m_GradingCurves.Apply(false, false);
  173. return this.m_GradingCurves;
  174. }
  175. private bool IsLogLutValid(RenderTexture lut)
  176. {
  177. return lut != null && lut.IsCreated() && lut.height == 32;
  178. }
  179. private RenderTextureFormat GetLutFormat()
  180. {
  181. if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
  182. {
  183. return RenderTextureFormat.ARGBHalf;
  184. }
  185. return RenderTextureFormat.ARGB32;
  186. }
  187. private void GenerateLut()
  188. {
  189. ColorGradingModel.Settings settings = base.model.settings;
  190. if (!this.IsLogLutValid(base.model.bakedLut))
  191. {
  192. GraphicsUtils.Destroy(base.model.bakedLut);
  193. base.model.bakedLut = new RenderTexture(1024, 32, 0, this.GetLutFormat())
  194. {
  195. name = "Color Grading Log LUT",
  196. hideFlags = HideFlags.DontSave,
  197. filterMode = FilterMode.Bilinear,
  198. wrapMode = TextureWrapMode.Clamp,
  199. anisoLevel = 0
  200. };
  201. }
  202. Material material = this.context.materialFactory.Get("Hidden/Post FX/Lut Generator");
  203. material.SetVector(ColorGradingComponent.Uniforms._LutParams, new Vector4(32f, 0.00048828125f, 0.015625f, 1.032258f));
  204. material.shaderKeywords = null;
  205. ColorGradingModel.TonemappingSettings tonemapping = settings.tonemapping;
  206. ColorGradingModel.Tonemapper tonemapper = tonemapping.tonemapper;
  207. if (tonemapper != ColorGradingModel.Tonemapper.Neutral)
  208. {
  209. if (tonemapper == ColorGradingModel.Tonemapper.ACES)
  210. {
  211. material.EnableKeyword("TONEMAPPING_FILMIC");
  212. }
  213. }
  214. else
  215. {
  216. material.EnableKeyword("TONEMAPPING_NEUTRAL");
  217. float num = tonemapping.neutralBlackIn * 20f + 1f;
  218. float num2 = tonemapping.neutralBlackOut * 10f + 1f;
  219. float num3 = tonemapping.neutralWhiteIn / 20f;
  220. float num4 = 1f - tonemapping.neutralWhiteOut / 20f;
  221. float t = num / num2;
  222. float t2 = num3 / num4;
  223. float y = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, t));
  224. float z = Mathf.LerpUnclamped(0.01f, 0.24f, t2);
  225. float w = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.2f, t));
  226. material.SetVector(ColorGradingComponent.Uniforms._NeutralTonemapperParams1, new Vector4(0.2f, y, z, w));
  227. material.SetVector(ColorGradingComponent.Uniforms._NeutralTonemapperParams2, new Vector4(0.02f, 0.3f, tonemapping.neutralWhiteLevel, tonemapping.neutralWhiteClip / 10f));
  228. }
  229. material.SetFloat(ColorGradingComponent.Uniforms._HueShift, settings.basic.hueShift / 360f);
  230. material.SetFloat(ColorGradingComponent.Uniforms._Saturation, settings.basic.saturation);
  231. material.SetFloat(ColorGradingComponent.Uniforms._Contrast, settings.basic.contrast);
  232. material.SetVector(ColorGradingComponent.Uniforms._Balance, this.CalculateColorBalance(settings.basic.temperature, settings.basic.tint));
  233. Vector3 v;
  234. Vector3 v2;
  235. Vector3 v3;
  236. ColorGradingComponent.CalculateLiftGammaGain(settings.colorWheels.linear.lift, settings.colorWheels.linear.gamma, settings.colorWheels.linear.gain, out v, out v2, out v3);
  237. material.SetVector(ColorGradingComponent.Uniforms._Lift, v);
  238. material.SetVector(ColorGradingComponent.Uniforms._InvGamma, v2);
  239. material.SetVector(ColorGradingComponent.Uniforms._Gain, v3);
  240. Vector3 v4;
  241. Vector3 v5;
  242. Vector3 v6;
  243. ColorGradingComponent.CalculateSlopePowerOffset(settings.colorWheels.log.slope, settings.colorWheels.log.power, settings.colorWheels.log.offset, out v4, out v5, out v6);
  244. material.SetVector(ColorGradingComponent.Uniforms._Slope, v4);
  245. material.SetVector(ColorGradingComponent.Uniforms._Power, v5);
  246. material.SetVector(ColorGradingComponent.Uniforms._Offset, v6);
  247. material.SetVector(ColorGradingComponent.Uniforms._ChannelMixerRed, settings.channelMixer.red);
  248. material.SetVector(ColorGradingComponent.Uniforms._ChannelMixerGreen, settings.channelMixer.green);
  249. material.SetVector(ColorGradingComponent.Uniforms._ChannelMixerBlue, settings.channelMixer.blue);
  250. material.SetTexture(ColorGradingComponent.Uniforms._Curves, this.GetCurveTexture());
  251. Graphics.Blit(null, base.model.bakedLut, material, 0);
  252. }
  253. public override void Prepare(Material uberMaterial)
  254. {
  255. if (base.model.isDirty || !this.IsLogLutValid(base.model.bakedLut))
  256. {
  257. this.GenerateLut();
  258. base.model.isDirty = false;
  259. }
  260. uberMaterial.EnableKeyword((!this.context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.PreGradingLog)) ? "COLOR_GRADING" : "COLOR_GRADING_LOG_VIEW");
  261. RenderTexture bakedLut = base.model.bakedLut;
  262. uberMaterial.SetTexture(ColorGradingComponent.Uniforms._LogLut, bakedLut);
  263. uberMaterial.SetVector(ColorGradingComponent.Uniforms._LogLut_Params, new Vector3(1f / (float)bakedLut.width, 1f / (float)bakedLut.height, (float)bakedLut.height - 1f));
  264. float value = Mathf.Exp(base.model.settings.basic.postExposure * 0.6931472f);
  265. uberMaterial.SetFloat(ColorGradingComponent.Uniforms._ExposureEV, value);
  266. }
  267. public void OnGUI()
  268. {
  269. RenderTexture bakedLut = base.model.bakedLut;
  270. Rect position = new Rect(this.context.viewport.x * (float)Screen.width + 8f, 8f, (float)bakedLut.width, (float)bakedLut.height);
  271. GUI.DrawTexture(position, bakedLut);
  272. }
  273. public override void OnDisable()
  274. {
  275. GraphicsUtils.Destroy(this.m_GradingCurves);
  276. GraphicsUtils.Destroy(base.model.bakedLut);
  277. this.m_GradingCurves = null;
  278. base.model.bakedLut = null;
  279. }
  280. private const int k_InternalLogLutSize = 32;
  281. private const int k_CurvePrecision = 128;
  282. private const float k_CurveStep = 0.0078125f;
  283. private Texture2D m_GradingCurves;
  284. private Color[] m_pixels = new Color[256];
  285. private static class Uniforms
  286. {
  287. internal static readonly int _LutParams = Shader.PropertyToID("_LutParams");
  288. internal static readonly int _NeutralTonemapperParams1 = Shader.PropertyToID("_NeutralTonemapperParams1");
  289. internal static readonly int _NeutralTonemapperParams2 = Shader.PropertyToID("_NeutralTonemapperParams2");
  290. internal static readonly int _HueShift = Shader.PropertyToID("_HueShift");
  291. internal static readonly int _Saturation = Shader.PropertyToID("_Saturation");
  292. internal static readonly int _Contrast = Shader.PropertyToID("_Contrast");
  293. internal static readonly int _Balance = Shader.PropertyToID("_Balance");
  294. internal static readonly int _Lift = Shader.PropertyToID("_Lift");
  295. internal static readonly int _InvGamma = Shader.PropertyToID("_InvGamma");
  296. internal static readonly int _Gain = Shader.PropertyToID("_Gain");
  297. internal static readonly int _Slope = Shader.PropertyToID("_Slope");
  298. internal static readonly int _Power = Shader.PropertyToID("_Power");
  299. internal static readonly int _Offset = Shader.PropertyToID("_Offset");
  300. internal static readonly int _ChannelMixerRed = Shader.PropertyToID("_ChannelMixerRed");
  301. internal static readonly int _ChannelMixerGreen = Shader.PropertyToID("_ChannelMixerGreen");
  302. internal static readonly int _ChannelMixerBlue = Shader.PropertyToID("_ChannelMixerBlue");
  303. internal static readonly int _Curves = Shader.PropertyToID("_Curves");
  304. internal static readonly int _LogLut = Shader.PropertyToID("_LogLut");
  305. internal static readonly int _LogLut_Params = Shader.PropertyToID("_LogLut_Params");
  306. internal static readonly int _ExposureEV = Shader.PropertyToID("_ExposureEV");
  307. }
  308. }
  309. }