float EvalFilmicHelper(float srcR, float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW) { // figure out the linear value of this 3d texel float dstR = LutToLin(srcR, lutA); if (enableFilmicCurve) { // we could allow this to be customized, but most people probably // would not understand it and it would just create complexity. // 18% grey is the standard film reference grey so let's just go with that. float linRef = .18f; dstR = LogContrast(dstR, linRef, lutContrast); SimplePolyFunc polyR = polyToe; if (dstR >= x0) { polyR = polyLinear; } if (dstR >= x1) { polyR = polyShoulder; } dstR = Mathf.Min(dstR, linearW); dstR = polyR.Eval(dstR); } return(dstR); }
void CreateFilmicCurveHelper(float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW, float liftR, float invGammaR, float gainR, float liftG, float invGammaG, float gainG, float liftB, float invGammaB, float gainB) { int curveLen = 128; Color[] newC = new Color[curveLen * 2]; float oneOverDim = 1.0f / (1.0f * curveLen - 1.0f); for (int i = 0; i < curveLen; i++) { float srcR = (i * 1.0f) * oneOverDim; float srcG = (i * 1.0f) * oneOverDim; float srcB = (i * 1.0f) * oneOverDim; float dstR = EvalFilmicHelper(srcR, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstG = EvalFilmicHelper(srcG, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstB = EvalFilmicHelper(srcB, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); // enable lut if (enableUserLut) { Color c = SampleLutLinear(dstR, dstG, dstB); dstR = c.r; dstG = c.g; dstB = c.b; } dstR = EvalCurveGradingHelper(dstR, liftR, invGammaR, gainR); dstG = EvalCurveGradingHelper(dstG, liftG, invGammaG, gainG); dstB = EvalCurveGradingHelper(dstB, liftB, invGammaB, gainB); if (enableColorGrading) { // saturation float midVal = (dstR + dstG + dstB) / 3.0f; dstR = midVal + (dstR - midVal) * lutSaturation; dstG = midVal + (dstG - midVal) * lutSaturation; dstB = midVal + (dstB - midVal) * lutSaturation; } dstR = Mathf.LinearToGammaSpace(dstR); dstG = Mathf.LinearToGammaSpace(dstG); dstB = Mathf.LinearToGammaSpace(dstB); newC[i + 0 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); newC[i + 1 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); } if (lutCurveTex1D) DestroyImmediate(lutCurveTex1D); lutCurveTex1D = new Texture2D(curveLen, 2, TextureFormat.ARGB32, false); lutCurveTex1D.filterMode = FilterMode.Bilinear; lutCurveTex1D.wrapMode = TextureWrapMode.Clamp; lutCurveTex1D.hideFlags = HideFlags.DontSave; lutCurveTex1D.SetPixels(newC); lutCurveTex1D.Apply(); }
float EvalFilmicHelper(float srcR, float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW) { // figure out the linear value of this 3d texel float dstR = LutToLin(srcR, lutA); if (enableFilmicCurve) { // we could allow this to be customized, but most people probably // would not understand it and it would just create complexity. // 18% grey is the standard film reference grey so let's just go with that. float linRef = .18f; dstR = LogContrast(dstR, linRef, lutContrast); SimplePolyFunc polyR = polyToe; if (dstR >= x0) polyR = polyLinear; if (dstR >= x1) polyR = polyShoulder; dstR = Mathf.Min(dstR, linearW); dstR = polyR.Eval(dstR); } return dstR; }
void CreateFilmicCurveHelper(float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW, float liftR, float invGammaR, float gainR, float liftG, float invGammaG, float gainG, float liftB, float invGammaB, float gainB) { int curveLen = 128; Color[] newC = new Color[curveLen * 2]; float oneOverDim = 1.0f / (1.0f * curveLen - 1.0f); for (int i = 0; i < curveLen; i++) { float srcR = (i * 1.0f) * oneOverDim; float srcG = (i * 1.0f) * oneOverDim; float srcB = (i * 1.0f) * oneOverDim; float dstR = EvalFilmicHelper(srcR, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstG = EvalFilmicHelper(srcG, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstB = EvalFilmicHelper(srcB, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); // enable lut if (enableUserLut) { Color c = SampleLutLinear(dstR, dstG, dstB); dstR = c.r; dstG = c.g; dstB = c.b; } dstR = EvalCurveGradingHelper(dstR, liftR, invGammaR, gainR); dstG = EvalCurveGradingHelper(dstG, liftG, invGammaG, gainG); dstB = EvalCurveGradingHelper(dstB, liftB, invGammaB, gainB); if (enableColorGrading) { // saturation float midVal = (dstR + dstG + dstB) / 3.0f; dstR = midVal + (dstR - midVal) * lutSaturation; dstG = midVal + (dstG - midVal) * lutSaturation; dstB = midVal + (dstB - midVal) * lutSaturation; } dstR = Mathf.LinearToGammaSpace(dstR); dstG = Mathf.LinearToGammaSpace(dstG); dstB = Mathf.LinearToGammaSpace(dstB); newC[i + 0 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); newC[i + 1 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); } if (lutCurveTex1D) { DestroyImmediate(lutCurveTex1D); } lutCurveTex1D = new Texture2D(curveLen, 2, TextureFormat.ARGB32, false); lutCurveTex1D.filterMode = FilterMode.Bilinear; lutCurveTex1D.wrapMode = TextureWrapMode.Clamp; lutCurveTex1D.hideFlags = HideFlags.DontSave; lutCurveTex1D.SetPixels(newC); lutCurveTex1D.Apply(); }
void Create1DLut(float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW, float liftR, float invGammaR, float gainR, float liftG, float invGammaG, float gainG, float liftB, float invGammaB, float gainB) { int curveLen = 128; Color[] newC = new Color[curveLen * 2]; float oneOverDim = 1.0f / (1.0f * curveLen - 1.0f); for (int i = 0; i < curveLen; i++) { float srcR = (i * 1.0f) * oneOverDim; float srcG = (i * 1.0f) * oneOverDim; float srcB = (i * 1.0f) * oneOverDim; float dstR = EvalFilmicHelper(srcR, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstG = EvalFilmicHelper(srcG, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstB = EvalFilmicHelper(srcB, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); Color c = SampleLutLinear(dstR, dstG, dstB); dstR = c.r; dstG = c.g; dstB = c.b; dstR = EvalCurveGradingHelper(dstR, liftR, invGammaR, gainR); dstG = EvalCurveGradingHelper(dstG, liftG, invGammaG, gainG); dstB = EvalCurveGradingHelper(dstB, liftB, invGammaB, gainB); // Saturation is done in the shader as it can't be baked into color curves if (isLinearColorSpace) { dstR = Mathf.LinearToGammaSpace(dstR); dstG = Mathf.LinearToGammaSpace(dstG); dstB = Mathf.LinearToGammaSpace(dstB); } newC[i + 0 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); newC[i + 1 * curveLen] = new Color(dstR, dstG, dstB, 1.0f); } if (m_LutCurveTex1D == null) { m_LutCurveTex1D = new Texture2D(curveLen, 2, TextureFormat.RGB24, false); m_LutCurveTex1D.filterMode = FilterMode.Bilinear; m_LutCurveTex1D.wrapMode = TextureWrapMode.Clamp; m_LutCurveTex1D.hideFlags = HideFlags.DontSave; } m_LutCurveTex1D.SetPixels(newC); m_LutCurveTex1D.Apply(); }
void Create3DLut(float lutA, SimplePolyFunc polyToe, SimplePolyFunc polyLinear, SimplePolyFunc polyShoulder, float x0, float x1, float linearW, float liftR, float invGammaR, float gainR, float liftG, float invGammaG, float gainG, float liftB, float invGammaB, float gainB) { int dim = 32; Color[] newC = new Color[dim * dim * dim]; float oneOverDim = 1.0f / (1.0f * dim - 1.0f); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { float srcR = (i * 1.0f) * oneOverDim; float srcG = (j * 1.0f) * oneOverDim; float srcB = (k * 1.0f) * oneOverDim; float dstR = EvalFilmicHelper(srcR, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstG = EvalFilmicHelper(srcG, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstB = EvalFilmicHelper(srcB, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); Color c = SampleLutLinear(dstR, dstG, dstB); dstR = c.r; dstG = c.g; dstB = c.b; dstR = EvalCurveGradingHelper(dstR, liftR, invGammaR, gainR); dstG = EvalCurveGradingHelper(dstG, liftG, invGammaG, gainG); dstB = EvalCurveGradingHelper(dstB, liftB, invGammaB, gainB); if (m_ColorGrading.enabled) { // Saturation float lum = dstR * 0.2125f + dstG * 0.7154f + dstB * 0.0721f; dstR = lum + (dstR - lum) * m_ColorGrading.saturation; dstG = lum + (dstG - lum) * m_ColorGrading.saturation; dstB = lum + (dstB - lum) * m_ColorGrading.saturation; } newC[i + (j * dim) + (k * dim * dim)] = new Color(dstR, dstG, dstB, 1.0f); } } } if (m_LutTex == null) { m_LutTex = new Texture3D(dim, dim, dim, TextureFormat.RGB24, false); m_LutTex.filterMode = FilterMode.Bilinear; m_LutTex.wrapMode = TextureWrapMode.Clamp; m_LutTex.hideFlags = HideFlags.DontSave; } m_LutTex.SetPixels(newC); m_LutTex.Apply(); }