Advertisement
Guest User

Untitled

a guest
Dec 20th, 2020
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.99 KB | None | 0 0
  1. namespace UnityStandardAssets.CinematicEffects
  2. {
  3. using UnityEngine;
  4. using UnityEngine.Events;
  5. using System;
  6.  
  7. [ExecuteInEditMode]
  8. [RequireComponent(typeof(Camera))]
  9. [AddComponentMenu("Image Effects/Cinematic/Tonemapping and Color Grading")]
  10. #if UNITY_5_4_OR_NEWER
  11. [ImageEffectAllowedInSceneView]
  12. #endif
  13. public class TonemappingColorGrading : MonoBehaviour
  14. {
  15. #if UNITY_EDITOR
  16. // EDITOR ONLY call for allowing the editor to update the histogram
  17. public UnityAction<RenderTexture> onFrameEndEditorOnly;
  18.  
  19. [SerializeField]
  20. private ComputeShader m_HistogramComputeShader;
  21. public ComputeShader histogramComputeShader
  22. {
  23. get
  24. {
  25. if (m_HistogramComputeShader == null)
  26. m_HistogramComputeShader = Resources.Load<ComputeShader>("HistogramCompute");
  27.  
  28. return m_HistogramComputeShader;
  29. }
  30. }
  31.  
  32. [SerializeField]
  33. private Shader m_HistogramShader;
  34. public Shader histogramShader
  35. {
  36. get
  37. {
  38. if (m_HistogramShader == null)
  39. m_HistogramShader = Shader.Find("Hidden/TonemappingColorGradingHistogram");
  40.  
  41. return m_HistogramShader;
  42. }
  43. }
  44.  
  45. [SerializeField]
  46. public bool histogramRefreshOnPlay = true;
  47. #endif
  48.  
  49. #region Attributes
  50. [AttributeUsage(AttributeTargets.Field)]
  51. public class SettingsGroup : Attribute
  52. {}
  53.  
  54. public class IndentedGroup : PropertyAttribute
  55. {}
  56.  
  57. public class ChannelMixer : PropertyAttribute
  58. {}
  59.  
  60. public class ColorWheelGroup : PropertyAttribute
  61. {
  62. public int minSizePerWheel = 60;
  63. public int maxSizePerWheel = 150;
  64.  
  65. public ColorWheelGroup()
  66. {}
  67.  
  68. public ColorWheelGroup(int minSizePerWheel, int maxSizePerWheel)
  69. {
  70. this.minSizePerWheel = minSizePerWheel;
  71. this.maxSizePerWheel = maxSizePerWheel;
  72. }
  73. }
  74.  
  75. public class Curve : PropertyAttribute
  76. {
  77. public Color color = Color.white;
  78.  
  79. public Curve()
  80. {}
  81.  
  82. public Curve(float r, float g, float b, float a) // Can't pass a struct in an attribute
  83. {
  84. color = new Color(r, g, b, a);
  85. }
  86. }
  87. #endregion
  88.  
  89. #region Settings
  90. [Serializable]
  91. public struct EyeAdaptationSettings
  92. {
  93. public bool enabled;
  94.  
  95. [Min(0f), Tooltip("Midpoint Adjustment.")]
  96. public float middleGrey;
  97.  
  98. [Tooltip("The lowest possible exposure value; adjust this value to modify the brightest areas of your level.")]
  99. public float min;
  100.  
  101. [Tooltip("The highest possible exposure value; adjust this value to modify the darkest areas of your level.")]
  102. public float max;
  103.  
  104. [Min(0f), Tooltip("Speed of linear adaptation. Higher is faster.")]
  105. public float speed;
  106.  
  107. [Tooltip("Displays a luminosity helper in the GameView.")]
  108. public bool showDebug;
  109.  
  110. public static EyeAdaptationSettings defaultSettings
  111. {
  112. get
  113. {
  114. return new EyeAdaptationSettings
  115. {
  116. enabled = false,
  117. showDebug = false,
  118. middleGrey = 0.5f,
  119. min = -3f,
  120. max = 3f,
  121. speed = 1.5f
  122. };
  123. }
  124. }
  125. }
  126.  
  127. public enum Tonemapper
  128. {
  129. ACES,
  130. Curve,
  131. Hable,
  132. HejlDawson,
  133. Photographic,
  134. Reinhard,
  135. Neutral
  136. }
  137.  
  138. [Serializable]
  139. public struct TonemappingSettings
  140. {
  141. public bool enabled;
  142.  
  143. [Tooltip("Tonemapping technique to use. ACES is the recommended one.")]
  144. public Tonemapper tonemapper;
  145.  
  146. [Min(0f), Tooltip("Adjusts the overall exposure of the scene.")]
  147. public float exposure;
  148.  
  149. [Tooltip("Custom tonemapping curve.")]
  150. public AnimationCurve curve;
  151.  
  152. // Neutral settings
  153. [Range(-0.1f, 0.1f)]
  154. public float neutralBlackIn;
  155.  
  156. [Range(1f, 20f)]
  157. public float neutralWhiteIn;
  158.  
  159. [Range(-0.09f, 0.1f)]
  160. public float neutralBlackOut;
  161.  
  162. [Range(1f, 19f)]
  163. public float neutralWhiteOut;
  164.  
  165. [Range(0.1f, 20f)]
  166. public float neutralWhiteLevel;
  167.  
  168. [Range(1f, 10f)]
  169. public float neutralWhiteClip;
  170.  
  171. public static TonemappingSettings defaultSettings
  172. {
  173. get
  174. {
  175. return new TonemappingSettings
  176. {
  177. enabled = false,
  178. tonemapper = Tonemapper.Neutral,
  179. exposure = 1f,
  180. curve = CurvesSettings.defaultCurve,
  181. neutralBlackIn = 0.02f,
  182. neutralWhiteIn = 10f,
  183. neutralBlackOut = 0f,
  184. neutralWhiteOut = 10f,
  185. neutralWhiteLevel = 5.3f,
  186. neutralWhiteClip = 10f
  187. };
  188. }
  189. }
  190. }
  191.  
  192. [Serializable]
  193. public struct LUTSettings
  194. {
  195. public bool enabled;
  196.  
  197. [Tooltip("Custom lookup texture (strip format, e.g. 256x16).")]
  198. public Texture texture;
  199.  
  200. [Range(0f, 1f), Tooltip("Blending factor.")]
  201. public float contribution;
  202.  
  203. public static LUTSettings defaultSettings
  204. {
  205. get
  206. {
  207. return new LUTSettings
  208. {
  209. enabled = false,
  210. texture = null,
  211. contribution = 1f
  212. };
  213. }
  214. }
  215. }
  216.  
  217. [Serializable]
  218. public struct ColorWheelsSettings
  219. {
  220. [ColorUsage(false)]
  221. public Color shadows;
  222.  
  223. [ColorUsage(false)]
  224. public Color midtones;
  225.  
  226. [ColorUsage(false)]
  227. public Color highlights;
  228.  
  229. public static ColorWheelsSettings defaultSettings
  230. {
  231. get
  232. {
  233. return new ColorWheelsSettings
  234. {
  235. shadows = Color.white,
  236. midtones = Color.white,
  237. highlights = Color.white
  238. };
  239. }
  240. }
  241. }
  242.  
  243. [Serializable]
  244. public struct BasicsSettings
  245. {
  246. [Range(-2f, 2f), Tooltip("Sets the white balance to a custom color temperature.")]
  247. public float temperatureShift;
  248.  
  249. [Range(-2f, 2f), Tooltip("Sets the white balance to compensate for a green or magenta tint.")]
  250. public float tint;
  251.  
  252. [Space, Range(-0.5f, 0.5f), Tooltip("Shift the hue of all colors.")]
  253. public float hue;
  254.  
  255. [Range(0f, 2f), Tooltip("Pushes the intensity of all colors.")]
  256. public float saturation;
  257.  
  258. [Range(-1f, 1f), Tooltip("Adjusts the saturation so that clipping is minimized as colors approach full saturation.")]
  259. public float vibrance;
  260.  
  261. [Range(0f, 10f), Tooltip("Brightens or darkens all colors.")]
  262. public float value;
  263.  
  264. [Space, Range(0f, 2f), Tooltip("Expands or shrinks the overall range of tonal values.")]
  265. public float contrast;
  266.  
  267. [Range(0.01f, 5f), Tooltip("Contrast gain curve. Controls the steepness of the curve.")]
  268. public float gain;
  269.  
  270. [Range(0.01f, 5f), Tooltip("Applies a pow function to the source.")]
  271. public float gamma;
  272.  
  273. public static BasicsSettings defaultSettings
  274. {
  275. get
  276. {
  277. return new BasicsSettings
  278. {
  279. temperatureShift = 0f,
  280. tint = 0f,
  281. contrast = 1f,
  282. hue = 0f,
  283. saturation = 1f,
  284. value = 1f,
  285. vibrance = 0f,
  286. gain = 1f,
  287. gamma = 1f
  288. };
  289. }
  290. }
  291. }
  292.  
  293. [Serializable]
  294. public struct ChannelMixerSettings
  295. {
  296. public int currentChannel;
  297. public Vector3[] channels;
  298.  
  299. public static ChannelMixerSettings defaultSettings
  300. {
  301. get
  302. {
  303. return new ChannelMixerSettings
  304. {
  305. currentChannel = 0,
  306. channels = new[]
  307. {
  308. new Vector3(1f, 0f, 0f),
  309. new Vector3(0f, 1f, 0f),
  310. new Vector3(0f, 0f, 1f)
  311. }
  312. };
  313. }
  314. }
  315. }
  316.  
  317. [Serializable]
  318. public struct CurvesSettings
  319. {
  320. [Curve]
  321. public AnimationCurve master;
  322.  
  323. [Curve(1f, 0f, 0f, 1f)]
  324. public AnimationCurve red;
  325.  
  326. [Curve(0f, 1f, 0f, 1f)]
  327. public AnimationCurve green;
  328.  
  329. [Curve(0f, 1f, 1f, 1f)]
  330. public AnimationCurve blue;
  331.  
  332. public static CurvesSettings defaultSettings
  333. {
  334. get
  335. {
  336. return new CurvesSettings
  337. {
  338. master = defaultCurve,
  339. red = defaultCurve,
  340. green = defaultCurve,
  341. blue = defaultCurve
  342. };
  343. }
  344. }
  345.  
  346. public static AnimationCurve defaultCurve
  347. {
  348. get { return new AnimationCurve(new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f)); }
  349. }
  350. }
  351.  
  352. public enum ColorGradingPrecision
  353. {
  354. Normal = 16,
  355. High = 32
  356. }
  357.  
  358. [Serializable]
  359. public struct ColorGradingSettings
  360. {
  361. public bool enabled;
  362.  
  363. [Tooltip("Internal LUT precision. \"Normal\" is 256x16, \"High\" is 1024x32. Prefer \"Normal\" on mobile devices.")]
  364. public ColorGradingPrecision precision;
  365.  
  366. [Space, ColorWheelGroup]
  367. public ColorWheelsSettings colorWheels;
  368.  
  369. [Space, IndentedGroup]
  370. public BasicsSettings basics;
  371.  
  372. [Space, ChannelMixer]
  373. public ChannelMixerSettings channelMixer;
  374.  
  375. [Space, IndentedGroup]
  376. public CurvesSettings curves;
  377.  
  378. [Space, Tooltip("Use dithering to try and minimize color banding in dark areas.")]
  379. public bool useDithering;
  380.  
  381. [Tooltip("Displays the generated LUT in the top left corner of the GameView.")]
  382. public bool showDebug;
  383.  
  384. public static ColorGradingSettings defaultSettings
  385. {
  386. get
  387. {
  388. return new ColorGradingSettings
  389. {
  390. enabled = false,
  391. useDithering = false,
  392. showDebug = false,
  393. precision = ColorGradingPrecision.Normal,
  394. colorWheels = ColorWheelsSettings.defaultSettings,
  395. basics = BasicsSettings.defaultSettings,
  396. channelMixer = ChannelMixerSettings.defaultSettings,
  397. curves = CurvesSettings.defaultSettings
  398. };
  399. }
  400. }
  401.  
  402. internal void Reset()
  403. {
  404. curves = CurvesSettings.defaultSettings;
  405. }
  406. }
  407.  
  408. [SerializeField, SettingsGroup]
  409. private EyeAdaptationSettings m_EyeAdaptation = EyeAdaptationSettings.defaultSettings;
  410. public EyeAdaptationSettings eyeAdaptation
  411. {
  412. get { return m_EyeAdaptation; }
  413. set { m_EyeAdaptation = value; }
  414. }
  415.  
  416. [SerializeField, SettingsGroup]
  417. private TonemappingSettings m_Tonemapping = TonemappingSettings.defaultSettings;
  418. public TonemappingSettings tonemapping
  419. {
  420. get { return m_Tonemapping; }
  421. set
  422. {
  423. m_Tonemapping = value;
  424. SetTonemapperDirty();
  425. }
  426. }
  427.  
  428. [SerializeField, SettingsGroup]
  429. private LUTSettings m_Lut = LUTSettings.defaultSettings;
  430. public LUTSettings lut
  431. {
  432. get { return m_Lut; }
  433. set
  434. {
  435. m_Lut = value;
  436. SetDirty();
  437. }
  438. }
  439.  
  440. [SerializeField, SettingsGroup]
  441. private ColorGradingSettings m_ColorGrading = ColorGradingSettings.defaultSettings;
  442. public ColorGradingSettings colorGrading
  443. {
  444. get { return m_ColorGrading; }
  445. set
  446. {
  447. m_ColorGrading = value;
  448. SetDirty();
  449. }
  450. }
  451. #endregion
  452. private Texture2D m_IdentityLut;
  453. private RenderTexture m_InternalLut;
  454. private Texture2D m_CurveTexture;
  455. private Texture2D m_TonemapperCurve;
  456. private float m_TonemapperCurveRange;
  457.  
  458. private Texture2D identityLut
  459. {
  460. get
  461. {
  462. if (m_IdentityLut == null || m_IdentityLut.height != lutSize)
  463. {
  464. DestroyImmediate(m_IdentityLut);
  465. m_IdentityLut = GenerateIdentityLut(lutSize);
  466. }
  467.  
  468. return m_IdentityLut;
  469. }
  470. }
  471.  
  472. private RenderTexture internalLutRt
  473. {
  474. get
  475. {
  476. if (m_InternalLut == null || !m_InternalLut.IsCreated() || m_InternalLut.height != lutSize)
  477. {
  478. DestroyImmediate(m_InternalLut);
  479. m_InternalLut = new RenderTexture(lutSize * lutSize, lutSize, 0, RenderTextureFormat.ARGB32)
  480. {
  481. name = "Internal LUT",
  482. filterMode = FilterMode.Bilinear,
  483. anisoLevel = 0,
  484. hideFlags = HideFlags.DontSave
  485. };
  486. }
  487.  
  488. return m_InternalLut;
  489. }
  490. }
  491.  
  492. private Texture2D curveTexture
  493. {
  494. get
  495. {
  496. if (m_CurveTexture == null)
  497. {
  498. m_CurveTexture = new Texture2D(256, 1, TextureFormat.ARGB32, false, true)
  499. {
  500. name = "Curve texture",
  501. wrapMode = TextureWrapMode.Clamp,
  502. filterMode = FilterMode.Bilinear,
  503. anisoLevel = 0,
  504. hideFlags = HideFlags.DontSave
  505. };
  506. }
  507.  
  508. return m_CurveTexture;
  509. }
  510. }
  511.  
  512. private Texture2D tonemapperCurve
  513. {
  514. get
  515. {
  516. if (m_TonemapperCurve == null)
  517. {
  518. TextureFormat format = TextureFormat.RGB24;
  519. if (SystemInfo.SupportsTextureFormat(TextureFormat.RFloat))
  520. format = TextureFormat.RFloat;
  521. else if (SystemInfo.SupportsTextureFormat(TextureFormat.RHalf))
  522. format = TextureFormat.RHalf;
  523.  
  524. m_TonemapperCurve = new Texture2D(256, 1, format, false, true)
  525. {
  526. name = "Tonemapper curve texture",
  527. wrapMode = TextureWrapMode.Clamp,
  528. filterMode = FilterMode.Bilinear,
  529. anisoLevel = 0,
  530. hideFlags = HideFlags.DontSave
  531. };
  532. }
  533.  
  534. return m_TonemapperCurve;
  535. }
  536. }
  537.  
  538. [SerializeField]
  539. private Shader m_Shader;
  540. public Shader shader
  541. {
  542. get
  543. {
  544. if (m_Shader == null)
  545. m_Shader = Shader.Find("Hidden/TonemappingColorGrading");
  546.  
  547. return m_Shader;
  548. }
  549. }
  550.  
  551. private Material m_Material;
  552. public Material material
  553. {
  554. get
  555. {
  556. if (m_Material == null)
  557. m_Material = ImageEffectHelper.CheckShaderAndCreateMaterial(shader);
  558.  
  559. return m_Material;
  560. }
  561. }
  562.  
  563. public bool isGammaColorSpace
  564. {
  565. get { return QualitySettings.activeColorSpace == ColorSpace.Gamma; }
  566. }
  567.  
  568. public int lutSize
  569. {
  570. get { return (int)colorGrading.precision; }
  571. }
  572.  
  573. private enum Pass
  574. {
  575. LutGen,
  576. AdaptationLog,
  577. AdaptationExpBlend,
  578. AdaptationExp,
  579. TonemappingOff,
  580. TonemappingACES,
  581. TonemappingCurve,
  582. TonemappingHable,
  583. TonemappingHejlDawson,
  584. TonemappingPhotographic,
  585. TonemappingReinhard,
  586. TonemappingNeutral,
  587. AdaptationDebug
  588. }
  589.  
  590. public bool validRenderTextureFormat { get; private set; }
  591. public bool validUserLutSize { get; private set; }
  592.  
  593. private bool m_Dirty = true;
  594. private bool m_TonemapperDirty = true;
  595.  
  596. private RenderTexture m_SmallAdaptiveRt;
  597. private RenderTextureFormat m_AdaptiveRtFormat;
  598.  
  599. public void SetDirty()
  600. {
  601. m_Dirty = true;
  602. }
  603.  
  604. public void SetTonemapperDirty()
  605. {
  606. m_TonemapperDirty = true;
  607. }
  608.  
  609. private void OnEnable()
  610. {
  611. if (!ImageEffectHelper.IsSupported(shader, false, true, this))
  612. {
  613. enabled = false;
  614. return;
  615. }
  616.  
  617. SetDirty();
  618. SetTonemapperDirty();
  619. }
  620.  
  621. private void OnDisable()
  622. {
  623. if (m_Material != null)
  624. DestroyImmediate(m_Material);
  625.  
  626. if (m_IdentityLut != null)
  627. DestroyImmediate(m_IdentityLut);
  628.  
  629. if (m_InternalLut != null)
  630. DestroyImmediate(internalLutRt);
  631.  
  632. if (m_SmallAdaptiveRt != null)
  633. DestroyImmediate(m_SmallAdaptiveRt);
  634.  
  635. if (m_CurveTexture != null)
  636. DestroyImmediate(m_CurveTexture);
  637.  
  638. if (m_TonemapperCurve != null)
  639. DestroyImmediate(m_TonemapperCurve);
  640.  
  641. m_Material = null;
  642. m_IdentityLut = null;
  643. m_InternalLut = null;
  644. m_SmallAdaptiveRt = null;
  645. m_CurveTexture = null;
  646. m_TonemapperCurve = null;
  647. }
  648.  
  649. private void OnValidate()
  650. {
  651. SetDirty();
  652. SetTonemapperDirty();
  653. }
  654.  
  655. private static Texture2D GenerateIdentityLut(int dim)
  656. {
  657. Color[] newC = new Color[dim * dim * dim];
  658. float oneOverDim = 1f / ((float)dim - 1f);
  659.  
  660. for (int i = 0; i < dim; i++)
  661. for (int j = 0; j < dim; j++)
  662. for (int k = 0; k < dim; k++)
  663. newC[i + (j * dim) + (k * dim * dim)] = new Color((float)i * oneOverDim, Mathf.Abs((float)k * oneOverDim), (float)j * oneOverDim, 1f);
  664.  
  665. Texture2D tex2D = new Texture2D(dim * dim, dim, TextureFormat.RGB24, false, true)
  666. {
  667. name = "Identity LUT",
  668. filterMode = FilterMode.Bilinear,
  669. anisoLevel = 0,
  670. hideFlags = HideFlags.DontSave
  671. };
  672. tex2D.SetPixels(newC);
  673. tex2D.Apply();
  674.  
  675. return tex2D;
  676. }
  677.  
  678. // An analytical model of chromaticity of the standard illuminant, by Judd et al.
  679. // http://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_series_D
  680. // Slightly modifed to adjust it with the D65 white point (x=0.31271, y=0.32902).
  681. private float StandardIlluminantY(float x)
  682. {
  683. return 2.87f * x - 3f * x * x - 0.27509507f;
  684. }
  685.  
  686. // CIE xy chromaticity to CAT02 LMS.
  687. // http://en.wikipedia.org/wiki/LMS_color_space#CAT02
  688. private Vector3 CIExyToLMS(float x, float y)
  689. {
  690. float Y = 1f;
  691. float X = Y * x / y;
  692. float Z = Y * (1f - x - y) / y;
  693.  
  694. float L = 0.7328f * X + 0.4296f * Y - 0.1624f * Z;
  695. float M = -0.7036f * X + 1.6975f * Y + 0.0061f * Z;
  696. float S = 0.0030f * X + 0.0136f * Y + 0.9834f * Z;
  697.  
  698. return new Vector3(L, M, S);
  699. }
  700.  
  701. private Vector3 GetWhiteBalance()
  702. {
  703. float t1 = colorGrading.basics.temperatureShift;
  704. float t2 = colorGrading.basics.tint;
  705.  
  706. // Get the CIE xy chromaticity of the reference white point.
  707. // Note: 0.31271 = x value on the D65 white point
  708. float x = 0.31271f - t1 * (t1 < 0f ? 0.1f : 0.05f);
  709. float y = StandardIlluminantY(x) + t2 * 0.05f;
  710.  
  711. // Calculate the coefficients in the LMS space.
  712. Vector3 w1 = new Vector3(0.949237f, 1.03542f, 1.08728f); // D65 white point
  713. Vector3 w2 = CIExyToLMS(x, y);
  714. return new Vector3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);
  715. }
  716.  
  717. private static Color NormalizeColor(Color c)
  718. {
  719. float sum = (c.r + c.g + c.b) / 3f;
  720.  
  721. if (Mathf.Approximately(sum, 0f))
  722. return new Color(1f, 1f, 1f, 1f);
  723.  
  724. return new Color
  725. {
  726. r = c.r / sum,
  727. g = c.g / sum,
  728. b = c.b / sum,
  729. a = 1f
  730. };
  731. }
  732.  
  733. private void GenerateLiftGammaGain(out Color lift, out Color gamma, out Color gain)
  734. {
  735. Color nLift = NormalizeColor(colorGrading.colorWheels.shadows);
  736. Color nGamma = NormalizeColor(colorGrading.colorWheels.midtones);
  737. Color nGain = NormalizeColor(colorGrading.colorWheels.highlights);
  738.  
  739. float avgLift = (nLift.r + nLift.g + nLift.b) / 3f;
  740. float avgGamma = (nGamma.r + nGamma.g + nGamma.b) / 3f;
  741. float avgGain = (nGain.r + nGain.g + nGain.b) / 3f;
  742.  
  743. // Magic numbers
  744. const float liftScale = 0.1f;
  745. const float gammaScale = 0.5f;
  746. const float gainScale = 0.5f;
  747.  
  748. float liftR = (nLift.r - avgLift) * liftScale;
  749. float liftG = (nLift.g - avgLift) * liftScale;
  750. float liftB = (nLift.b - avgLift) * liftScale;
  751.  
  752. float gammaR = Mathf.Pow(2f, (nGamma.r - avgGamma) * gammaScale);
  753. float gammaG = Mathf.Pow(2f, (nGamma.g - avgGamma) * gammaScale);
  754. float gammaB = Mathf.Pow(2f, (nGamma.b - avgGamma) * gammaScale);
  755.  
  756. float gainR = Mathf.Pow(2f, (nGain.r - avgGain) * gainScale);
  757. float gainG = Mathf.Pow(2f, (nGain.g - avgGain) * gainScale);
  758. float gainB = Mathf.Pow(2f, (nGain.b - avgGain) * gainScale);
  759.  
  760. const float minGamma = 0.01f;
  761. float invGammaR = 1f / Mathf.Max(minGamma, gammaR);
  762. float invGammaG = 1f / Mathf.Max(minGamma, gammaG);
  763. float invGammaB = 1f / Mathf.Max(minGamma, gammaB);
  764.  
  765. lift = new Color(liftR, liftG, liftB);
  766. gamma = new Color(invGammaR, invGammaG, invGammaB);
  767. gain = new Color(gainR, gainG, gainB);
  768. }
  769.  
  770. private void GenCurveTexture()
  771. {
  772. AnimationCurve master = colorGrading.curves.master;
  773. AnimationCurve red = colorGrading.curves.red;
  774. AnimationCurve green = colorGrading.curves.green;
  775. AnimationCurve blue = colorGrading.curves.blue;
  776.  
  777. Color[] pixels = new Color[256];
  778.  
  779. for (float i = 0f; i <= 1f; i += 1f / 255f)
  780. {
  781. float m = Mathf.Clamp(master.Evaluate(i), 0f, 1f);
  782. float r = Mathf.Clamp(red.Evaluate(i), 0f, 1f);
  783. float g = Mathf.Clamp(green.Evaluate(i), 0f, 1f);
  784. float b = Mathf.Clamp(blue.Evaluate(i), 0f, 1f);
  785. pixels[(int)Mathf.Floor(i * 255f)] = new Color(r, g, b, m);
  786. }
  787.  
  788. curveTexture.SetPixels(pixels);
  789. curveTexture.Apply();
  790. }
  791.  
  792. private bool CheckUserLut()
  793. {
  794. validUserLutSize = (lut.texture.height == (int)Mathf.Sqrt(lut.texture.width));
  795. return validUserLutSize;
  796. }
  797.  
  798. private bool CheckSmallAdaptiveRt()
  799. {
  800. if (m_SmallAdaptiveRt != null)
  801. return false;
  802.  
  803. m_AdaptiveRtFormat = RenderTextureFormat.ARGBHalf;
  804.  
  805. if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf))
  806. m_AdaptiveRtFormat = RenderTextureFormat.RGHalf;
  807.  
  808. m_SmallAdaptiveRt = new RenderTexture(1, 1, 0, m_AdaptiveRtFormat);
  809. m_SmallAdaptiveRt.hideFlags = HideFlags.DontSave;
  810.  
  811. return true;
  812. }
  813.  
  814. private void OnGUI()
  815. {
  816. if (Event.current.type != EventType.Repaint)
  817. return;
  818.  
  819. int yoffset = 0;
  820.  
  821. // Color grading debug
  822. if (m_InternalLut != null && colorGrading.enabled && colorGrading.showDebug)
  823. {
  824. Graphics.DrawTexture(new Rect(0f, yoffset, lutSize * lutSize, lutSize), internalLutRt);
  825. yoffset += lutSize;
  826. }
  827.  
  828. // Eye Adaptation debug
  829. if (m_SmallAdaptiveRt != null && eyeAdaptation.enabled && eyeAdaptation.showDebug)
  830. {
  831. m_Material.SetPass((int)Pass.AdaptationDebug);
  832. Graphics.DrawTexture(new Rect(0f, yoffset, 256, 16), m_SmallAdaptiveRt, m_Material);
  833. }
  834. }
  835.  
  836. [ImageEffectTransformsToLDR]
  837. private void OnRenderImage(RenderTexture source, RenderTexture destination)
  838. {
  839. #if UNITY_EDITOR
  840. validRenderTextureFormat = true;
  841.  
  842. if (source.format != RenderTextureFormat.ARGBHalf && source.format != RenderTextureFormat.ARGBFloat)
  843. validRenderTextureFormat = false;
  844. #endif
  845. material.shaderKeywords = null;
  846.  
  847. Texture lutUsed = null;
  848. float lutContrib = 1f;
  849.  
  850. RenderTexture rtSquared = null;
  851. RenderTexture[] rts = null;
  852.  
  853. if (eyeAdaptation.enabled)
  854. {
  855. bool freshlyBrewedSmallRt = CheckSmallAdaptiveRt();
  856. int srcSize = source.width < source.height ? source.width : source.height;
  857.  
  858. // Fast lower or equal power of 2
  859. int adaptiveSize = srcSize;
  860. adaptiveSize |= (adaptiveSize >> 1);
  861. adaptiveSize |= (adaptiveSize >> 2);
  862. adaptiveSize |= (adaptiveSize >> 4);
  863. adaptiveSize |= (adaptiveSize >> 8);
  864. adaptiveSize |= (adaptiveSize >> 16);
  865. adaptiveSize -= (adaptiveSize >> 1);
  866.  
  867. rtSquared = RenderTexture.GetTemporary(adaptiveSize, adaptiveSize, 0, m_AdaptiveRtFormat);
  868. Graphics.Blit(source, rtSquared);
  869.  
  870. int downsample = (int)Mathf.Log(rtSquared.width, 2f);
  871.  
  872. int div = 2;
  873. rts = new RenderTexture[downsample];
  874. for (int i = 0; i < downsample; i++)
  875. {
  876. rts[i] = RenderTexture.GetTemporary(rtSquared.width / div, rtSquared.width / div, 0, m_AdaptiveRtFormat);
  877. div <<= 1;
  878. }
  879.  
  880. // Downsample pyramid
  881. var lumRt = rts[downsample - 1];
  882. Graphics.Blit(rtSquared, rts[0], material, (int)Pass.AdaptationLog);
  883. for (int i = 0; i < downsample - 1; i++)
  884. {
  885. Graphics.Blit(rts[i], rts[i + 1]);
  886. lumRt = rts[i + 1];
  887. }
  888.  
  889. // Keeping luminance values between frames, RT restore expected
  890. m_SmallAdaptiveRt.MarkRestoreExpected();
  891.  
  892. material.SetFloat("_AdaptationSpeed", Mathf.Max(eyeAdaptation.speed, 0.001f));
  893.  
  894. #if UNITY_EDITOR
  895. if (Application.isPlaying && !freshlyBrewedSmallRt)
  896. Graphics.Blit(lumRt, m_SmallAdaptiveRt, material, (int)Pass.AdaptationExpBlend);
  897. else
  898. Graphics.Blit(lumRt, m_SmallAdaptiveRt, material, (int)Pass.AdaptationExp);
  899. #else
  900. Graphics.Blit(lumRt, m_SmallAdaptiveRt, material, freshlyBrewedSmallRt ? (int)Pass.AdaptationExp : (int)Pass.AdaptationExpBlend);
  901. #endif
  902.  
  903. material.SetFloat("_MiddleGrey", eyeAdaptation.middleGrey);
  904. material.SetFloat("_AdaptationMin", Mathf.Pow(2f, eyeAdaptation.min));
  905. material.SetFloat("_AdaptationMax", Mathf.Pow(2f, eyeAdaptation.max));
  906. material.SetTexture("_LumTex", m_SmallAdaptiveRt);
  907. material.EnableKeyword("ENABLE_EYE_ADAPTATION");
  908. }
  909.  
  910. int renderPass = (int)Pass.TonemappingOff;
  911.  
  912. if (tonemapping.enabled)
  913. {
  914. if (tonemapping.tonemapper == Tonemapper.Curve)
  915. {
  916. if (m_TonemapperDirty)
  917. {
  918. float range = 1f;
  919.  
  920. if (tonemapping.curve.length > 0)
  921. {
  922. range = tonemapping.curve[tonemapping.curve.length - 1].time;
  923.  
  924. for (float i = 0f; i <= 1f; i += 1f / 255f)
  925. {
  926. float c = tonemapping.curve.Evaluate(i * range);
  927. tonemapperCurve.SetPixel(Mathf.FloorToInt(i * 255f), 0, new Color(c, c, c));
  928. }
  929.  
  930. tonemapperCurve.Apply();
  931. }
  932.  
  933. m_TonemapperCurveRange = 1f / range;
  934. m_TonemapperDirty = false;
  935. }
  936.  
  937. material.SetFloat("_ToneCurveRange", m_TonemapperCurveRange);
  938. material.SetTexture("_ToneCurve", tonemapperCurve);
  939. }
  940. else if (tonemapping.tonemapper == Tonemapper.Neutral)
  941. {
  942. const float scaleFactor = 20f;
  943. const float scaleFactorHalf = scaleFactor * 0.5f;
  944.  
  945. float inBlack = tonemapping.neutralBlackIn * scaleFactor + 1f;
  946. float outBlack = tonemapping.neutralBlackOut * scaleFactorHalf + 1f;
  947. float inWhite = tonemapping.neutralWhiteIn / scaleFactor;
  948. float outWhite = 1f - tonemapping.neutralWhiteOut / scaleFactor;
  949. float blackRatio = inBlack / outBlack;
  950. float whiteRatio = inWhite / outWhite;
  951.  
  952. const float a = 0.2f;
  953. float b = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, blackRatio));
  954. float c = Mathf.LerpUnclamped(0.01f, 0.24f, whiteRatio);
  955. float d = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.20f, blackRatio));
  956. const float e = 0.02f;
  957. const float f = 0.30f;
  958.  
  959. material.SetVector("_NeutralTonemapperParams1", new Vector4(a, b, c, d));
  960. material.SetVector("_NeutralTonemapperParams2", new Vector4(e, f, tonemapping.neutralWhiteLevel, tonemapping.neutralWhiteClip / scaleFactorHalf));
  961. }
  962.  
  963. material.SetFloat("_Exposure", tonemapping.exposure);
  964. renderPass += (int)tonemapping.tonemapper + 1;
  965. }
  966.  
  967. if (lut.enabled)
  968. {
  969. Texture tex = lut.texture;
  970.  
  971. if (lut.texture == null || !CheckUserLut())
  972. tex = identityLut;
  973.  
  974. lutUsed = tex;
  975. lutContrib = lut.contribution;
  976. material.EnableKeyword("ENABLE_COLOR_GRADING");
  977. }
  978.  
  979. if (colorGrading.enabled)
  980. {
  981. if (m_Dirty || !m_InternalLut.IsCreated())
  982. {
  983. if (lutUsed == null)
  984. {
  985. material.SetVector("_UserLutParams", new Vector4(1f / identityLut.width, 1f / identityLut.height, identityLut.height - 1f, 1f));
  986. material.SetTexture("_UserLutTex", identityLut);
  987. }
  988. else
  989. {
  990. material.SetVector("_UserLutParams", new Vector4(1f / lutUsed.width, 1f / lutUsed.height, lutUsed.height - 1f, lut.contribution));
  991. material.SetTexture("_UserLutTex", lutUsed);
  992. }
  993.  
  994. Color lift, gamma, gain;
  995. GenerateLiftGammaGain(out lift, out gamma, out gain);
  996. GenCurveTexture();
  997.  
  998. material.SetVector("_WhiteBalance", GetWhiteBalance());
  999. material.SetVector("_Lift", lift);
  1000. material.SetVector("_Gamma", gamma);
  1001. material.SetVector("_Gain", gain);
  1002. material.SetVector("_ContrastGainGamma", new Vector3(colorGrading.basics.contrast, colorGrading.basics.gain, 1f / colorGrading.basics.gamma));
  1003. material.SetFloat("_Vibrance", colorGrading.basics.vibrance);
  1004. material.SetVector("_HSV", new Vector4(colorGrading.basics.hue, colorGrading.basics.saturation, colorGrading.basics.value));
  1005. material.SetVector("_ChannelMixerRed", colorGrading.channelMixer.channels[0]);
  1006. material.SetVector("_ChannelMixerGreen", colorGrading.channelMixer.channels[1]);
  1007. material.SetVector("_ChannelMixerBlue", colorGrading.channelMixer.channels[2]);
  1008. material.SetTexture("_CurveTex", curveTexture);
  1009. internalLutRt.MarkRestoreExpected();
  1010. Graphics.Blit(identityLut, internalLutRt, material, (int)Pass.LutGen);
  1011. m_Dirty = false;
  1012. }
  1013.  
  1014. lutUsed = internalLutRt;
  1015. lutContrib = 1f;
  1016. material.EnableKeyword("ENABLE_COLOR_GRADING");
  1017.  
  1018. if (colorGrading.useDithering)
  1019. material.EnableKeyword("ENABLE_DITHERING");
  1020. }
  1021.  
  1022. if (lutUsed != null)
  1023. {
  1024. material.SetTexture("_LutTex", lutUsed);
  1025. material.SetVector("_LutParams", new Vector4(1f / lutUsed.width, 1f / lutUsed.height, lutUsed.height - 1f, lutContrib));
  1026. }
  1027.  
  1028. Graphics.Blit(source, destination, material, renderPass);
  1029.  
  1030. // Cleanup for eye adaptation
  1031. if (eyeAdaptation.enabled)
  1032. {
  1033. for (int i = 0; i < rts.Length; i++)
  1034. RenderTexture.ReleaseTemporary(rts[i]);
  1035.  
  1036. RenderTexture.ReleaseTemporary(rtSquared);
  1037. }
  1038.  
  1039. #if UNITY_EDITOR
  1040. // If we have an on frame end callabck we need to pass a valid result texture
  1041. // if destination is null we wrote to the backbuffer so we need to copy that out.
  1042. // It's slow and not amazing, but editor only
  1043. if (onFrameEndEditorOnly != null)
  1044. {
  1045. if (destination == null)
  1046. {
  1047. RenderTexture rt = RenderTexture.GetTemporary(source.width, source.height, 0);
  1048. Graphics.Blit(source, rt, material, renderPass);
  1049. onFrameEndEditorOnly(rt);
  1050. RenderTexture.ReleaseTemporary(rt);
  1051. RenderTexture.active = null;
  1052. }
  1053. else
  1054. {
  1055. onFrameEndEditorOnly(destination);
  1056. }
  1057. }
  1058. #endif
  1059. }
  1060.  
  1061. public Texture2D BakeLUT()
  1062. {
  1063. Texture2D lut = new Texture2D(internalLutRt.width, internalLutRt.height, TextureFormat.RGB24, false, true);
  1064. RenderTexture.active = internalLutRt;
  1065. lut.ReadPixels(new Rect(0f, 0f, lut.width, lut.height), 0, 0);
  1066. RenderTexture.active = null;
  1067. return lut;
  1068. }
  1069. }
  1070. }
  1071.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement