@@ -29,6 +29,7 @@ public sealed class GradingModeParameter : ParameterOverride<GradingMode> {}
29
29
[ Serializable ]
30
30
public sealed class TonemapperParameter : ParameterOverride < Tonemapper > { }
31
31
32
+ // TODO: Could use some refactoring, too much duplicated code here
32
33
[ Serializable ]
33
34
[ PostProcess ( typeof ( ColorGradingRenderer ) , "Unity/Color Grading" ) ]
34
35
public sealed class ColorGrading : PostProcessEffectSettings
@@ -137,7 +138,7 @@ public sealed class ColorGrading : PostProcessEffectSettings
137
138
138
139
public override bool IsEnabledAndSupported ( PostProcessRenderContext context )
139
140
{
140
- if ( gradingMode . value == GradingMode . HighDefinitionRange || gradingMode . value == GradingMode . External )
141
+ if ( gradingMode . value == GradingMode . External )
141
142
{
142
143
if ( ! SystemInfo . supports3DRenderTextures || ! SystemInfo . supportsComputeShaders )
143
144
return false ;
@@ -153,6 +154,7 @@ enum Pass
153
154
{
154
155
LutGenLDRFromScratch ,
155
156
LutGenLDR ,
157
+ LutGenHDR2D
156
158
}
157
159
158
160
Texture2D m_GradingCurves ;
@@ -167,28 +169,30 @@ enum Pass
167
169
168
170
public override void Render ( PostProcessRenderContext context )
169
171
{
170
- switch ( settings . gradingMode . value )
171
- {
172
- case GradingMode . External : RenderExternalPipeline ( context ) ;
173
- break ;
174
- case GradingMode . LowDefinitionRange : RenderLDRPipeline ( context ) ;
175
- break ;
176
- case GradingMode . HighDefinitionRange : RenderHDRPipeline ( context ) ;
177
- break ;
178
- }
172
+ var gradingMode = settings . gradingMode . value ;
173
+ var supportComputeTex3D = SystemInfo . supports3DRenderTextures && SystemInfo . supportsComputeShaders ;
174
+
175
+ if ( gradingMode == GradingMode . External )
176
+ RenderExternalPipeline3D ( context ) ;
177
+ else if ( gradingMode == GradingMode . HighDefinitionRange && supportComputeTex3D )
178
+ RenderHDRPipeline3D ( context ) ;
179
+ else if ( gradingMode == GradingMode . HighDefinitionRange )
180
+ RenderHDRPipeline2D ( context ) ;
181
+ else
182
+ RenderLDRPipeline2D ( context ) ;
179
183
}
180
184
181
185
// Do color grading using an externally authored 3D lut; it requires Texture3D support and
182
186
// compute shaders in case blending is required - Desktop / Consoles / Some high-end mobiles
183
- void RenderExternalPipeline ( PostProcessRenderContext context )
187
+ void RenderExternalPipeline3D ( PostProcessRenderContext context )
184
188
{
185
189
var lut = settings . externalLut . value ;
186
190
187
191
if ( lut == null )
188
192
return ;
189
193
190
194
var uberSheet = context . uberSheet ;
191
- uberSheet . EnableKeyword ( "COLOR_GRADING_HDR " ) ;
195
+ uberSheet . EnableKeyword ( "COLOR_GRADING_HDR_3D " ) ;
192
196
uberSheet . properties . SetTexture ( ShaderIDs . Lut3D , lut ) ;
193
197
uberSheet . properties . SetVector ( ShaderIDs . Lut3D_Params , new Vector2 ( 1f / lut . width , lut . width - 1f ) ) ;
194
198
uberSheet . properties . SetFloat ( ShaderIDs . PostExposure , RuntimeUtilities . Exp2 ( settings . postExposure . value ) ) ;
@@ -197,7 +201,8 @@ void RenderExternalPipeline(PostProcessRenderContext context)
197
201
198
202
// HDR color pipeline is rendered to a 3D lut; it requires Texture3D & compute shaders
199
203
// support - Desktop / Consoles / Some high-end mobiles
200
- void RenderHDRPipeline ( PostProcessRenderContext context )
204
+ // TODO: Use ShaderIDs for compute once the compatible APIs go in
205
+ void RenderHDRPipeline3D ( PostProcessRenderContext context )
201
206
{
202
207
// Unfortunately because AnimationCurve doesn't implement GetHashCode and we don't have
203
208
// any reliable way to figure out if a curve data is different from another one we can't
@@ -266,48 +271,118 @@ void RenderHDRPipeline(PostProcessRenderContext context)
266
271
settings . toneCurveGamma . value
267
272
) ;
268
273
269
- var curve = new Vector4 ( m_HableCurve . inverseWhitePoint , m_HableCurve . x0 , m_HableCurve . x1 , 0f ) ;
270
- cmd . SetComputeVectorParam ( compute , "_CustomToneCurve" , curve ) ;
271
-
272
- var toe = m_HableCurve . segments [ 0 ] ;
273
- var mid = m_HableCurve . segments [ 1 ] ;
274
- var sho = m_HableCurve . segments [ 2 ] ;
275
- var toeSegmentA = new Vector4 ( toe . offsetX , toe . offsetY , toe . scaleX , toe . scaleY ) ;
276
- var toeSegmentB = new Vector4 ( toe . lnA , toe . B , 0f , 0f ) ;
277
- var midSegmentA = new Vector4 ( mid . offsetX , mid . offsetY , mid . scaleX , mid . scaleY ) ;
278
- var midSegmentB = new Vector4 ( mid . lnA , mid . B , 0f , 0f ) ;
279
- var shoSegmentA = new Vector4 ( sho . offsetX , sho . offsetY , sho . scaleX , sho . scaleY ) ;
280
- var shoSegmentB = new Vector4 ( sho . lnA , sho . B , 0f , 0f ) ;
281
- cmd . SetComputeVectorParam ( compute , "_ToeSegmentA" , toeSegmentA ) ;
282
- cmd . SetComputeVectorParam ( compute , "_ToeSegmentB" , toeSegmentB ) ;
283
- cmd . SetComputeVectorParam ( compute , "_MidSegmentA" , midSegmentA ) ;
284
- cmd . SetComputeVectorParam ( compute , "_MidSegmentB" , midSegmentB ) ;
285
- cmd . SetComputeVectorParam ( compute , "_ShoSegmentA" , shoSegmentA ) ;
286
- cmd . SetComputeVectorParam ( compute , "_ShoSegmentB" , shoSegmentB ) ;
274
+ cmd . SetComputeVectorParam ( compute , "_CustomToneCurve" , m_HableCurve . uniforms . curve ) ;
275
+ cmd . SetComputeVectorParam ( compute , "_ToeSegmentA" , m_HableCurve . uniforms . toeSegmentA ) ;
276
+ cmd . SetComputeVectorParam ( compute , "_ToeSegmentB" , m_HableCurve . uniforms . toeSegmentB ) ;
277
+ cmd . SetComputeVectorParam ( compute , "_MidSegmentA" , m_HableCurve . uniforms . midSegmentA ) ;
278
+ cmd . SetComputeVectorParam ( compute , "_MidSegmentB" , m_HableCurve . uniforms . midSegmentB ) ;
279
+ cmd . SetComputeVectorParam ( compute , "_ShoSegmentA" , m_HableCurve . uniforms . shoSegmentA ) ;
280
+ cmd . SetComputeVectorParam ( compute , "_ShoSegmentB" , m_HableCurve . uniforms . shoSegmentB ) ;
287
281
}
288
282
289
283
// Generate the lut
290
- context . command . BeginSample ( "HdrColorGradingLut " ) ;
284
+ context . command . BeginSample ( "HdrColorGradingLut3D " ) ;
291
285
cmd . DispatchCompute ( compute , kernel , groupSizeXY , groupSizeXY , groupSizeZ ) ;
292
- context . command . EndSample ( "HdrColorGradingLut " ) ;
286
+ context . command . EndSample ( "HdrColorGradingLut3D " ) ;
293
287
}
294
288
295
289
var lut = m_InternalLogLut ;
296
290
var uberSheet = context . uberSheet ;
297
- uberSheet . EnableKeyword ( "COLOR_GRADING_HDR " ) ;
291
+ uberSheet . EnableKeyword ( "COLOR_GRADING_HDR_3D " ) ;
298
292
uberSheet . properties . SetTexture ( ShaderIDs . Lut3D , lut ) ;
299
293
uberSheet . properties . SetVector ( ShaderIDs . Lut3D_Params , new Vector2 ( 1f / lut . width , lut . width - 1f ) ) ;
300
294
uberSheet . properties . SetFloat ( ShaderIDs . PostExposure , RuntimeUtilities . Exp2 ( settings . postExposure . value ) ) ;
301
295
302
296
context . logLut = lut ;
303
297
}
304
298
299
+ // HDR color pipeline is rendered to a 2D strip lut (works on HDR platforms without compute
300
+ // and 3D texture support). Precision is sliiiiiiightly lower than when using a 3D texture
301
+ // LUT (33^3 -> 32^3) but most of the time it's imperceptible.
302
+ void RenderHDRPipeline2D ( PostProcessRenderContext context )
303
+ {
304
+ // For the same reasons as in RenderHDRPipeline3D, regen LUT on evey frame
305
+ {
306
+ CheckInternalStripLut ( ) ;
307
+
308
+ // Lut setup
309
+ var lutSheet = context . propertySheets . Get ( context . resources . shaders . lut2DBaker ) ;
310
+ lutSheet . ClearKeywords ( ) ;
311
+
312
+ lutSheet . properties . SetVector ( ShaderIDs . Lut2D_Params , new Vector4 ( k_Lut2DSize , 0.5f / ( k_Lut2DSize * k_Lut2DSize ) , 0.5f / k_Lut2DSize , k_Lut2DSize / ( k_Lut2DSize - 1f ) ) ) ;
313
+
314
+ var colorBalance = ColorUtilities . ComputeColorBalance ( settings . temperature . value , settings . tint . value ) ;
315
+ lutSheet . properties . SetVector ( ShaderIDs . ColorBalance , colorBalance ) ;
316
+ lutSheet . properties . SetVector ( ShaderIDs . ColorFilter , settings . colorFilter . value ) ;
317
+
318
+ float hue = settings . hueShift . value / 360f ; // Remap to [-0.5;0.5]
319
+ float sat = settings . saturation . value / 100f + 1f ; // Remap to [0;2]
320
+ float con = settings . contrast . value / 100f + 1f ; // Remap to [0;2]
321
+ lutSheet . properties . SetVector ( ShaderIDs . HueSatCon , new Vector3 ( hue , sat , con ) ) ;
322
+
323
+ var channelMixerR = new Vector3 ( settings . mixerRedOutRedIn , settings . mixerRedOutGreenIn , settings . mixerRedOutBlueIn ) ;
324
+ var channelMixerG = new Vector3 ( settings . mixerGreenOutRedIn , settings . mixerGreenOutGreenIn , settings . mixerGreenOutBlueIn ) ;
325
+ var channelMixerB = new Vector3 ( settings . mixerBlueOutRedIn , settings . mixerBlueOutGreenIn , settings . mixerBlueOutBlueIn ) ;
326
+ lutSheet . properties . SetVector ( ShaderIDs . ChannelMixerRed , channelMixerR / 100f ) ; // Remap to [-2;2]
327
+ lutSheet . properties . SetVector ( ShaderIDs . ChannelMixerGreen , channelMixerG / 100f ) ;
328
+ lutSheet . properties . SetVector ( ShaderIDs . ChannelMixerBlue , channelMixerB / 100f ) ;
329
+
330
+ var lift = ColorUtilities . ColorToLift ( settings . lift . value * 0.2f ) ;
331
+ var gain = ColorUtilities . ColorToGain ( settings . gain . value * 0.8f ) ;
332
+ var invgamma = ColorUtilities . ColorToInverseGamma ( settings . gamma . value * 0.8f ) ;
333
+ lutSheet . properties . SetVector ( ShaderIDs . Lift , lift ) ;
334
+ lutSheet . properties . SetVector ( ShaderIDs . InvGamma , invgamma ) ;
335
+ lutSheet . properties . SetVector ( ShaderIDs . Gain , gain ) ;
336
+
337
+ lutSheet . properties . SetTexture ( ShaderIDs . Curves , GetCurveTexture ( false ) ) ;
338
+
339
+ var tonemapper = settings . tonemapper . value ;
340
+ if ( tonemapper == Tonemapper . Custom )
341
+ {
342
+ lutSheet . EnableKeyword ( "TONEMAPPING_CUSTOM" ) ;
343
+
344
+ m_HableCurve . Init (
345
+ settings . toneCurveToeStrength . value ,
346
+ settings . toneCurveToeLength . value ,
347
+ settings . toneCurveShoulderStrength . value ,
348
+ settings . toneCurveShoulderLength . value ,
349
+ settings . toneCurveShoulderAngle . value ,
350
+ settings . toneCurveGamma . value
351
+ ) ;
352
+
353
+ lutSheet . properties . SetVector ( ShaderIDs . CustomToneCurve , m_HableCurve . uniforms . curve ) ;
354
+ lutSheet . properties . SetVector ( ShaderIDs . ToeSegmentA , m_HableCurve . uniforms . toeSegmentA ) ;
355
+ lutSheet . properties . SetVector ( ShaderIDs . ToeSegmentB , m_HableCurve . uniforms . toeSegmentB ) ;
356
+ lutSheet . properties . SetVector ( ShaderIDs . MidSegmentA , m_HableCurve . uniforms . midSegmentA ) ;
357
+ lutSheet . properties . SetVector ( ShaderIDs . MidSegmentB , m_HableCurve . uniforms . midSegmentB ) ;
358
+ lutSheet . properties . SetVector ( ShaderIDs . ShoSegmentA , m_HableCurve . uniforms . shoSegmentA ) ;
359
+ lutSheet . properties . SetVector ( ShaderIDs . ShoSegmentB , m_HableCurve . uniforms . shoSegmentB ) ;
360
+ }
361
+ else if ( tonemapper == Tonemapper . ACES )
362
+ lutSheet . EnableKeyword ( "TONEMAPPING_ACES" ) ;
363
+ else if ( tonemapper == Tonemapper . Neutral )
364
+ lutSheet . EnableKeyword ( "TONEMAPPING_NEUTRAL" ) ;
365
+
366
+ // Generate the lut
367
+ context . command . BeginSample ( "HdrColorGradingLut2D" ) ;
368
+ context . command . BlitFullscreenTriangle ( BuiltinRenderTextureType . None , m_InternalLdrLut , lutSheet , ( int ) Pass . LutGenHDR2D ) ;
369
+ context . command . EndSample ( "HdrColorGradingLut2D" ) ;
370
+ }
371
+
372
+ var lut = m_InternalLdrLut ;
373
+ var uberSheet = context . uberSheet ;
374
+ uberSheet . EnableKeyword ( "COLOR_GRADING_HDR_2D" ) ;
375
+ uberSheet . properties . SetVector ( ShaderIDs . Lut2D_Params , new Vector3 ( 1f / lut . width , 1f / lut . height , lut . height - 1f ) ) ;
376
+ uberSheet . properties . SetTexture ( ShaderIDs . Lut2D , lut ) ;
377
+ uberSheet . properties . SetFloat ( ShaderIDs . PostExposure , RuntimeUtilities . Exp2 ( settings . postExposure . value ) ) ;
378
+ }
379
+
305
380
// LDR color pipeline is rendered to a 2D strip lut (works on every platform)
306
- void RenderLDRPipeline ( PostProcessRenderContext context )
381
+ void RenderLDRPipeline2D ( PostProcessRenderContext context )
307
382
{
308
- // For the same reasons as in RenderHDRPipeline , regen LUT on evey frame
383
+ // For the same reasons as in RenderHDRPipeline3D , regen LUT on evey frame
309
384
{
310
- CheckInternalLdrLut ( ) ;
385
+ CheckInternalStripLut ( ) ;
311
386
312
387
// Lut setup
313
388
var lutSheet = context . propertySheets . Get ( context . resources . shaders . lut2DBaker ) ;
@@ -342,18 +417,18 @@ void RenderLDRPipeline(PostProcessRenderContext context)
342
417
lutSheet . properties . SetTexture ( ShaderIDs . Curves , GetCurveTexture ( false ) ) ;
343
418
344
419
// Generate the lut
345
- context . command . BeginSample ( "LdrColorGradingLut " ) ;
420
+ context . command . BeginSample ( "LdrColorGradingLut2D " ) ;
346
421
var userLut = settings . ldrLut . value ;
347
422
if ( userLut == null )
348
423
context . command . BlitFullscreenTriangle ( BuiltinRenderTextureType . None , m_InternalLdrLut , lutSheet , ( int ) Pass . LutGenLDRFromScratch ) ;
349
424
else
350
425
context . command . BlitFullscreenTriangle ( userLut , m_InternalLdrLut , lutSheet , ( int ) Pass . LutGenLDR ) ;
351
- context . command . EndSample ( "LdrColorGradingLut " ) ;
426
+ context . command . EndSample ( "LdrColorGradingLut2D " ) ;
352
427
}
353
428
354
429
var lut = m_InternalLdrLut ;
355
430
var uberSheet = context . uberSheet ;
356
- uberSheet . EnableKeyword ( "COLOR_GRADING_LDR " ) ;
431
+ uberSheet . EnableKeyword ( "COLOR_GRADING_LDR_2D " ) ;
357
432
uberSheet . properties . SetVector ( ShaderIDs . Lut2D_Params , new Vector3 ( 1f / lut . width , 1f / lut . height , lut . height - 1f ) ) ;
358
433
uberSheet . properties . SetTexture ( ShaderIDs . Lut2D , lut ) ;
359
434
}
@@ -383,7 +458,7 @@ void CheckInternalLogLut()
383
458
}
384
459
}
385
460
386
- void CheckInternalLdrLut ( )
461
+ void CheckInternalStripLut ( )
387
462
{
388
463
// Check internal lut state, (re)create it if needed
389
464
if ( m_InternalLdrLut == null || ! m_InternalLdrLut . IsCreated ( ) )
@@ -393,7 +468,7 @@ void CheckInternalLdrLut()
393
468
var format = GetLutFormat ( ) ;
394
469
m_InternalLdrLut = new RenderTexture ( k_Lut2DSize * k_Lut2DSize , k_Lut2DSize , 0 , format , RenderTextureReadWrite . Linear )
395
470
{
396
- name = "Color Grading Ldr Lut" ,
471
+ name = "Color Grading Strip Lut" ,
397
472
hideFlags = HideFlags . DontSave ,
398
473
filterMode = FilterMode . Bilinear ,
399
474
wrapMode = TextureWrapMode . Clamp ,
0 commit comments