Add color grading pass into main pipeline (#4005)
* Add HDR color grading pass and shaders. Signed-off-by: Robin <rbarrand@amazon.com> * Improve code quality. Signed-off-by: Robin <rbarrand@amazon.com> * Code refactor. Signed-off-by: Robin <rbarrand@amazon.com> * Remove color grading pass from light adaptation parent pass due to failing ASV tests. This will be added back later on. Signed-off-by: Robin <rbarrand@amazon.com> * Add newline. Signed-off-by: Robin <rbarrand@amazon.com> * Correct case for file. Signed-off-by: Robin <rbarrand@amazon.com> * Update comment. Signed-off-by: Robin <rbarrand@amazon.com> Co-authored-by: Robin <rbarrand@amazon.com>monroegm-disable-blank-issue-2
parent
bbe437819b
commit
b2445ebe0c
@ -0,0 +1,215 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "HDRColorGradingTemplate",
|
||||
"PassClass": "FullScreenTriangle",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "Input",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_framebuffer",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "Output",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget",
|
||||
"LoadStoreAction": {
|
||||
"LoadAction": "DontCare"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "ColorGradingOutput",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "This",
|
||||
"Attachment": "Input"
|
||||
}
|
||||
},
|
||||
"FormatSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "Input"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "ColorGradingOutput"
|
||||
}
|
||||
}
|
||||
],
|
||||
"FallbackConnections": [
|
||||
{
|
||||
"Input": "Input",
|
||||
"Output": "Output"
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "FullscreenTrianglePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/PostProcessing/HDRColorGrading.shader"
|
||||
},
|
||||
"ShaderDataMappings": {
|
||||
"FloatMappings": [
|
||||
{
|
||||
"Name": "m_colorGradingExposure",
|
||||
"Value": 0.0 // unconstrained, log2 stops
|
||||
},
|
||||
{
|
||||
"Name": "m_colorGradingContrast",
|
||||
"Value": 0.0 // -100 ... 100
|
||||
},
|
||||
{
|
||||
"Name": "m_colorGradingHueShift",
|
||||
"Value": 0.0 // 0 ... 1, can wrap
|
||||
},
|
||||
{
|
||||
"Name": "m_colorGradingPreSaturation",
|
||||
"Value": 1.0 // -100 ... 100
|
||||
},
|
||||
{
|
||||
"Name": "m_colorFilterIntensity",
|
||||
"Value": 1.0 // unconstrained, log2 stops
|
||||
},
|
||||
{
|
||||
"Name": "m_colorFilterMultiply",
|
||||
"Value": 0.0 // modulate, 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_whiteBalanceKelvin",
|
||||
"Value": 6500.0 // 1000.0f ... 40000.0f kelvin
|
||||
},
|
||||
{
|
||||
"Name": "m_whiteBalanceTint",
|
||||
"Value": 0.0 // -100 ... 100
|
||||
},
|
||||
{
|
||||
"Name": "m_splitToneBalance",
|
||||
"Value": 0.0 // -1 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_splitToneMix",
|
||||
"Value": 0.0 // 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_colorGradingPostSaturation",
|
||||
"Value": 1.0 // -100 ... 100
|
||||
},
|
||||
{
|
||||
"Name": "m_smhShadowsStart",
|
||||
"Value": 0.0 // 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_smhShadowsEnd",
|
||||
"Value": 0.3 // 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_smhHighlightsStart",
|
||||
"Value": 0.55 // 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_smhHighlightsEnd",
|
||||
"Value": 1.0 // 0 ... 1
|
||||
},
|
||||
{
|
||||
"Name": "m_smhMix",
|
||||
"Value": 0.0 // 0 ... 1
|
||||
}
|
||||
],
|
||||
// The colors defined here are expected to be in linear rgb color space.
|
||||
// These are converted to ACEScg color space within the HDRColorGrading.azsl shader
|
||||
"ColorMappings": [
|
||||
{
|
||||
"Name": "m_colorFilterSwatch",
|
||||
"Value": [
|
||||
1.0,
|
||||
0.5,
|
||||
0.5,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_splitToneShadowsColor",
|
||||
"Value": [
|
||||
1.0,
|
||||
0.1,
|
||||
0.1,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_splitToneHighlightsColor",
|
||||
"Value": [
|
||||
0.1,
|
||||
1.0,
|
||||
0.1,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_smhShadowsColor",
|
||||
"Value": [
|
||||
1.0,
|
||||
0.25,
|
||||
0.25,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_smhMidtonesColor",
|
||||
"Value": [
|
||||
0.1,
|
||||
0.1,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_smhHighlightsColor",
|
||||
"Value": [
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"Float3Mappings": [
|
||||
{
|
||||
"Name": "m_channelMixingRed",
|
||||
"Value": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_channelMixingGreen",
|
||||
"Value": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "m_channelMixingBlue",
|
||||
"Value": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: (Apache-2.0 OR MIT) AND Creative Commons 3.0
|
||||
*
|
||||
*/
|
||||
|
||||
// Ref: https://www.shadertoy.com/view/lsSXW1
|
||||
// ported by Renaud Bédard (@renaudbedard) from original code from Tanner Helland
|
||||
// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
|
||||
// color space functions translated from HLSL versions on Chilli Ant (by Ian Taylor)
|
||||
// http://www.chilliant.com/rgb2hsv.html
|
||||
|
||||
// licensed and released under Creative Commons 3.0 Attribution
|
||||
// https://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
float3 HueToRgb(float hue)
|
||||
{
|
||||
return saturate(float3(abs(hue * 6.0f - 3.0f) - 1.0f,
|
||||
2.0f - abs(hue * 6.0f - 2.0f),
|
||||
2.0f - abs(hue * 6.0f - 4.0f)));
|
||||
}
|
||||
|
||||
float3 RgbToHcv(float3 rgb)
|
||||
{
|
||||
// Based on work by Sam Hocevar and Emil Persson
|
||||
const float4 p = (rgb.g < rgb.b) ? float4(rgb.bg, -1.0f, 2.0f/3.0f) : float4(rgb.gb, 0.0f, -1.0f/3.0f);
|
||||
const float4 q1 = (rgb.r < p.x) ? float4(p.xyw, rgb.r) : float4(rgb.r, p.yzx);
|
||||
const float c = q1.x - min(q1.w, q1.y);
|
||||
const float h = abs((q1.w - q1.y) / (6.0f * c + 0.000001f ) + q1.z);
|
||||
return float3(h, c, q1.x);
|
||||
}
|
||||
|
||||
float3 RgbToHsl(float3 rgb)
|
||||
{
|
||||
rgb.xyz = max(rgb.xyz, 0.000001f);
|
||||
const float3 hcv = RgbToHcv(rgb);
|
||||
const float L = hcv.z - hcv.y * 0.5f;
|
||||
const float S = hcv.y / (1.0f - abs(L * 2.0f - 1.0f) + 0.000001f);
|
||||
return float3(hcv.x, S, L);
|
||||
}
|
||||
|
||||
float3 HslToRgb(float3 hsl)
|
||||
{
|
||||
const float3 rgb = HueToRgb(hsl.x);
|
||||
const float c = (1.0f - abs(2.0f * hsl.z - 1.0f)) * hsl.y;
|
||||
return (rgb - 0.5f) * c + hsl.z;
|
||||
}
|
||||
|
||||
// Color temperature
|
||||
float3 KelvinToRgb(float kelvin)
|
||||
{
|
||||
float3 ret;
|
||||
kelvin = clamp(kelvin, 1000.0f, 40000.0f) / 100.0f;
|
||||
if(kelvin <= 66.0f)
|
||||
{
|
||||
ret.r = 1.0f;
|
||||
ret.g = saturate(0.39008157876901960784f * log(kelvin) - 0.63184144378862745098f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float t = max(kelvin - 60.0f, 0.0f);
|
||||
ret.r = saturate(1.29293618606274509804f * pow(t, -0.1332047592f));
|
||||
ret.g = saturate(1.12989086089529411765f * pow(t, -0.0755148492f));
|
||||
}
|
||||
if(kelvin >= 66.0f)
|
||||
ret.b = 1.0f;
|
||||
else if(kelvin < 19.0f)
|
||||
ret.b = 0.0f;
|
||||
else
|
||||
ret.b = saturate(0.54320678911019607843f * log(kelvin - 10.0f) - 1.19625408914f);
|
||||
return ret;
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
Public Domain
|
||||
------------------------------------------------------------------------------
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
Source: https://www.ryanjuckett.com/photoshop-blend-modes-in-hlsl/
|
||||
*/
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
float Color_GetLuminosity(float3 c)
|
||||
{
|
||||
return 0.3*c.r + 0.59*c.g + 0.11*c.b;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
float3 Color_SetLuminosity(float3 c, float lum)
|
||||
{
|
||||
float d = lum - Color_GetLuminosity(c);
|
||||
c.rgb += float3(d,d,d);
|
||||
|
||||
// clip back into legal range
|
||||
lum = Color_GetLuminosity(c);
|
||||
float cMin = min(c.r, min(c.g, c.b));
|
||||
float cMax = max(c.r, max(c.g, c.b));
|
||||
|
||||
if(cMin < 0)
|
||||
c = lerp(float3(lum,lum,lum), c, lum / (lum - cMin));
|
||||
|
||||
if(cMax > 1)
|
||||
c = lerp(float3(lum,lum,lum), c, (1 - lum) / (cMax - lum));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
float Color_GetSaturation(float3 c)
|
||||
{
|
||||
return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Set saturation if color components are sorted in ascending order.
|
||||
//******************************************************************************
|
||||
float3 Color_SetSaturation_MinMidMax(float3 cSorted, float s)
|
||||
{
|
||||
if(cSorted.z > cSorted.x)
|
||||
{
|
||||
cSorted.y = (((cSorted.y - cSorted.x) * s) / (cSorted.z - cSorted.x));
|
||||
cSorted.z = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
cSorted.y = 0;
|
||||
cSorted.z = 0;
|
||||
}
|
||||
|
||||
cSorted.x = 0;
|
||||
|
||||
return cSorted;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
float3 Color_SetSaturation(float3 c, float s)
|
||||
{
|
||||
if (c.r <= c.g && c.r <= c.b)
|
||||
{
|
||||
if (c.g <= c.b)
|
||||
c.rgb = Color_SetSaturation_MinMidMax(c.rgb, s);
|
||||
else
|
||||
c.rbg = Color_SetSaturation_MinMidMax(c.rbg, s);
|
||||
}
|
||||
else if (c.g <= c.r && c.g <= c.b)
|
||||
{
|
||||
if (c.r <= c.b)
|
||||
c.grb = Color_SetSaturation_MinMidMax(c.grb, s);
|
||||
else
|
||||
c.gbr = Color_SetSaturation_MinMidMax(c.gbr, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c.r <= c.g)
|
||||
c.brg = Color_SetSaturation_MinMidMax(c.brg, s);
|
||||
else
|
||||
c.bgr = Color_SetSaturation_MinMidMax(c.bgr, s);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Creates a color with the hue of the blend color and the saturation and
|
||||
// luminosity of the base color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_Hue(float3 base, float3 blend)
|
||||
{
|
||||
return Color_SetLuminosity(Color_SetSaturation(blend, Color_GetSaturation(base)), Color_GetLuminosity(base));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Creates a color with the saturation of the blend color and the hue and
|
||||
// luminosity of the base color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_Saturation(float3 base, float3 blend)
|
||||
{
|
||||
return Color_SetLuminosity(Color_SetSaturation(base, Color_GetSaturation(blend)), Color_GetLuminosity(base));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Creates a color with the hue and saturation of the blend color and the
|
||||
// luminosity of the base color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_Color(float3 base, float3 blend)
|
||||
{
|
||||
return Color_SetLuminosity(blend, Color_GetLuminosity(base));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Creates a color with the luminosity of the blend color and the hue and
|
||||
// saturation of the base color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_Luminosity(float3 base, float3 blend)
|
||||
{
|
||||
return Color_SetLuminosity(base, Color_GetLuminosity(blend));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Compares the total of all channel values for the blend and base color and
|
||||
// displays the lower value color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_DarkerColor(float3 base, float3 blend)
|
||||
{
|
||||
return Color_GetLuminosity(base) <= Color_GetLuminosity(blend) ? base : blend;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Compares the total of all channel values for the blend and base color and
|
||||
// displays the higher value color.
|
||||
//******************************************************************************
|
||||
float3 BlendMode_LighterColor(float3 base, float3 blend)
|
||||
{
|
||||
return Color_GetLuminosity(base) > Color_GetLuminosity(blend) ? base : blend;
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: (MIT OR Apache-2.0) AND LicenseRef-ACES
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
License Terms for Academy Color Encoding System Components
|
||||
|
||||
Academy Color Encoding System (ACES) software and tools are provided by the
|
||||
Academy under the following terms and conditions: A worldwide, royalty-free,
|
||||
non-exclusive right to copy, modify, create derivatives, and use, in source and
|
||||
binary forms, is hereby granted, subject to acceptance of this license.
|
||||
|
||||
Copyright © 2015 Academy of Motion Picture Arts and Sciences (A.M.P.A.S.).
|
||||
Portions contributed by others as indicated. All rights reserved.
|
||||
|
||||
Performance of any of the aforementioned acts indicates acceptance to be bound
|
||||
by the following terms and conditions:
|
||||
|
||||
* Copies of source code, in whole or in part, must retain the above copyright
|
||||
notice, this list of conditions and the Disclaimer of Warranty.
|
||||
* Use in binary form must retain the above copyright notice, this list of
|
||||
conditions and the Disclaimer of Warranty in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
* Nothing in this license shall be deemed to grant any rights to trademarks,
|
||||
copyrights, patents, trade secrets or any other intellectual property of
|
||||
A.M.P.A.S. or any contributors, except as expressly stated herein.
|
||||
* Neither the name "A.M.P.A.S." nor the name of any other contributors to this
|
||||
software may be used to endorse or promote products derivative of or based on
|
||||
this software without express prior written permission of A.M.P.A.S. or the
|
||||
contributors, as appropriate.
|
||||
|
||||
This license shall be construed pursuant to the laws of the State of California,
|
||||
and any disputes related thereto shall be subject to the jurisdiction of the
|
||||
courts therein.
|
||||
|
||||
Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL A.M.P.A.S., OR ANY
|
||||
CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, RESITUTIONARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY SPECIFICALLY
|
||||
DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER RELATED TO PATENT OR
|
||||
OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY COLOR ENCODING SYSTEM, OR
|
||||
APPLICATIONS THEREOF, HELD BY PARTIES OTHER THAN A.M.P.A.S.,WHETHER DISCLOSED OR
|
||||
UNDISCLOSED.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
static const float HALF_MAX = 65504.0f;
|
||||
|
||||
float AcesCcToLinear(float value)
|
||||
{
|
||||
if (value < -0.3013698630) // (9.72-15)/17.52
|
||||
return (pow( 2., value*17.52-9.72) - pow( 2.,-16.))*2.0;
|
||||
else if (value < (log2(HALF_MAX)+9.72)/17.52)
|
||||
return pow( 2., value*17.52-9.72);
|
||||
else // (value >= (log2(HALF_MAX)+9.72)/17.52)
|
||||
return HALF_MAX;
|
||||
}
|
||||
|
||||
float3 AcesCcToAcesCg(float3 color)
|
||||
{
|
||||
return float3(
|
||||
AcesCcToLinear(color.r),
|
||||
AcesCcToLinear(color.g),
|
||||
AcesCcToLinear(color.b));
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: (MIT OR Apache-2.0) AND LicenseRef-ACES
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
License Terms for Academy Color Encoding System Components
|
||||
|
||||
Academy Color Encoding System (ACES) software and tools are provided by the
|
||||
Academy under the following terms and conditions: A worldwide, royalty-free,
|
||||
non-exclusive right to copy, modify, create derivatives, and use, in source and
|
||||
binary forms, is hereby granted, subject to acceptance of this license.
|
||||
|
||||
Copyright © 2015 Academy of Motion Picture Arts and Sciences (A.M.P.A.S.).
|
||||
Portions contributed by others as indicated. All rights reserved.
|
||||
|
||||
Performance of any of the aforementioned acts indicates acceptance to be bound
|
||||
by the following terms and conditions:
|
||||
|
||||
* Copies of source code, in whole or in part, must retain the above copyright
|
||||
notice, this list of conditions and the Disclaimer of Warranty.
|
||||
* Use in binary form must retain the above copyright notice, this list of
|
||||
conditions and the Disclaimer of Warranty in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
* Nothing in this license shall be deemed to grant any rights to trademarks,
|
||||
copyrights, patents, trade secrets or any other intellectual property of
|
||||
A.M.P.A.S. or any contributors, except as expressly stated herein.
|
||||
* Neither the name "A.M.P.A.S." nor the name of any other contributors to this
|
||||
software may be used to endorse or promote products derivative of or based on
|
||||
this software without express prior written permission of A.M.P.A.S. or the
|
||||
contributors, as appropriate.
|
||||
|
||||
This license shall be construed pursuant to the laws of the State of California,
|
||||
and any disputes related thereto shall be subject to the jurisdiction of the
|
||||
courts therein.
|
||||
|
||||
Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL A.M.P.A.S., OR ANY
|
||||
CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, RESITUTIONARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY SPECIFICALLY
|
||||
DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER RELATED TO PATENT OR
|
||||
OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY COLOR ENCODING SYSTEM, OR
|
||||
APPLICATIONS THEREOF, HELD BY PARTIES OTHER THAN A.M.P.A.S.,WHETHER DISCLOSED OR
|
||||
UNDISCLOSED.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
float LinearToAcesCc(float value)
|
||||
{
|
||||
if (value <= 0)
|
||||
return -0.3584474886; // =(log2( pow(2.,-16.))+9.72)/17.52
|
||||
else if (value < pow(2.,-15.))
|
||||
return (log2( pow(2.,-16.) + value * 0.5) + 9.72) / 17.52;
|
||||
else // (value >= pow(2.,-15))
|
||||
return (log2(value) + 9.72) / 17.52;
|
||||
}
|
||||
|
||||
float3 AcesCgToAcesCc(float3 color)
|
||||
{
|
||||
return float3(
|
||||
LinearToAcesCc(color.r),
|
||||
LinearToAcesCc(color.g),
|
||||
LinearToAcesCc(color.b)
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RPI/Math.azsli>
|
||||
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
|
||||
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
#include <Atom/Features/PostProcessing/AcesColorSpaceConversion.azsli>
|
||||
#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli>
|
||||
#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli>
|
||||
#include <3rdParty/Features/PostProcessing/KelvinToRgb.azsli>
|
||||
|
||||
static const float FloatEpsilon = 1.192092896e-07; // 1.0 + FloatEpsilon != 1.0, smallest positive float
|
||||
static const float FloatMin = FLOAT_32_MIN; // Min float number that is positive
|
||||
static const float FloatMax = FLOAT_32_MAX; // Max float number representable
|
||||
|
||||
static const float AcesCcMidGrey = 0.4135884;
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
{
|
||||
// get the framebuffer
|
||||
Texture2D<float4> m_framebuffer;
|
||||
|
||||
// framebuffer sampler
|
||||
Sampler LinearSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Linear;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
float m_colorGradingExposure;
|
||||
float m_colorGradingContrast;
|
||||
float m_colorGradingHueShift;
|
||||
float m_colorGradingPreSaturation;
|
||||
float m_colorFilterIntensity;
|
||||
float m_colorFilterMultiply;
|
||||
float m_whiteBalanceKelvin;
|
||||
float m_whiteBalanceTint;
|
||||
float m_splitToneBalance;
|
||||
float m_splitToneMix;
|
||||
float m_colorGradingPostSaturation;
|
||||
float m_smhShadowsStart;
|
||||
float m_smhShadowsEnd;
|
||||
float m_smhHighlightsStart;
|
||||
float m_smhHighlightsEnd;
|
||||
float m_smhMix;
|
||||
|
||||
float3 m_channelMixingRed;
|
||||
float3 m_channelMixingGreen;
|
||||
float3 m_channelMixingBlue;
|
||||
|
||||
float4 m_colorFilterSwatch;
|
||||
float4 m_splitToneShadowsColor;
|
||||
float4 m_splitToneHighlightsColor;
|
||||
|
||||
float4 m_smhShadowsColor;
|
||||
float4 m_smhMidtonesColor;
|
||||
float4 m_smhHighlightsColor;
|
||||
|
||||
// my color grading output
|
||||
float4 m_color;
|
||||
}
|
||||
|
||||
float SaturateWithEpsilon(float value)
|
||||
{
|
||||
return clamp(value, FloatEpsilon, 1.0f);
|
||||
}
|
||||
|
||||
// Below are the color grading functions. These expect the frame color to be in ACEScg space.
|
||||
// Note that some functions may have some quirks in their implementation and is subject to change.
|
||||
float3 ColorGradePostExposure (float3 frameColor, float exposure)
|
||||
{
|
||||
frameColor *= pow(2.0f, exposure);
|
||||
return frameColor;
|
||||
}
|
||||
|
||||
// The contrast equation is performed in ACEScc (logarithmic) color space.
|
||||
float3 ColorGradingContrast (float3 frameColor, float midgrey, float amount)
|
||||
{
|
||||
const float contrastAdjustment = amount * 0.01f + 1.0f;
|
||||
frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScg, ColorSpaceId::ACEScc);
|
||||
frameColor = (frameColor - midgrey) * contrastAdjustment + midgrey;
|
||||
return frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScc, ColorSpaceId::ACEScg);
|
||||
}
|
||||
|
||||
// The swatchColor param expects a linear RGB value.
|
||||
float3 ColorGradeColorFilter (float3 frameColor, float3 swatchColor, float alpha)
|
||||
{
|
||||
swatchColor = TransformColor(swatchColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
swatchColor *= pow(2.0f, PassSrg::m_colorFilterIntensity);
|
||||
const float3 frameAdjust = frameColor * swatchColor;
|
||||
return frameColor = lerp(frameColor, frameAdjust, alpha);
|
||||
}
|
||||
|
||||
float3 ColorGradeHueShift (float3 frameColor, float amount)
|
||||
{
|
||||
float3 frameHsv = RgbToHsv(frameColor);
|
||||
const float hue = frameHsv.x + amount;
|
||||
frameHsv.x = RotateHue(hue, 0.0, 1.0);
|
||||
return HsvToRgb(frameHsv);
|
||||
}
|
||||
|
||||
float3 ColorGradeSaturation (float3 frameColor, float control)
|
||||
{
|
||||
const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg);
|
||||
return (frameColor - vLuminance) * control + vLuminance;
|
||||
}
|
||||
|
||||
float3 ColorGradeKelvinColorTemp(float3 frameColor, float kelvin)
|
||||
{
|
||||
const float3 kColor = TransformColor(KelvinToRgb(kelvin), ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
const float luminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg);
|
||||
const float3 resHsl = RgbToHsl(frameColor.rgb * kColor.rgb); // Apply Kelvin color and convert to HSL
|
||||
return HslToRgb(float3(resHsl.xy, luminance)); // Preserve luminance
|
||||
}
|
||||
|
||||
// pow(f, e) won't work if f is negative, or may cause inf/NAN.
|
||||
float3 NoNanPow(float3 base, float3 power)
|
||||
{
|
||||
return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power);
|
||||
}
|
||||
|
||||
float3 ColorGradeSplitTone (float3 frameColor, float balance, float mix)
|
||||
{
|
||||
float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2);
|
||||
const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance);
|
||||
const float3 shadows = lerp(0.5, PassSrg::m_splitToneShadowsColor.rgb, 1.0 - t);
|
||||
const float3 highlights = lerp(0.5, PassSrg::m_splitToneHighlightsColor.rgb, t);
|
||||
frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows);
|
||||
frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights);
|
||||
frameSplitTone = NoNanPow(frameSplitTone, 2.2);
|
||||
return lerp(frameColor.rgb, frameSplitTone.rgb, mix);
|
||||
}
|
||||
|
||||
float3 ColorGradeChannelMixer (float3 frameColor)
|
||||
{
|
||||
return mul(float3x3(PassSrg::m_channelMixingRed.rgb,
|
||||
PassSrg::m_channelMixingGreen.rgb,
|
||||
PassSrg::m_channelMixingBlue.rgb),
|
||||
frameColor);
|
||||
}
|
||||
|
||||
float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd,
|
||||
float highlightsStart, float highlightsEnd, float mix,
|
||||
float4 shadowsColor, float4 midtonesColor, float4 highlightsColor)
|
||||
{
|
||||
const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
const float3 midtonesColorACEScg = TransformColor(midtonesColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
const float3 highlightsColorACEScg = TransformColor(highlightsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
|
||||
const float cLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg);
|
||||
const float shadowsWeight = 1.0 - smoothstep(shadowsStart, shadowsEnd, cLuminance);
|
||||
const float highlightsWeight = smoothstep(highlightsStart, highlightsEnd, cLuminance);
|
||||
const float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight;
|
||||
|
||||
const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight +
|
||||
frameColor * midtonesColorACEScg * midtonesWeight +
|
||||
frameColor * highlightsColorACEScg * highlightsWeight;
|
||||
return lerp(frameColor.rgb, frameSmh.rgb, mix);
|
||||
}
|
||||
|
||||
float3 ColorGrade (float3 frameColor)
|
||||
{
|
||||
frameColor = ColorGradePostExposure(frameColor, PassSrg::m_colorGradingExposure);
|
||||
frameColor = ColorGradeKelvinColorTemp(frameColor, PassSrg::m_whiteBalanceKelvin);
|
||||
frameColor = ColorGradingContrast(frameColor, AcesCcMidGrey, PassSrg::m_colorGradingContrast);
|
||||
frameColor = ColorGradeColorFilter(frameColor, PassSrg::m_colorFilterSwatch.rgb,
|
||||
PassSrg::m_colorFilterMultiply);
|
||||
frameColor = max(frameColor, 0.0);
|
||||
frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation);
|
||||
frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneMix);
|
||||
frameColor = ColorGradeChannelMixer(frameColor);
|
||||
frameColor = max(frameColor, 0.0);
|
||||
frameColor = ColorGradeShadowsMidtonesHighlights(frameColor, PassSrg::m_smhShadowsStart, PassSrg::m_smhShadowsEnd,
|
||||
PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhMix,
|
||||
PassSrg::m_smhShadowsColor, PassSrg::m_smhMidtonesColor, PassSrg::m_smhHighlightsColor);
|
||||
frameColor = ColorGradeHueShift(frameColor, PassSrg::m_colorGradingHueShift);
|
||||
frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation);
|
||||
return frameColor.rgb;
|
||||
}
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
PSOutput OUT;
|
||||
|
||||
// Fetch the pixel color from the input texture
|
||||
float3 frameColor = PassSrg::m_framebuffer.Sample(PassSrg::LinearSampler, IN.m_texCoord).rgb;
|
||||
|
||||
OUT.m_color.rgb = ColorGrade(frameColor);
|
||||
OUT.m_color.w = 1;
|
||||
|
||||
return OUT;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"Source" : "HDRColorGrading",
|
||||
|
||||
"DepthStencilState" : {
|
||||
"Depth" : { "Enable" : false }
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
{
|
||||
"EntryPoints":
|
||||
[
|
||||
{
|
||||
"name": "MainVS",
|
||||
"type": "Vertex"
|
||||
},
|
||||
{
|
||||
"name": "MainPS",
|
||||
"type": "Fragment"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue