cm: Use precomputed primaries conversion (#9814)

This commit is contained in:
UjinT34 2025-04-29 22:29:40 +03:00 committed by GitHub
parent 94bc132084
commit 49974d5e34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 164 additions and 136 deletions

View file

@ -11,7 +11,6 @@ uniform int texType; // eTextureType: 0 - rgba, 1 - rgbx, 2 - ext
// uniform int skipCM;
uniform int sourceTF; // eTransferFunction
uniform int targetTF; // eTransferFunction
uniform mat4x2 sourcePrimaries;
uniform mat4x2 targetPrimaries;
uniform float alpha;
@ -43,7 +42,7 @@ void main() {
discard;
// this shader shouldn't be used when skipCM == 1
pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries);
pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries);
if (applyTint == 1)
pixColor = vec4(pixColor.rgb * tint.rgb, pixColor[3]);

View file

@ -1,8 +1,12 @@
uniform vec2 srcTFRange;
uniform vec2 dstTFRange;
uniform float maxLuminance;
uniform float dstMaxLuminance;
uniform float dstRefLuminance;
uniform float sdrSaturation;
uniform float sdrBrightnessMultiplier;
uniform mat3 convertMatrix;
//enum eTransferFunction
#define CM_TRANSFER_FUNCTION_BT1886 1
@ -117,30 +121,8 @@ vec4 toLinear(vec4 color, int tf) {
return color;
}
vec4 toNit(vec4 color, int tf) {
if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR)
color.rgb = color.rgb * SDR_MAX_LUMINANCE;
else {
switch (tf) {
case CM_TRANSFER_FUNCTION_ST2084_PQ:
color.rgb = color.rgb * (HDR_MAX_LUMINANCE - HDR_MIN_LUMINANCE) + HDR_MIN_LUMINANCE; break;
case CM_TRANSFER_FUNCTION_HLG:
color.rgb = color.rgb * (HLG_MAX_LUMINANCE - HDR_MIN_LUMINANCE) + HDR_MIN_LUMINANCE; break;
case CM_TRANSFER_FUNCTION_GAMMA22:
case CM_TRANSFER_FUNCTION_GAMMA28:
case CM_TRANSFER_FUNCTION_BT1886:
case CM_TRANSFER_FUNCTION_ST240:
case CM_TRANSFER_FUNCTION_LOG_100:
case CM_TRANSFER_FUNCTION_LOG_316:
case CM_TRANSFER_FUNCTION_XVYCC:
case CM_TRANSFER_FUNCTION_EXT_SRGB:
case CM_TRANSFER_FUNCTION_ST428:
case CM_TRANSFER_FUNCTION_SRGB:
default:
color.rgb = color.rgb * (SDR_MAX_LUMINANCE - SDR_MIN_LUMINANCE) + SDR_MIN_LUMINANCE; break;
}
}
vec4 toNit(vec4 color, vec2 range) {
color.rgb = color.rgb * (range[1] - range[0]) + range[0];
return color;
}
@ -195,33 +177,13 @@ vec4 fromLinear(vec4 color, int tf) {
return color;
}
vec4 fromLinearNit(vec4 color, int tf) {
vec4 fromLinearNit(vec4 color, int tf, vec2 range) {
if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR)
color.rgb = color.rgb / SDR_MAX_LUMINANCE;
else {
color.rgb /= max(color.a, 0.001);
switch (tf) {
case CM_TRANSFER_FUNCTION_ST2084_PQ:
color.rgb = (color.rgb - HDR_MIN_LUMINANCE) / (HDR_MAX_LUMINANCE - HDR_MIN_LUMINANCE); break;
case CM_TRANSFER_FUNCTION_HLG:
color.rgb = (color.rgb - HDR_MIN_LUMINANCE) / (HLG_MAX_LUMINANCE - HDR_MIN_LUMINANCE); break;
case CM_TRANSFER_FUNCTION_GAMMA22:
case CM_TRANSFER_FUNCTION_GAMMA28:
case CM_TRANSFER_FUNCTION_BT1886:
case CM_TRANSFER_FUNCTION_ST240:
case CM_TRANSFER_FUNCTION_LOG_100:
case CM_TRANSFER_FUNCTION_LOG_316:
case CM_TRANSFER_FUNCTION_XVYCC:
case CM_TRANSFER_FUNCTION_EXT_SRGB:
case CM_TRANSFER_FUNCTION_ST428:
case CM_TRANSFER_FUNCTION_SRGB:
default:
color.rgb = (color.rgb - SDR_MIN_LUMINANCE) / (SDR_MAX_LUMINANCE - SDR_MIN_LUMINANCE); break;
}
color.rgb = (color.rgb - range[0]) / (range[1] - range[0]);
color.rgb = fromLinearRGB(color.rgb, tf);
color.rgb *= color.a;
}
return color;
@ -250,13 +212,6 @@ mat3 primaries2xyz(mat4x2 primaries) {
);
}
// const vec2 D65 = vec2(0.3127, 0.3290);
const mat3 Bradford = mat3(
0.8951, 0.2664, -0.1614,
-0.7502, 1.7135, 0.0367,
0.0389, -0.0685, 1.0296
);
const mat3 BradfordInv = inverse(Bradford);
mat3 adaptWhite(vec2 src, vec2 dst) {
if (src == dst)
@ -266,6 +221,13 @@ mat3 adaptWhite(vec2 src, vec2 dst) {
0.0, 0.0, 1.0
);
// const vec2 D65 = vec2(0.3127, 0.3290);
const mat3 Bradford = mat3(
0.8951, 0.2664, -0.1614,
-0.7502, 1.7135, 0.0367,
0.0389, -0.0685, 1.0296
);
mat3 BradfordInv = inverse(Bradford);
vec3 srcXYZ = xy2xyz(src);
vec3 dstXYZ = xy2xyz(dst);
vec3 factors = (Bradford * dstXYZ) / (Bradford * srcXYZ);
@ -287,21 +249,37 @@ const mat3 BT2020toLMS = mat3(
-0.1922, 1.1004, 0.0755,
0.0070, 0.0749, 0.8434
);
const mat3 LMStoBT2020 = inverse(BT2020toLMS);
//const mat3 LMStoBT2020 = inverse(BT2020toLMS);
const mat3 LMStoBT2020 = mat3(
2.0701800566956135096, -1.3264568761030210255, 0.20661600684785517081,
0.36498825003265747974, 0.68046736285223514102, -0.045421753075853231409,
-0.049595542238932107896, -0.049421161186757487412, 1.1879959417328034394
);
const mat3 ICtCpPQ = transpose(mat3(
2048.0, 2048.0, 0.0,
6610.0, -13613.0, 7003.0,
17933.0, -17390.0, -543.0
) / 4096.0);
const mat3 ICtCpPQInv = inverse(ICtCpPQ);
// const mat3 ICtCpPQ = transpose(mat3(
// 2048.0, 2048.0, 0.0,
// 6610.0, -13613.0, 7003.0,
// 17933.0, -17390.0, -543.0
// ) / 4096.0);
const mat3 ICtCpPQ = mat3(
0.5, 1.61376953125, 4.378173828125,
0.5, -3.323486328125, -4.24560546875,
0.0, 1.709716796875, -0.132568359375
);
//const mat3 ICtCpPQInv = inverse(ICtCpPQ);
const mat3 ICtCpPQInv = mat3(
1.0, 1.0, 1.0,
0.0086090370379327566, -0.0086090370379327566, 0.560031335710679118,
0.11102962500302595656, -0.11102962500302595656, -0.32062717498731885185
);
const mat3 ICtCpHLG = transpose(mat3(
2048.0, 2048.0, 0.0,
3625.0, -7465.0, 3840.0,
9500.0, -9212.0, -288.0
) / 4096.0);
const mat3 ICtCpHLGInv = inverse(ICtCpHLG);
// unused for now
// const mat3 ICtCpHLG = transpose(mat3(
// 2048.0, 2048.0, 0.0,
// 3625.0, -7465.0, 3840.0,
// 9500.0, -9212.0, -288.0
// ) / 4096.0);
// const mat3 ICtCpHLGInv = inverse(ICtCpHLG);
vec4 tonemap(vec4 color, mat3 dstXYZ) {
if (maxLuminance < dstMaxLuminance * 1.01)
@ -339,23 +317,17 @@ vec4 tonemap(vec4 color, mat3 dstXYZ) {
return vec4(fromLMS * toLinear(vec4(ICtCpPQInv * ICtCp, 1.0), CM_TRANSFER_FUNCTION_ST2084_PQ).rgb * HDR_MAX_LUMINANCE, color[3]);
}
vec4 doColorManagement(vec4 pixColor, int srcTF, mat4x2 srcPrimaries, int dstTF, mat4x2 dstPrimaries) {
vec4 doColorManagement(vec4 pixColor, int srcTF, int dstTF, mat4x2 dstPrimaries) {
pixColor.rgb /= max(pixColor.a, 0.001);
pixColor.rgb = toLinearRGB(pixColor.rgb, srcTF);
mat3 srcxyz = primaries2xyz(srcPrimaries);
mat3 dstxyz;
if (srcPrimaries == dstPrimaries)
dstxyz = srcxyz;
else {
dstxyz = primaries2xyz(dstPrimaries);
pixColor = convertPrimaries(pixColor, srcxyz, srcPrimaries[3], dstxyz, dstPrimaries[3]);
}
pixColor = toNit(pixColor, srcTF);
pixColor.rgb = convertMatrix * pixColor.rgb;
pixColor = toNit(pixColor, srcTFRange);
pixColor.rgb *= pixColor.a;
mat3 dstxyz = primaries2xyz(dstPrimaries);
pixColor = tonemap(pixColor, dstxyz);
pixColor = fromLinearNit(pixColor, dstTF);
pixColor = fromLinearNit(pixColor, dstTF, dstTFRange);
if (srcTF == CM_TRANSFER_FUNCTION_SRGB && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
pixColor = saturate(pixColor, srcxyz, sdrSaturation);
pixColor = saturate(pixColor, dstxyz, sdrSaturation);
pixColor.rgb /= pixColor.a;
pixColor.rgb *= sdrBrightnessMultiplier;
pixColor.rgb *= pixColor.a;

View file

@ -11,8 +11,6 @@ uniform float brightness;
uniform int skipCM;
uniform int sourceTF; // eTransferFunction
uniform int targetTF; // eTransferFunction
uniform mat4x2 sourcePrimaries;
uniform mat4x2 targetPrimaries;
#include "CM.glsl"
@ -29,17 +27,9 @@ void main() {
if (sourceTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
pixColor.rgb /= sdrBrightnessMultiplier;
}
pixColor.rgb = toLinearRGB(pixColor.rgb, sourceTF);
mat3 srcxyz = primaries2xyz(sourcePrimaries);
mat3 dstxyz;
if (sourcePrimaries == targetPrimaries)
dstxyz = srcxyz;
else {
dstxyz = primaries2xyz(targetPrimaries);
pixColor = convertPrimaries(pixColor, srcxyz, sourcePrimaries[3], dstxyz, targetPrimaries[3]);
}
pixColor = toNit(pixColor, sourceTF);
pixColor = fromLinearNit(pixColor, targetTF);
pixColor.rgb = convertMatrix * toLinearRGB(pixColor.rgb, sourceTF);
pixColor = toNit(pixColor, srcTFRange);
pixColor = fromLinearNit(pixColor, targetTF, dstTFRange);
}
// contrast

View file

@ -7,7 +7,6 @@ in vec2 v_texcoord;
uniform int skipCM;
uniform int sourceTF; // eTransferFunction
uniform int targetTF; // eTransferFunction
uniform mat4x2 sourcePrimaries;
uniform mat4x2 targetPrimaries;
uniform vec2 fullSizeUntransformed;
@ -175,7 +174,7 @@ void main() {
pixColor.rgb *= pixColor[3];
if (skipCM == 0)
pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries);
pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries);
pixColor *= alpha * additionalAlpha;

View file

@ -8,7 +8,6 @@ in vec2 v_texcoord;
uniform int skipCM;
uniform int sourceTF; // eTransferFunction
uniform int targetTF; // eTransferFunction
uniform mat4x2 sourcePrimaries;
uniform mat4x2 targetPrimaries;
uniform vec2 topLeft;
@ -94,7 +93,7 @@ void main() {
pixColor.rgb *= pixColor[3];
if (skipCM == 0)
pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries);
pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries);
fragColor = pixColor;
}