1
0
Fork 0
This commit is contained in:
Allen Pestaluky 2025-02-28 01:36:16 +01:00 committed by GitHub
commit 94e25119b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 53 additions and 69 deletions

View File

@ -425,11 +425,11 @@
Uses a film-like tonemapping curve to prevent clipping of bright values and provide better contrast than [constant TONE_MAPPER_REINHARDT]. Slightly slower than [constant TONE_MAPPER_REINHARDT].
</constant>
<constant name="TONE_MAPPER_ACES" value="3" enum="ToneMapper">
Uses a high-contrast film-like tonemapping curve and desaturates bright values for a more realistic appearance. Slightly slower than [constant TONE_MAPPER_FILMIC].
Uses a high-contrast film-like tonemapping curve and desaturates bright values for a more realistic appearance. Slightly slower than [constant TONE_MAPPER_FILMIC] and similar performance to [constant TONE_MAPPER_AGX].
[b]Note:[/b] This tonemapping operator is called "ACES Fitted" in Godot 3.x.
</constant>
<constant name="TONE_MAPPER_AGX" value="4" enum="ToneMapper">
Uses a film-like tonemapping curve and desaturates bright values for a more realistic appearance. Better than other tonemappers at maintaining the hue of colors as they become brighter. The slowest tonemapping option.
Uses a film-like tonemapping curve and desaturates bright values for a more realistic appearance. Better than other tonemappers at maintaining the hue of colors as they become brighter. Slightly slower than [constant TONE_MAPPER_FILMIC] and similar performance to [constant TONE_MAPPER_ACES].
[b]Note:[/b] [member tonemap_white] is fixed at a value of [code]16.29[/code], which makes [constant TONE_MAPPER_AGX] unsuitable for use with the Mobile rendering method.
</constant>
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="GlowBlendMode">

View File

@ -5403,11 +5403,11 @@
Uses a film-like tonemapping curve to prevent clipping of bright values and provide better contrast than [constant ENV_TONE_MAPPER_REINHARD]. Slightly slower than [constant ENV_TONE_MAPPER_REINHARD].
</constant>
<constant name="ENV_TONE_MAPPER_ACES" value="3" enum="EnvironmentToneMapper">
Uses a high-contrast film-like tonemapping curve and desaturates bright values for a more realistic appearance. Slightly slower than [constant ENV_TONE_MAPPER_FILMIC].
Uses a high-contrast film-like tonemapping curve and desaturates bright values for a more realistic appearance. Slightly slower than [constant ENV_TONE_MAPPER_FILMIC] and similar performance to [constant ENV_TONE_MAPPER_AGX].
[b]Note:[/b] This tonemapping operator is called "ACES Fitted" in Godot 3.x.
</constant>
<constant name="ENV_TONE_MAPPER_AGX" value="4" enum="EnvironmentToneMapper">
Uses a film-like tonemapping curve and desaturates bright values for a more realistic appearance. Better than other tonemappers at maintaining the hue of colors as they become brighter. The slowest tonemapping option.
Uses a film-like tonemapping curve and desaturates bright values for a more realistic appearance. Better than other tonemappers at maintaining the hue of colors as they become brighter. Slightly slower than [constant ENV_TONE_MAPPER_FILMIC] and similar performance to [constant ENV_TONE_MAPPER_ACES].
[b]Note:[/b] [member Environment.tonemap_white] is fixed at a value of [code]16.29[/code], which makes [constant ENV_TONE_MAPPER_AGX] unsuitable for use with the Mobile rendering method.
</constant>
<constant name="ENV_SSR_ROUGHNESS_QUALITY_DISABLED" value="0" enum="EnvironmentSSRRoughnessQuality">

View File

@ -84,21 +84,14 @@ vec3 tonemap_aces(vec3 color, float p_white) {
return color_tonemapped / p_white_tonemapped;
}
// Polynomial approximation of EaryChow's AgX sigmoid curve.
// x must be within the range [0.0, 1.0]
vec3 agx_contrast_approx(vec3 x) {
// Generated with Excel trendline
// Input data: Generated using python sigmoid with EaryChow's configuration and 57 steps
// Additional padding values were added to give correct intersections at 0.0 and 1.0
// 6th order, intercept of 0.0 to remove an operation and ensure intersection at 0.0
vec3 x2 = x * x;
vec3 x4 = x2 * x2;
return 0.021 * x + 4.0111 * x2 - 25.682 * x2 * x + 70.359 * x4 - 74.778 * x4 * x + 27.069 * x4 * x2;
}
// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender.
// This is a simplified glsl implementation of EaryChow's AgX that is used by Blender.
// Input: unbounded linear Rec. 709
// Output: unbounded linear Rec. 709 (Most any value you care about will be within [0.0, 1.0], thus safe to clip.)
// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses.
// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py
// Changes: Negative clipping in input color space without "guard rails" and no chroma-angle mixing.
// Repository for this code: https://github.com/allenwp/AgX-GLSL-Shaders
// Refer to source repository for other matrices if input/output color space ever changes.
vec3 tonemap_agx(vec3 color) {
// Combined linear sRGB to linear Rec 2020 and Blender AgX inset matrices:
const mat3 srgb_to_rec2020_agx_inset_matrix = mat3(
@ -112,11 +105,13 @@ vec3 tonemap_agx(vec3 color) {
-0.85585845117807513559, 1.3264510741502356555, -0.23822464068860595117,
-0.10886710826831608324, -0.027084020983874825605, 1.402665347143271889);
// LOG2_MIN = -10.0
// LOG2_MAX = +6.5
// MIDDLE_GRAY = 0.18
const float min_ev = -12.4739311883324; // log2(pow(2, LOG2_MIN) * MIDDLE_GRAY)
const float max_ev = 4.02606881166759; // log2(pow(2, LOG2_MAX) * MIDDLE_GRAY)
// Terms of Timothy Lottes' tonemapping curve equation:
// c and b are calculated based on a and d with AgX mid and max parameters
// using the Mathematica notebook in the source AgX-GLSL-Shaders repository.
const float a = 1.36989969378897;
const float c = 0.3589386656982;
const float b = 1.4325264680543;
const float e = a * 0.903916850555009; // = a * d
// Large negative values in one channel and large positive values in other
// channels can result in a colour that appears darker and more saturated than
@ -125,28 +120,25 @@ vec3 tonemap_agx(vec3 color) {
// This is done before the Rec. 2020 transform to allow the Rec. 2020
// transform to be combined with the AgX inset matrix. This results in a loss
// of color information that could be correctly interpreted within the
// Rec. 2020 color space as positive RGB values, but it is less common for Godot
// to provide this function with negative sRGB values and therefore not worth
// Rec. 2020 color space as positive RGB values, but is often not worth
// the performance cost of an additional matrix multiplication.
// A value of 2e-10 intentionally introduces insignificant error to prevent
// log2(0.0) after the inset matrix is applied; color will be >= 1e-10 after
// the matrix transform.
color = max(color, 2e-10);
// Do AGX in rec2020 to match Blender and then apply inset matrix.
// Apply inset matrix.
color = srgb_to_rec2020_agx_inset_matrix * color;
// Log2 space encoding.
// Must be clamped because agx_contrast_approx may not work
// well with values outside of the range [0.0, 1.0]
color = clamp(log2(color), min_ev, max_ev);
color = (color - min_ev) / (max_ev - min_ev);
// Apply sigmoid function approximation.
color = agx_contrast_approx(color);
// Convert back to linear before applying outset matrix.
color = pow(color, vec3(2.4));
// Use Timothy Lottes' tonemapping equation to approximate AgX's curve.
// Slide 44 of "Advanced Techniques and Optimization of HDR Color Pipelines"
// https://gpuopen.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf
// color = pow(color, a);
// color = color / (pow(color, d) * b + c);
// Simplified using hardware-implemented shader operations.
// Thanks to Stephen Hill for this optimization tip!
color = log2(color);
color = exp2(color * a) / (exp2(color * e) * b + c);
// Apply outset to make the result more chroma-laden and then go back to linear sRGB.
color = agx_outset_rec2020_to_srgb_matrix * color;

View File

@ -1278,7 +1278,7 @@ void Environment::_bind_methods() {
ADD_GROUP("Tonemap", "tonemap_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES,AgX"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_tonemap_white", "get_tonemap_white");
// SSR

View File

@ -264,21 +264,14 @@ vec3 tonemap_aces(vec3 color, float white) {
return color_tonemapped / white_tonemapped;
}
// Polynomial approximation of EaryChow's AgX sigmoid curve.
// x must be within the range [0.0, 1.0]
vec3 agx_contrast_approx(vec3 x) {
// Generated with Excel trendline
// Input data: Generated using python sigmoid with EaryChow's configuration and 57 steps
// Additional padding values were added to give correct intersections at 0.0 and 1.0
// 6th order, intercept of 0.0 to remove an operation and ensure intersection at 0.0
vec3 x2 = x * x;
vec3 x4 = x2 * x2;
return 0.021 * x + 4.0111 * x2 - 25.682 * x2 * x + 70.359 * x4 - 74.778 * x4 * x + 27.069 * x4 * x2;
}
// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender.
// This is a simplified glsl implementation of EaryChow's AgX that is used by Blender.
// Input: unbounded linear Rec. 709
// Output: unbounded linear Rec. 709 (Most any value you care about will be within [0.0, 1.0], thus safe to clip.)
// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses.
// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py
// Changes: Negative clipping in input color space without "guard rails" and no chroma-angle mixing.
// Repository for this code: https://github.com/allenwp/AgX-GLSL-Shaders
// Refer to source repository for other matrices if input/output color space ever changes.
vec3 tonemap_agx(vec3 color) {
// Combined linear sRGB to linear Rec 2020 and Blender AgX inset matrices:
const mat3 srgb_to_rec2020_agx_inset_matrix = mat3(
@ -292,11 +285,13 @@ vec3 tonemap_agx(vec3 color) {
-0.85585845117807513559, 1.3264510741502356555, -0.23822464068860595117,
-0.10886710826831608324, -0.027084020983874825605, 1.402665347143271889);
// LOG2_MIN = -10.0
// LOG2_MAX = +6.5
// MIDDLE_GRAY = 0.18
const float min_ev = -12.4739311883324; // log2(pow(2, LOG2_MIN) * MIDDLE_GRAY)
const float max_ev = 4.02606881166759; // log2(pow(2, LOG2_MAX) * MIDDLE_GRAY)
// Terms of Timothy Lottes' tonemapping curve equation:
// c and b are calculated based on a and d with AgX mid and max parameters
// using the Mathematica notebook in the source AgX-GLSL-Shaders repository.
const float a = 1.36989969378897;
const float c = 0.3589386656982;
const float b = 1.4325264680543;
const float e = a * 0.903916850555009; // = a * d
// Large negative values in one channel and large positive values in other
// channels can result in a colour that appears darker and more saturated than
@ -305,28 +300,25 @@ vec3 tonemap_agx(vec3 color) {
// This is done before the Rec. 2020 transform to allow the Rec. 2020
// transform to be combined with the AgX inset matrix. This results in a loss
// of color information that could be correctly interpreted within the
// Rec. 2020 color space as positive RGB values, but it is less common for Godot
// to provide this function with negative sRGB values and therefore not worth
// Rec. 2020 color space as positive RGB values, but is often not worth
// the performance cost of an additional matrix multiplication.
// A value of 2e-10 intentionally introduces insignificant error to prevent
// log2(0.0) after the inset matrix is applied; color will be >= 1e-10 after
// the matrix transform.
color = max(color, 2e-10);
// Do AGX in rec2020 to match Blender and then apply inset matrix.
// Apply inset matrix.
color = srgb_to_rec2020_agx_inset_matrix * color;
// Log2 space encoding.
// Must be clamped because agx_contrast_approx may not work
// well with values outside of the range [0.0, 1.0]
color = clamp(log2(color), min_ev, max_ev);
color = (color - min_ev) / (max_ev - min_ev);
// Apply sigmoid function approximation.
color = agx_contrast_approx(color);
// Convert back to linear before applying outset matrix.
color = pow(color, vec3(2.4));
// Use Timothy Lottes' tonemapping equation to approximate AgX's curve.
// Slide 44 of "Advanced Techniques and Optimization of HDR Color Pipelines"
// https://gpuopen.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf
// color = pow(color, a);
// color = color / (pow(color, d) * b + c);
// Simplified using hardware-implemented shader operations.
// Thanks to Stephen Hill for this optimization tip!
color = log2(color);
color = exp2(color * a) / (exp2(color * e) * b + c);
// Apply outset to make the result more chroma-laden and then go back to linear sRGB.
color = agx_outset_rec2020_to_srgb_matrix * color;