Skip to content
This repository was archived by the owner on Nov 30, 2020. It is now read-only.

Commit cd9f472

Browse files
committed
Added a helper curve in the neutral tonemapper UI
1 parent 29fbd35 commit cd9f472

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

PostProcessing/Editor/Models/ColorGradingModelEditor.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ struct CurvesSettings
8989
CurveEditor m_CurveEditor;
9090
Dictionary<SerializedProperty, Color> m_CurveDict;
9191

92+
// Neutral tonemapping curve helper
93+
const int k_CurveResolution = 24;
94+
const float k_NeutralRangeX = 2f;
95+
const float k_NeutralRangeY = 1f;
96+
Vector3[] m_RectVertices = new Vector3[4];
97+
Vector3[] m_LineVertices = new Vector3[2];
98+
Vector3[] m_CurveVertices = new Vector3[k_CurveResolution];
99+
Rect m_NeutralCurveRect;
100+
92101
public override void OnEnable()
93102
{
94103
// Tonemapping settings
@@ -214,6 +223,8 @@ void DoTonemappingGUI()
214223

215224
if (tid == (int)Tonemapper.Neutral)
216225
{
226+
DrawNeutralTonemappingCurve();
227+
217228
EditorGUILayout.PropertyField(m_Tonemapping.neutralBlackIn, EditorGUIHelper.GetContent("Black In"));
218229
EditorGUILayout.PropertyField(m_Tonemapping.neutralWhiteIn, EditorGUIHelper.GetContent("White In"));
219230
EditorGUILayout.PropertyField(m_Tonemapping.neutralBlackOut, EditorGUIHelper.GetContent("Black Out"));
@@ -225,6 +236,129 @@ void DoTonemappingGUI()
225236
m_Tonemapping.tonemapper.intValue = tid;
226237
}
227238

239+
void DrawNeutralTonemappingCurve()
240+
{
241+
using (new GUILayout.HorizontalScope())
242+
{
243+
GUILayout.Space(EditorGUI.indentLevel * 15f);
244+
m_NeutralCurveRect = GUILayoutUtility.GetRect(128, 80);
245+
}
246+
247+
// Background
248+
m_RectVertices[0] = PointInRect( 0f, 0f);
249+
m_RectVertices[1] = PointInRect(k_NeutralRangeX, 0f);
250+
m_RectVertices[2] = PointInRect(k_NeutralRangeX, k_NeutralRangeY);
251+
m_RectVertices[3] = PointInRect( 0f, k_NeutralRangeY);
252+
253+
Handles.DrawSolidRectangleWithOutline(
254+
m_RectVertices,
255+
Color.white * 0.1f,
256+
Color.white * 0.4f
257+
);
258+
259+
// Horizontal lines
260+
for (var i = 1; i < k_NeutralRangeY; i++)
261+
DrawLine(0, i, k_NeutralRangeX, i, 0.4f);
262+
263+
// Vertical lines
264+
for (var i = 1; i < k_NeutralRangeX; i++)
265+
DrawLine(i, 0, i, k_NeutralRangeY, 0.4f);
266+
267+
// Label
268+
Handles.Label(
269+
PointInRect(0, k_NeutralRangeY) + Vector3.right,
270+
"Neutral Tonemapper", EditorStyles.miniLabel
271+
);
272+
273+
// Precompute some values
274+
var tonemap = ((ColorGradingModel)target).settings.tonemapping;
275+
276+
const float scaleFactor = 20f;
277+
const float scaleFactorHalf = scaleFactor * 0.5f;
278+
279+
float inBlack = tonemap.neutralBlackIn * scaleFactor + 1f;
280+
float outBlack = tonemap.neutralBlackOut * scaleFactorHalf + 1f;
281+
float inWhite = tonemap.neutralWhiteIn / scaleFactor;
282+
float outWhite = 1f - tonemap.neutralWhiteOut / scaleFactor;
283+
float blackRatio = inBlack / outBlack;
284+
float whiteRatio = inWhite / outWhite;
285+
286+
const float a = 0.2f;
287+
float b = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, blackRatio));
288+
float c = Mathf.LerpUnclamped(0.01f, 0.24f, whiteRatio);
289+
float d = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.20f, blackRatio));
290+
const float e = 0.02f;
291+
const float f = 0.30f;
292+
float whiteLevel = tonemap.neutralWhiteLevel;
293+
float whiteClip = tonemap.neutralWhiteClip / scaleFactorHalf;
294+
295+
// Tonemapping curve
296+
var vcount = 0;
297+
while (vcount < k_CurveResolution)
298+
{
299+
float x = k_NeutralRangeX * vcount / (k_CurveResolution - 1);
300+
float y = NeutralTonemap(x, a, b, c, d, e, f, whiteLevel, whiteClip);
301+
302+
if (y < k_NeutralRangeY)
303+
{
304+
m_CurveVertices[vcount++] = PointInRect(x, y);
305+
}
306+
else
307+
{
308+
if (vcount > 1)
309+
{
310+
// Extend the last segment to the top edge of the rect.
311+
var v1 = m_CurveVertices[vcount - 2];
312+
var v2 = m_CurveVertices[vcount - 1];
313+
var clip = (m_NeutralCurveRect.y - v1.y) / (v2.y - v1.y);
314+
m_CurveVertices[vcount - 1] = v1 + (v2 - v1) * clip;
315+
}
316+
break;
317+
}
318+
}
319+
320+
if (vcount > 1)
321+
{
322+
Handles.color = Color.white * 0.9f;
323+
Handles.DrawAAPolyLine(2.0f, vcount, m_CurveVertices);
324+
}
325+
}
326+
327+
void DrawLine(float x1, float y1, float x2, float y2, float grayscale)
328+
{
329+
m_LineVertices[0] = PointInRect(x1, y1);
330+
m_LineVertices[1] = PointInRect(x2, y2);
331+
Handles.color = Color.white * grayscale;
332+
Handles.DrawAAPolyLine(2f, m_LineVertices);
333+
}
334+
335+
Vector3 PointInRect(float x, float y)
336+
{
337+
x = Mathf.Lerp(m_NeutralCurveRect.x, m_NeutralCurveRect.xMax, x / k_NeutralRangeX);
338+
y = Mathf.Lerp(m_NeutralCurveRect.yMax, m_NeutralCurveRect.y, y / k_NeutralRangeY);
339+
return new Vector3(x, y, 0);
340+
}
341+
342+
float NeutralCurve(float x, float a, float b, float c, float d, float e, float f)
343+
{
344+
return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
345+
}
346+
347+
float NeutralTonemap(float x, float a, float b, float c, float d, float e, float f, float whiteLevel, float whiteClip)
348+
{
349+
x = Mathf.Max(0f, x);
350+
351+
// Tonemap
352+
float whiteScale = 1f / NeutralCurve(whiteLevel, a, b, c, d, e, f);
353+
x = NeutralCurve(x * whiteScale, a, b, c, d, e, f);
354+
x *= whiteScale;
355+
356+
// Post-curve white point adjustment
357+
x /= whiteClip;
358+
359+
return x;
360+
}
361+
228362
void DoBasicGUI()
229363
{
230364
EditorGUILayout.PropertyField(m_Basic.exposure, EditorGUIHelper.GetContent("Post Exposure (EV)"));

0 commit comments

Comments
 (0)