mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 17:16:14 +03:00
178 lines
5.9 KiB
GLSL
178 lines
5.9 KiB
GLSL
#ifndef TONEMAPPER_FUNCTION_GLSL
|
|
#define TONEMAPPER_FUNCTION_GLSL
|
|
|
|
/*
|
|
** Physical based render code, develop by engineer: qiutanguu.
|
|
*/
|
|
|
|
// GT tonemapper.
|
|
/////////////////////////////////////////////////////////
|
|
|
|
float uchimuraTonemapper(float x, float P, float a, float m, float l, float c, float b) {
|
|
// Uchimura 2017, "HDR theory and practice"
|
|
// Math: https://www.desmos.com/calculator/gslcdxvipg
|
|
// Source: https://www.slideshare.net/nikuque/hdr-theory-and-practicce-jp
|
|
float l0 = ((P - m) * l) / a;
|
|
float L0 = m - m / a;
|
|
float L1 = m + (1.0 - m) / a;
|
|
float S0 = m + l0;
|
|
float S1 = m + a * l0;
|
|
float C2 = (a * P) / (P - S1);
|
|
float CP = -C2 / P;
|
|
|
|
float w0 = 1.0 - smoothstep(0.0, m, x);
|
|
float w2 = step(m + l0, x);
|
|
float w1 = 1.0 - w0 - w2;
|
|
|
|
float T = m * pow(x / m, c) + b;
|
|
float S = P - (P - S1) * exp(CP * (x - S0));
|
|
float L = m + a * (x - m);
|
|
|
|
return T * w0 + L * w1 + S * w2;
|
|
}
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// AMD Tonemapper
|
|
//--------------------------------------------------------------------------------------
|
|
// General tonemapping operator, build 'b' term.
|
|
float ColToneB(float hdrMax, float contrast, float shoulder, float midIn, float midOut)
|
|
{
|
|
return
|
|
-((-pow(midIn, contrast) + (midOut*(pow(hdrMax, contrast * shoulder) * pow(midIn, contrast) -
|
|
pow(hdrMax, contrast) * pow(midIn, contrast*shoulder) * midOut)) /
|
|
(pow(hdrMax, contrast * shoulder) * midOut - pow(midIn, contrast * shoulder) * midOut)) /
|
|
(pow(midIn, contrast * shoulder) * midOut));
|
|
}
|
|
|
|
// General tonemapping operator, build 'c' term.
|
|
float ColToneC(float hdrMax, float contrast, float shoulder, float midIn, float midOut)
|
|
{
|
|
return (pow(hdrMax, contrast*shoulder)*pow(midIn, contrast) - pow(hdrMax, contrast)*pow(midIn, contrast*shoulder)*midOut) /
|
|
(pow(hdrMax, contrast*shoulder)*midOut - pow(midIn, contrast*shoulder)*midOut);
|
|
}
|
|
|
|
// General tonemapping operator, p := {contrast,shoulder,b,c}.
|
|
float ColTone(float x, vec4 p)
|
|
{
|
|
float z = pow(x, p.r);
|
|
return z / (pow(z, p.g)*p.b + p.a);
|
|
}
|
|
|
|
vec3 AMDTonemapper(vec3 color)
|
|
{
|
|
const float hdrMax = 25.0; // How much HDR range before clipping. HDR modes likely need this pushed up to say 25.0.
|
|
const float contrast = 2.0; // Use as a baseline to tune the amount of contrast the tonemapper has.
|
|
const float shoulder = 1.0; // Likely don't need to mess with this factor, unless matching existing tonemapper is not working well..
|
|
const float midIn = 0.18; // most games will have a {0.0 to 1.0} range for LDR so midIn should be 0.18.
|
|
const float midOut = 0.18; // Use for LDR. For HDR10 10:10:10:2 use maybe 0.18/25.0 to start. For scRGB, I forget what a good starting point is, need to re-calculate.
|
|
|
|
float b = ColToneB(hdrMax, contrast, shoulder, midIn, midOut);
|
|
float c = ColToneC(hdrMax, contrast, shoulder, midIn, midOut);
|
|
|
|
#define EPS 1e-6f
|
|
float peak = max(color.r, max(color.g, color.b));
|
|
peak = max(EPS, peak);
|
|
|
|
vec3 ratio = color / peak;
|
|
peak = ColTone(peak, vec4(contrast, shoulder, b, c) );
|
|
// then process ratio
|
|
|
|
// probably want send these pre-computed (so send over saturation/crossSaturation as a constant)
|
|
float crosstalk = 4.0; // controls amount of channel crosstalk
|
|
float saturation = contrast; // full tonal range saturation control
|
|
float crossSaturation = contrast*16.0; // crosstalk saturation
|
|
|
|
float white = 1.0;
|
|
|
|
// wrap crosstalk in transform
|
|
ratio = pow(abs(ratio), vec3(saturation / crossSaturation));
|
|
ratio = mix(ratio, vec3(white), vec3(pow(peak, crosstalk)));
|
|
ratio = pow(abs(ratio), vec3(crossSaturation));
|
|
|
|
// then apply ratio to peak
|
|
color = peak * ratio;
|
|
return color;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Lottes 2016, "Advanced Techniques and Optimization of HDR Color Pipelines" - https://gpuopen.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf
|
|
float TonemapLottes(float x, float contrast)
|
|
{
|
|
const float a = 1.6 * contrast;
|
|
const float d = 0.977;
|
|
const float hdrMax = 8.0;
|
|
const float midIn = 0.18;
|
|
const float midOut = 0.267;
|
|
|
|
// Can be precomputed
|
|
const float b =
|
|
(-pow(midIn, a) + pow(hdrMax, a) * midOut) /
|
|
((pow(hdrMax, a * d) - pow(midIn, a * d)) * midOut);
|
|
const float c =
|
|
(pow(hdrMax, a * d) * pow(midIn, a) - pow(hdrMax, a) * pow(midIn, a * d) * midOut) /
|
|
((pow(hdrMax, a * d) - pow(midIn, a * d)) * midOut);
|
|
|
|
return pow(x, a) / (pow(x, a * d) * b + c);
|
|
}
|
|
|
|
vec3 TonemapLottesx3(vec3 c, float contrast)
|
|
{
|
|
return vec3(
|
|
TonemapLottes(c.x, contrast),
|
|
TonemapLottes(c.y, contrast),
|
|
TonemapLottes(c.z, contrast)
|
|
);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
//== ACESFitted ===========================
|
|
// Baking Lab
|
|
// by MJP and David Neubelt
|
|
// http://mynameismjp.wordpress.com/
|
|
// All code licensed under the MIT license
|
|
//=========================================
|
|
|
|
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
|
const mat3 ACESInputMat = mat3
|
|
(
|
|
0.59719, 0.07600, 0.02840,
|
|
0.35458, 0.90834, 0.13383,
|
|
0.04823, 0.01566, 0.83777
|
|
);
|
|
|
|
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
|
const mat3 ACESOutputMat = mat3
|
|
(
|
|
1.60475, -0.10208, -0.00327,
|
|
-0.53108, 1.10813, -0.07276,
|
|
-0.07367, -0.00605, 1.07602
|
|
);
|
|
|
|
// ACES filmic tone map approximation
|
|
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
|
vec3 RRTAndODTFit(vec3 color)
|
|
{
|
|
vec3 a = color * (color + 0.0245786) - 0.000090537;
|
|
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
|
|
return a / b;
|
|
}
|
|
|
|
// Tone mapping
|
|
vec3 toneMapACES(vec3 color)
|
|
{
|
|
color = ACESInputMat * color;
|
|
|
|
// Apply RRT and ODT
|
|
color = RRTAndODTFit(color);
|
|
color = ACESOutputMat * color;
|
|
|
|
// Clamp to [0, 1]
|
|
color = clamp(color, 0.0, 1.0);
|
|
return color;
|
|
}
|
|
|
|
#endif |