반응형
출처 : https://github.com/keijiro/ColorSuite
using UnityEngine; using System.Collections; [ExecuteInEditMode] [ImageEffectTransformsToLDR] [RequireComponent(typeof(Camera))] [AddComponentMenu("Image Effects/Color Adjustments/Color Suite")] public class ColorSuite : MonoBehaviour { #region Public Properties // White balance. [SerializeField] float _colorTemp = 0.0f; [SerializeField] float _colorTint = 0.0f; public float colorTemp { get { return _colorTemp; } set { _colorTemp = value; } } public float colorTint { get { return _colorTint; } set { _colorTint = value; } } // Tone mapping. [SerializeField] bool _toneMapping = false; [SerializeField] float _exposure = 1.0f; public bool toneMapping { get { return _toneMapping; } set { _toneMapping = value; } } public float exposure { get { return _exposure; } set { _exposure = value; } } // Color saturation. [SerializeField] float _saturation = 1.0f; public float saturation { get { return _saturation; } set { _saturation = value; } } // Curves. [SerializeField] AnimationCurve _rCurve = AnimationCurve.Linear(0, 0, 1, 1); [SerializeField] AnimationCurve _gCurve = AnimationCurve.Linear(0, 0, 1, 1); [SerializeField] AnimationCurve _bCurve = AnimationCurve.Linear(0, 0, 1, 1); [SerializeField] AnimationCurve _cCurve = AnimationCurve.Linear(0, 0, 1, 1); public AnimationCurve redCurve { get { return _rCurve; } set { _rCurve = value; UpdateLUT(); } } public AnimationCurve greenCurve { get { return _gCurve; } set { _gCurve = value; UpdateLUT(); } } public AnimationCurve blueCurve { get { return _bCurve; } set { _bCurve = value; UpdateLUT(); } } public AnimationCurve rgbCurve { get { return _cCurve; } set { _cCurve = value; UpdateLUT(); } } // Dithering. public enum DitherMode { Off, Ordered, Triangular } [SerializeField] DitherMode _ditherMode = DitherMode.Off; public DitherMode ditherMode { get { return _ditherMode; } set { _ditherMode = value; } } #endregion #region Internal Properties // Reference to the shader. [SerializeField] Shader shader; // Temporary objects. Material _material; Texture2D _lutTexture; #endregion #region Local Functions // RGBM encoding. static Color EncodeRGBM(float r, float g, float b) { var a = Mathf.Max(Mathf.Max(r, g), Mathf.Max(b, 1e-6f)); a = Mathf.Ceil(a * 255) / 255; return new Color(r / a, g / a, b / a, a); } // An analytical model of chromaticity of the standard illuminant, by Judd et al. // http://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_series_D // Slightly modifed to adjust it with the D65 white point (x=0.31271, y=0.32902). static float StandardIlluminantY(float x) { return 2.87f * x - 3.0f * x * x - 0.27509507f; } // CIE xy chromaticity to CAT02 LMS. // http://en.wikipedia.org/wiki/LMS_color_space#CAT02 static Vector3 CIExyToLMS(float x, float y) { var Y = 1.0f; var X = Y * x / y; var Z = Y * (1.0f - x - y) / y; var L = 0.7328f * X + 0.4296f * Y - 0.1624f * Z; var M = -0.7036f * X + 1.6975f * Y + 0.0061f * Z; var S = 0.0030f * X + 0.0136f * Y + 0.9834f * Z; return new Vector3(L, M, S); } #endregion #region Private Methods // Set up the temporary assets. void Setup() { if (_material == null) { _material = new Material(shader); _material.hideFlags = HideFlags.DontSave; } if (_lutTexture == null) { _lutTexture = new Texture2D(512, 1, TextureFormat.ARGB32, false, true); _lutTexture.hideFlags = HideFlags.DontSave; _lutTexture.wrapMode = TextureWrapMode.Clamp; UpdateLUT(); } } // Update the LUT texture. void UpdateLUT() { for (var x = 0; x < _lutTexture.width; x++) { var u = 1.0f / (_lutTexture.width - 1) * x; var r = _cCurve.Evaluate(_rCurve.Evaluate(u)); var g = _cCurve.Evaluate(_gCurve.Evaluate(u)); var b = _cCurve.Evaluate(_bCurve.Evaluate(u)); _lutTexture.SetPixel(x, 0, EncodeRGBM(r, g, b)); } _lutTexture.Apply(); } // Calculate the color balance coefficients. Vector3 CalculateColorBalance() { // Get the CIE xy chromaticity of the reference white point. // Note: 0.31271 = x value on the D65 white point var x = 0.31271f - _colorTemp * (_colorTemp < 0.0f ? 0.1f : 0.05f); var y = StandardIlluminantY(x) + _colorTint * 0.05f; // Calculate the coefficients in the LMS space. var w1 = new Vector3(0.949237f, 1.03542f, 1.08728f); // D65 white point var w2 = CIExyToLMS(x, y); return new Vector3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z); } #endregion #region Monobehaviour Functions void Start() { Setup(); } void OnValidate() { Setup(); UpdateLUT(); } void Reset() { Setup(); UpdateLUT(); } void OnRenderImage(RenderTexture source, RenderTexture destination) { var linear = QualitySettings.activeColorSpace == ColorSpace.Linear; Setup(); if (linear) _material.EnableKeyword("COLORSPACE_LINEAR"); else _material.DisableKeyword("COLORSPACE_LINEAR"); if (_colorTemp != 0.0f || _colorTint != 0.0f) { _material.EnableKeyword("BALANCING_ON"); _material.SetVector("_Balance", CalculateColorBalance()); } else _material.DisableKeyword("BALANCING_ON"); if (_toneMapping && linear) { _material.EnableKeyword("TONEMAPPING_ON"); _material.SetFloat("_Exposure", _exposure); } else _material.DisableKeyword("TONEMAPPING_ON"); _material.SetTexture("_Curves", _lutTexture); _material.SetFloat("_Saturation", _saturation); if (_ditherMode == DitherMode.Ordered) { _material.EnableKeyword("DITHER_ORDERED"); _material.DisableKeyword("DITHER_TRIANGULAR"); } else if (_ditherMode == DitherMode.Triangular) { _material.DisableKeyword("DITHER_ORDERED"); _material.EnableKeyword("DITHER_TRIANGULAR"); } else { _material.DisableKeyword("DITHER_ORDERED"); _material.DisableKeyword("DITHER_TRIANGULAR"); } Graphics.Blit(source, destination, _material); } #endregion } |
- EncodeRGBM():
→ 큰 범위의 색을 RGBM 포맷으로 인코딩 (HDR 값을 LDR로 저장할 때 사용). - StandardIlluminantY():
→ 색온도에 따른 Y좌표를 계산 (표준 조명 모델 기반). - CIExyToLMS():
→ CIE xy 색공간을 LMS 색공간으로 변환 (화이트 밸런스 조정용 수학).
- 시작 시 Setup() 호출.
- OnValidate(), Reset() : Inspector 값이 수정되거나 리셋될 때 LUT 업데이트.
- OnRenderImage(RenderTexture source, RenderTexture destination) : 카메라 렌더링 결과인 source를 가져와서 Shader를 적용하고 destination으로 넘기고, 각 기능별로 Shader 키워드를 설정하여 조건별로 다른 효과를 켜거나 끔.
반응형
'Technical Report > Unity' 카테고리의 다른 글
Unity 5.5 texture option (0) | 2016.12.18 |
---|---|
Unity Graphics hardware capabilities and emulation (0) | 2016.09.05 |
Unity sprite texture shader (0) | 2016.08.09 |
Unity Attribetes (0) | 2016.07.18 |
UE4 25 tips for Unreal Engine 4(2) (0) | 2016.07.10 |