Skip to content

Instantly share code, notes, and snippets.

@KelSolaar
Last active December 17, 2020 06:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save KelSolaar/1213139203911a72fef531c32c3d4ec2 to your computer and use it in GitHub Desktop.
Save KelSolaar/1213139203911a72fef531c32c3d4ec2 to your computer and use it in GitHub Desktop.
Global Tonemapping Operator - Lottes (2016)
// https://github.com/KhronosGroup/glTF-Compressonator/blob/master/Compressonator/Applications/_Plugins/C3DModel_viewers/glTF_DX12_EX/DX12Util/shaders/Tonemapping.hlsl
kernel GlobalTonemappingOperator_Lottes2016 : ImageComputationKernel<ePixelWise>
{
Image<eRead, eAccessPoint, eEdgeClamped> src;
Image<eWrite> dst;
param:
float hdrMax;
float contrast;
float shoulder;
float midIn;
float midOut;
void define() {
defineParam(hdrMax, "hdrMax", 16.0f);
defineParam(contrast, "contrast", 2.0f);
defineParam(shoulder, "shoulder", 1.0f);
defineParam(midIn, "midIn", 0.18f);
defineParam(midOut, "midOut", 0.18f);
}
void init() {
}
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, float4 p)
{
float z = pow(x, p.x);
return z / (pow(z, p.y)*p.z + p.w);
}
float3 lerp(float3 a, float3 b, float c) {
return (1 - c) * a + c * b;
}
float3 GlobalTonemappingOperator(float3 color)
{
float b = ColToneB(hdrMax, contrast, shoulder, midIn, midOut);
float c = ColToneC(hdrMax, contrast, shoulder, midIn, midOut);
float peak = max(color.x, max(color.y, color.z));
float3 ratio = color / peak;
peak = ColTone(peak, float4(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
float saturationCrossSaturation = saturation / crossSaturation;
ratio = pow(fabs(ratio), float3(saturationCrossSaturation, saturationCrossSaturation, saturationCrossSaturation));
ratio = lerp(ratio, float3(white, white, white), pow(peak, crosstalk));
ratio = pow(fabs(ratio), float3(crossSaturation, crossSaturation, crossSaturation));
// then apply ratio to peak
color = peak * ratio;
return color;
}
void process() {
// Read the input image
SampleType(src) input = src();
// Isolate the RGB components
float3 srcPixel(input.x, input.y, input.z);
float3 tonemappedPixel = GlobalTonemappingOperator(srcPixel);
// Write the result to the output image
dst() = float4(tonemappedPixel.x, tonemappedPixel.y, tonemappedPixel.z, input.w);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment