@@ -29,6 +29,7 @@ public sealed class GradingModeParameter : ParameterOverride<GradingMode> {}
2929 [ Serializable ]
3030 public sealed class TonemapperParameter : ParameterOverride < Tonemapper > { }
3131
32+ // TODO: Could use some refactoring, too much duplicated code here
3233 [ Serializable ]
3334 [ PostProcess ( typeof ( ColorGradingRenderer ) , "Unity/Color Grading" ) ]
3435 public sealed class ColorGrading : PostProcessEffectSettings
@@ -137,7 +138,7 @@ public sealed class ColorGrading : PostProcessEffectSettings
137138
138139 public override bool IsEnabledAndSupported ( PostProcessRenderContext context )
139140 {
140- if ( gradingMode . value == GradingMode . HighDefinitionRange || gradingMode . value == GradingMode . External )
141+ if ( gradingMode . value == GradingMode . External )
141142 {
142143 if ( ! SystemInfo . supports3DRenderTextures || ! SystemInfo . supportsComputeShaders )
143144 return false ;
@@ -153,6 +154,7 @@ enum Pass
153154 {
154155 LutGenLDRFromScratch ,
155156 LutGenLDR ,
157+ LutGenHDR2D
156158 }
157159
158160 Texture2D m_GradingCurves ;
@@ -167,28 +169,30 @@ enum Pass
167169
168170 public override void Render ( PostProcessRenderContext context )
169171 {
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 ) ;
179183 }
180184
181185 // Do color grading using an externally authored 3D lut; it requires Texture3D support and
182186 // compute shaders in case blending is required - Desktop / Consoles / Some high-end mobiles
183- void RenderExternalPipeline ( PostProcessRenderContext context )
187+ void RenderExternalPipeline3D ( PostProcessRenderContext context )
184188 {
185189 var lut = settings . externalLut . value ;
186190
187191 if ( lut == null )
188192 return ;
189193
190194 var uberSheet = context . uberSheet ;
191- uberSheet . EnableKeyword ( "COLOR_GRADING_HDR " ) ;
195+ uberSheet . EnableKeyword ( "COLOR_GRADING_HDR_3D " ) ;
192196 uberSheet . properties . SetTexture ( ShaderIDs . Lut3D , lut ) ;
193197 uberSheet . properties . SetVector ( ShaderIDs . Lut3D_Params , new Vector2 ( 1f / lut . width , lut . width - 1f ) ) ;
194198 uberSheet . properties . SetFloat ( ShaderIDs . PostExposure , RuntimeUtilities . Exp2 ( settings . postExposure . value ) ) ;
@@ -197,7 +201,8 @@ void RenderExternalPipeline(PostProcessRenderContext context)
197201
198202 // HDR color pipeline is rendered to a 3D lut; it requires Texture3D & compute shaders
199203 // 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 )
201206 {
202207 // Unfortunately because AnimationCurve doesn't implement GetHashCode and we don't have
203208 // 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)
266271 settings . toneCurveGamma . value
267272 ) ;
268273
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 ) ;
287281 }
288282
289283 // Generate the lut
290- context . command . BeginSample ( "HdrColorGradingLut " ) ;
284+ context . command . BeginSample ( "HdrColorGradingLut3D " ) ;
291285 cmd . DispatchCompute ( compute , kernel , groupSizeXY , groupSizeXY , groupSizeZ ) ;
292- context . command . EndSample ( "HdrColorGradingLut " ) ;
286+ context . command . EndSample ( "HdrColorGradingLut3D " ) ;
293287 }
294288
295289 var lut = m_InternalLogLut ;
296290 var uberSheet = context . uberSheet ;
297- uberSheet . EnableKeyword ( "COLOR_GRADING_HDR " ) ;
291+ uberSheet . EnableKeyword ( "COLOR_GRADING_HDR_3D " ) ;
298292 uberSheet . properties . SetTexture ( ShaderIDs . Lut3D , lut ) ;
299293 uberSheet . properties . SetVector ( ShaderIDs . Lut3D_Params , new Vector2 ( 1f / lut . width , lut . width - 1f ) ) ;
300294 uberSheet . properties . SetFloat ( ShaderIDs . PostExposure , RuntimeUtilities . Exp2 ( settings . postExposure . value ) ) ;
301295
302296 context . logLut = lut ;
303297 }
304298
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+
305380 // LDR color pipeline is rendered to a 2D strip lut (works on every platform)
306- void RenderLDRPipeline ( PostProcessRenderContext context )
381+ void RenderLDRPipeline2D ( PostProcessRenderContext context )
307382 {
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
309384 {
310- CheckInternalLdrLut ( ) ;
385+ CheckInternalStripLut ( ) ;
311386
312387 // Lut setup
313388 var lutSheet = context . propertySheets . Get ( context . resources . shaders . lut2DBaker ) ;
@@ -342,18 +417,18 @@ void RenderLDRPipeline(PostProcessRenderContext context)
342417 lutSheet . properties . SetTexture ( ShaderIDs . Curves , GetCurveTexture ( false ) ) ;
343418
344419 // Generate the lut
345- context . command . BeginSample ( "LdrColorGradingLut " ) ;
420+ context . command . BeginSample ( "LdrColorGradingLut2D " ) ;
346421 var userLut = settings . ldrLut . value ;
347422 if ( userLut == null )
348423 context . command . BlitFullscreenTriangle ( BuiltinRenderTextureType . None , m_InternalLdrLut , lutSheet , ( int ) Pass . LutGenLDRFromScratch ) ;
349424 else
350425 context . command . BlitFullscreenTriangle ( userLut , m_InternalLdrLut , lutSheet , ( int ) Pass . LutGenLDR ) ;
351- context . command . EndSample ( "LdrColorGradingLut " ) ;
426+ context . command . EndSample ( "LdrColorGradingLut2D " ) ;
352427 }
353428
354429 var lut = m_InternalLdrLut ;
355430 var uberSheet = context . uberSheet ;
356- uberSheet . EnableKeyword ( "COLOR_GRADING_LDR " ) ;
431+ uberSheet . EnableKeyword ( "COLOR_GRADING_LDR_2D " ) ;
357432 uberSheet . properties . SetVector ( ShaderIDs . Lut2D_Params , new Vector3 ( 1f / lut . width , 1f / lut . height , lut . height - 1f ) ) ;
358433 uberSheet . properties . SetTexture ( ShaderIDs . Lut2D , lut ) ;
359434 }
@@ -383,7 +458,7 @@ void CheckInternalLogLut()
383458 }
384459 }
385460
386- void CheckInternalLdrLut ( )
461+ void CheckInternalStripLut ( )
387462 {
388463 // Check internal lut state, (re)create it if needed
389464 if ( m_InternalLdrLut == null || ! m_InternalLdrLut . IsCreated ( ) )
@@ -393,7 +468,7 @@ void CheckInternalLdrLut()
393468 var format = GetLutFormat ( ) ;
394469 m_InternalLdrLut = new RenderTexture ( k_Lut2DSize * k_Lut2DSize , k_Lut2DSize , 0 , format , RenderTextureReadWrite . Linear )
395470 {
396- name = "Color Grading Ldr Lut" ,
471+ name = "Color Grading Strip Lut" ,
397472 hideFlags = HideFlags . DontSave ,
398473 filterMode = FilterMode . Bilinear ,
399474 wrapMode = TextureWrapMode . Clamp ,
0 commit comments