mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-05-12 23:00:36 +01:00
cm: Use precomputed primaries conversion (#9814)
This commit is contained in:
parent
94bc132084
commit
49974d5e34
10 changed files with 164 additions and 136 deletions
|
@ -8,8 +8,6 @@
|
|||
|
||||
using namespace NColorManagement;
|
||||
|
||||
static uint64_t lastImageID = 0; // FIXME use for deduplication
|
||||
|
||||
CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resource) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
@ -191,14 +189,13 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
|||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings.id = ++lastImageID;
|
||||
RESOURCE->settings.windowsScRGB = true;
|
||||
RESOURCE->settings.primariesNamed = NColorManagement::CM_PRIMARIES_SRGB;
|
||||
RESOURCE->settings.primariesNameSet = true;
|
||||
RESOURCE->settings.primaries = NColorPrimaries::BT709;
|
||||
RESOURCE->settings.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||
RESOURCE->settings.luminances.reference = 203;
|
||||
RESOURCE->resource()->sendReady(RESOURCE->settings.id);
|
||||
RESOURCE->resource()->sendReady(RESOURCE->settings.updateId());
|
||||
});
|
||||
|
||||
m_resource->setOnDestroy([this](CWpColorManagerV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
@ -239,9 +236,7 @@ CColorManagementOutput::CColorManagementOutput(SP<CWpColorManagementOutputV1> re
|
|||
RESOURCE->m_resource->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_NO_OUTPUT, "No output");
|
||||
else {
|
||||
RESOURCE->settings = m_monitor->imageDescription;
|
||||
if (RESOURCE->settings.id)
|
||||
RESOURCE->settings.id = ++lastImageID;
|
||||
RESOURCE->m_resource->sendReady(RESOURCE->settings.id); // FIXME: create correct id
|
||||
RESOURCE->m_resource->sendReady(RESOURCE->settings.updateId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -383,10 +378,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CWpColorMana
|
|||
m_currentPreferred = RESOURCE;
|
||||
|
||||
m_currentPreferred->settings = g_pCompositor->getPreferredImageDescription();
|
||||
if (!m_currentPreferred->settings.id)
|
||||
m_currentPreferred->settings.id = ++lastImageID;
|
||||
|
||||
RESOURCE->resource()->sendReady(++lastImageID); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(m_currentPreferred->settings.updateId());
|
||||
});
|
||||
|
||||
m_resource->setGetPreferredParametric([this](CWpColorManagementSurfaceFeedbackV1* r, uint32_t id) {
|
||||
|
@ -419,7 +411,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CWpColorMana
|
|||
return;
|
||||
}
|
||||
|
||||
RESOURCE->resource()->sendReady(++lastImageID); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(m_currentPreferred->settings.updateId());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -467,8 +459,7 @@ CColorManagementIccCreator::CColorManagementIccCreator(SP<CWpImageDescriptionCre
|
|||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings = settings;
|
||||
settings.id = ++lastImageID;
|
||||
RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(settings.updateId());
|
||||
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
|
@ -522,8 +513,7 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CWpImage
|
|||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings = settings;
|
||||
settings.id = ++lastImageID;
|
||||
RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(settings.updateId());
|
||||
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#include "ColorManagement.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace NColorManagement {
|
||||
const SPCPRimaries& getPrimaries(ePrimaries name) {
|
||||
static uint32_t lastImageID = 0;
|
||||
static std::map<uint32_t, SImageDescription> knownDescriptionIds; // expected to be small
|
||||
|
||||
const SPCPRimaries& getPrimaries(ePrimaries name) {
|
||||
switch (name) {
|
||||
case CM_PRIMARIES_SRGB: return NColorPrimaries::BT709;
|
||||
case CM_PRIMARIES_BT2020: return NColorPrimaries::BT2020;
|
||||
|
@ -17,4 +21,26 @@ namespace NColorManagement {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO make image descriptions immutable and always set an id
|
||||
|
||||
uint32_t SImageDescription::findId() const {
|
||||
for (auto it = knownDescriptionIds.begin(); it != knownDescriptionIds.end(); ++it) {
|
||||
if (it->second == *this)
|
||||
return it->first;
|
||||
}
|
||||
|
||||
const auto newId = ++lastImageID;
|
||||
knownDescriptionIds.insert(std::make_pair(newId, *this));
|
||||
return newId;
|
||||
}
|
||||
|
||||
uint32_t SImageDescription::getId() const {
|
||||
return id > 0 ? id : findId();
|
||||
}
|
||||
|
||||
uint32_t SImageDescription::updateId() {
|
||||
id = 0;
|
||||
id = findId();
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "color-management-v1.hpp"
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
|
||||
#define SDR_MIN_LUMINANCE 0.2
|
||||
#define SDR_MAX_LUMINANCE 80.0
|
||||
#define HDR_MIN_LUMINANCE 0.005
|
||||
#define HDR_MAX_LUMINANCE 10000.0
|
||||
#define HLG_MAX_LUMINANCE 1000.0
|
||||
|
||||
namespace NColorManagement {
|
||||
enum ePrimaries : uint8_t {
|
||||
|
@ -47,19 +54,7 @@ namespace NColorManagement {
|
|||
return (eTransferFunction)tf;
|
||||
}
|
||||
|
||||
struct SPCPRimaries {
|
||||
struct xy { //NOLINT(readability-identifier-naming)
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
bool operator==(const xy& p2) const {
|
||||
return x == p2.x && y == p2.y;
|
||||
}
|
||||
} red, green, blue, white;
|
||||
bool operator==(const SPCPRimaries& p2) const {
|
||||
return red == p2.red && green == p2.green && blue == p2.blue && white == p2.white;
|
||||
}
|
||||
};
|
||||
typedef Hyprgraphics::SPCPRimaries SPCPRimaries;
|
||||
|
||||
namespace NColorPrimaries {
|
||||
static const auto DEFAULT_PRIMARIES = SPCPRimaries{};
|
||||
|
@ -185,5 +180,46 @@ namespace NColorManagement {
|
|||
return NColorManagement::getPrimaries(primariesNamed);
|
||||
return primaries;
|
||||
}
|
||||
|
||||
float getTFMinLuminance() const {
|
||||
switch (transferFunction) {
|
||||
case CM_TRANSFER_FUNCTION_EXT_LINEAR: return 0;
|
||||
case CM_TRANSFER_FUNCTION_ST2084_PQ:
|
||||
case CM_TRANSFER_FUNCTION_HLG: return HDR_MIN_LUMINANCE;
|
||||
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: return SDR_MIN_LUMINANCE;
|
||||
}
|
||||
};
|
||||
|
||||
float getTFMaxLuminance() const {
|
||||
switch (transferFunction) {
|
||||
case CM_TRANSFER_FUNCTION_ST2084_PQ: return HDR_MAX_LUMINANCE;
|
||||
case CM_TRANSFER_FUNCTION_HLG: return HLG_MAX_LUMINANCE;
|
||||
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: return SDR_MAX_LUMINANCE;
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t findId() const;
|
||||
uint32_t getId() const;
|
||||
uint32_t updateId();
|
||||
};
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
#include <GLES3/gl32.h>
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/path/Path.hpp>
|
||||
#include <random>
|
||||
|
@ -908,13 +910,15 @@ static void getCMShaderUniforms(CShader& shader) {
|
|||
shader.skipCM = glGetUniformLocation(shader.program, "skipCM");
|
||||
shader.sourceTF = glGetUniformLocation(shader.program, "sourceTF");
|
||||
shader.targetTF = glGetUniformLocation(shader.program, "targetTF");
|
||||
shader.sourcePrimaries = glGetUniformLocation(shader.program, "sourcePrimaries");
|
||||
shader.srcTFRange = glGetUniformLocation(shader.program, "srcTFRange");
|
||||
shader.dstTFRange = glGetUniformLocation(shader.program, "dstTFRange");
|
||||
shader.targetPrimaries = glGetUniformLocation(shader.program, "targetPrimaries");
|
||||
shader.maxLuminance = glGetUniformLocation(shader.program, "maxLuminance");
|
||||
shader.dstMaxLuminance = glGetUniformLocation(shader.program, "dstMaxLuminance");
|
||||
shader.dstRefLuminance = glGetUniformLocation(shader.program, "dstRefLuminance");
|
||||
shader.sdrSaturation = glGetUniformLocation(shader.program, "sdrSaturation");
|
||||
shader.sdrBrightness = glGetUniformLocation(shader.program, "sdrBrightnessMultiplier");
|
||||
shader.convertMatrix = glGetUniformLocation(shader.program, "convertMatrix");
|
||||
}
|
||||
|
||||
// shader has #include "rounding.glsl"
|
||||
|
@ -1437,27 +1441,26 @@ void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, const CBox& box,
|
|||
scissor(nullptr);
|
||||
}
|
||||
|
||||
static std::map<std::pair<uint32_t, uint32_t>, std::array<GLfloat, 9>> primariesConversionCache;
|
||||
|
||||
void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const NColorManagement::SImageDescription& imageDescription,
|
||||
const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR) {
|
||||
glUniform1i(shader.sourceTF, imageDescription.transferFunction);
|
||||
glUniform1i(shader.targetTF, targetImageDescription.transferFunction);
|
||||
const auto sourcePrimaries =
|
||||
imageDescription.primariesNameSet || imageDescription.primaries == SPCPRimaries{} ? getPrimaries(imageDescription.primariesNamed) : imageDescription.primaries;
|
||||
|
||||
const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ?
|
||||
getPrimaries(targetImageDescription.primariesNamed) :
|
||||
targetImageDescription.primaries;
|
||||
|
||||
const GLfloat glSourcePrimaries[8] = {
|
||||
sourcePrimaries.red.x, sourcePrimaries.red.y, sourcePrimaries.green.x, sourcePrimaries.green.y,
|
||||
sourcePrimaries.blue.x, sourcePrimaries.blue.y, sourcePrimaries.white.x, sourcePrimaries.white.y,
|
||||
};
|
||||
const GLfloat glTargetPrimaries[8] = {
|
||||
targetPrimaries.red.x, targetPrimaries.red.y, targetPrimaries.green.x, targetPrimaries.green.y,
|
||||
targetPrimaries.blue.x, targetPrimaries.blue.y, targetPrimaries.white.x, targetPrimaries.white.y,
|
||||
};
|
||||
glUniformMatrix4x2fv(shader.sourcePrimaries, 1, false, glSourcePrimaries);
|
||||
glUniformMatrix4x2fv(shader.targetPrimaries, 1, false, glTargetPrimaries);
|
||||
|
||||
glUniform2f(shader.srcTFRange, imageDescription.getTFMinLuminance(), imageDescription.getTFMaxLuminance());
|
||||
glUniform2f(shader.dstTFRange, targetImageDescription.getTFMinLuminance(), targetImageDescription.getTFMaxLuminance());
|
||||
|
||||
const float maxLuminance = imageDescription.luminances.max > 0 ? imageDescription.luminances.max : imageDescription.luminances.reference;
|
||||
glUniform1f(shader.maxLuminance, maxLuminance * targetImageDescription.luminances.reference / imageDescription.luminances.reference);
|
||||
glUniform1f(shader.dstMaxLuminance, targetImageDescription.luminances.max > 0 ? targetImageDescription.luminances.max : 10000);
|
||||
|
@ -1469,7 +1472,19 @@ void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const NColorManageme
|
|||
glUniform1f(shader.sdrBrightness,
|
||||
modifySDR && m_RenderData.pMonitor->sdrBrightness > 0 && targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ?
|
||||
m_RenderData.pMonitor->sdrBrightness :
|
||||
|
||||
1.0f);
|
||||
const auto cacheKey = std::make_pair(imageDescription.getId(), targetImageDescription.getId());
|
||||
if (!primariesConversionCache.contains(cacheKey)) {
|
||||
const auto mat = imageDescription.getPrimaries().convertMatrix(targetImageDescription.getPrimaries()).mat();
|
||||
const std::array<GLfloat, 9> glConvertMatrix = {
|
||||
mat[0][0], mat[1][0], mat[2][0], //
|
||||
mat[0][1], mat[1][1], mat[2][1], //
|
||||
mat[0][2], mat[1][2], mat[2][2], //
|
||||
};
|
||||
primariesConversionCache.insert(std::make_pair(cacheKey, glConvertMatrix));
|
||||
}
|
||||
glUniformMatrix3fv(shader.convertMatrix, 1, false, &primariesConversionCache[cacheKey][0]);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const SImageDescription& imageDescription) {
|
||||
|
|
|
@ -15,13 +15,15 @@ class CShader {
|
|||
GLint skipCM = -1;
|
||||
GLint sourceTF = -1;
|
||||
GLint targetTF = -1;
|
||||
GLint sourcePrimaries = -1;
|
||||
GLint srcTFRange = -1;
|
||||
GLint dstTFRange = -1;
|
||||
GLint targetPrimaries = -1;
|
||||
GLint maxLuminance = -1;
|
||||
GLint dstMaxLuminance = -1;
|
||||
GLint dstRefLuminance = -1;
|
||||
GLint sdrSaturation = -1; // sdr -> hdr saturation
|
||||
GLint sdrBrightness = -1; // sdr -> hdr brightness multiplier
|
||||
GLint convertMatrix = -1;
|
||||
GLint tex = -1;
|
||||
GLint alpha = -1;
|
||||
GLint posAttrib = -1;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue