color_helpers: refactored eetf2390 tonemapping
This commit is contained in:
parent
156660c72b
commit
941b22f68f
4 changed files with 308 additions and 166 deletions
|
@ -850,137 +850,3 @@ bool approxEqual( const glm::vec3 & a, const glm::vec3 & b, float flTolerance =
|
|||
glm::vec3 v = glm::abs(a - b);
|
||||
return ( v.x < flTolerance && v.y < flTolerance && v.z < flTolerance );
|
||||
}
|
||||
|
||||
int color_tests()
|
||||
{
|
||||
#if 0
|
||||
{
|
||||
// Test normalized primary matrix
|
||||
primaries_t primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } };
|
||||
glm::vec2 white = { 0.3070f, 0.3220f };
|
||||
|
||||
glm::mat3x3 rgb_to_xyz = normalised_primary_matrix( primaries, white, 1.f );
|
||||
printf("normalised_primary_matrix rgb_to_xyz %s\n", glm::to_string(rgb_to_xyz).c_str() );
|
||||
|
||||
glm::vec3 redXYZ = rgb_to_xyz * glm::vec3(1,0,0);
|
||||
glm::vec2 redxy = XYZ_to_xy( redXYZ );
|
||||
glm::vec3 whiteXYZ = rgb_to_xyz * glm::vec3(1);
|
||||
glm::vec2 whitexy = XYZ_to_xy( whiteXYZ );
|
||||
|
||||
printf("r xy %s == %s \n", glm::to_string(primaries.r).c_str(), glm::to_string(redxy).c_str() );
|
||||
printf("w xy %s == %s \n", glm::to_string(white).c_str(), glm::to_string(whitexy).c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// chromatic adapatation
|
||||
glm::vec3 d50XYZ = glm::vec3(0.96422f, 1.00000f, 0.82521f );
|
||||
glm::vec3 d65XYZ = glm::vec3(0.95047f, 1.00000f, 1.08883f );
|
||||
printf("d50XYZ %s\n", glm::to_string(d50XYZ).c_str() );
|
||||
printf("d65XYZ %s\n", glm::to_string(d65XYZ).c_str() );
|
||||
{
|
||||
|
||||
glm::mat3x3 d65From50 = chromatic_adaptation_matrix( d50XYZ, d65XYZ, k_EChromaticAdapatationMethod_Bradford );
|
||||
printf("bradford d65From50 %s\n", glm::to_string(d65From50).c_str() );
|
||||
glm::vec3 d65_2 = d65From50 * d50XYZ;
|
||||
printf("bradford d65_2 %s\n", glm::to_string(d65_2).c_str() );
|
||||
}
|
||||
{
|
||||
|
||||
glm::mat3x3 d65From50 = chromatic_adaptation_matrix( d50XYZ, d65XYZ, k_EChromaticAdapatationMethod_XYZ );
|
||||
printf("xyzscaling d65From50 %s\n", glm::to_string(d65From50).c_str() );
|
||||
glm::vec3 d65_2 = d65From50 * d50XYZ;
|
||||
printf("xyzscaling d65_2 %s\n", glm::to_string(d65_2).c_str() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
|
||||
int nLut3DSize = 4;
|
||||
float flScale = 1.f / ( (float) nLut3DSize - 1.f );
|
||||
for (int nBlue = 0; nBlue<nLut3DSize; ++nBlue )
|
||||
{
|
||||
for (int nGreen = 0; nGreen<nLut3DSize; ++nGreen )
|
||||
{
|
||||
for (int nRed = 0; nRed<nLut3DSize; ++nRed )
|
||||
{
|
||||
glm::vec3 rgb1( nRed * flScale, nGreen * flScale, nBlue * flScale );
|
||||
glm::vec3 hsv = rgb_to_hsv( rgb1 );
|
||||
glm::vec3 rgb2 = hsv_to_rgb( hsv );
|
||||
if ( !approxEqual(rgb1, rgb2 ) )
|
||||
{
|
||||
printf("****");
|
||||
}
|
||||
printf("%s %s %s\n", glm::to_string(rgb1).c_str(), glm::to_string(hsv).c_str(), glm::to_string(rgb2).c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Generate a 1d lut
|
||||
{
|
||||
int nLutsize = 9;
|
||||
lut1d_t lut;
|
||||
lut.resize( nLutsize );
|
||||
float flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
for ( int i = 0; i<nLutsize; ++i )
|
||||
{
|
||||
float f = flScale * (float) i;
|
||||
|
||||
lut.dataR[i] = f * f;
|
||||
lut.dataG[i] = f * f;
|
||||
lut.dataB[i] = f * f;
|
||||
}
|
||||
lut.finalize();
|
||||
|
||||
glm::vec3 rgb1 = ApplyLut1D_Linear( lut, glm::vec3( -1.f, 0.5f, 2.f ) );
|
||||
printf("%s\n", glm::to_string(rgb1).c_str() );
|
||||
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%s\n", glm::to_string(rgb2).c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Generate a 1d lut with a flat spot
|
||||
{
|
||||
int nLutsize = 9;
|
||||
lut1d_t lut;
|
||||
lut.resize( nLutsize );
|
||||
float flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
printf("LUT\n");
|
||||
for ( int i = 0; i<nLutsize; ++i )
|
||||
{
|
||||
float f = std::max( 0.25f, flScale * (float) i );
|
||||
lut.dataR[i] = f * f;
|
||||
lut.dataG[i] = f * f;
|
||||
lut.dataB[i] = f * f;
|
||||
printf("%f %d %f\n", f, i, lut.dataG[i] );
|
||||
}
|
||||
lut.finalize();
|
||||
|
||||
printf("\n");
|
||||
nLutsize = 21;
|
||||
flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
for (int i=0; i<21; ++i)
|
||||
{
|
||||
float f = std::max( 0.25f, flScale * (float) i );
|
||||
glm::vec3 rgb1 = ApplyLut1D_Linear( lut, glm::vec3( f, f, f ) );
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%f %f %f\n", f, rgb1.g, rgb2.g );
|
||||
}
|
||||
/*
|
||||
printf("%s\n", glm::to_string(rgb1).c_str() );
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%s\n", glm::to_string(rgb2).c_str() );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -76,17 +76,6 @@ inline T nits_to_pq( const T& nits )
|
|||
return n;
|
||||
}
|
||||
|
||||
inline float eetf_2390_spline( float value, float ks, float maxLum )
|
||||
{
|
||||
float t = ( value - ks ) / ( 1.f - ks ); // TODO : guard against ks == 1.f?
|
||||
float t_sq = t*t;
|
||||
float t_cub = t_sq*t;
|
||||
float v1 = ( 2.f * t_cub - 3.f * t_sq + 1.f ) * ks;
|
||||
float v2 = ( t_cub - 2.f * t_sq + t ) * ( 1.f - ks );
|
||||
float v3 = (-2.f * t_cub + 3.f * t_sq ) * maxLum;
|
||||
return v1 + v2 + v3;
|
||||
}
|
||||
|
||||
// Apply an HDR tonemapping according to eetf 2390 (R-REP-BT.2390-8-2020-PDF-E.pdf)
|
||||
// sourceXXX == "Mastering Display" == Lw, Lb (in the paper)
|
||||
// targetXXX == "Target Display" == Lmin, Lmax (in the paper)
|
||||
|
@ -96,32 +85,90 @@ inline float eetf_2390_spline( float value, float ks, float maxLum )
|
|||
// PQ all params first, and undo the output)
|
||||
// Values outside of 0-1 are not defined
|
||||
|
||||
inline float eetf_2390( float valuePQ, float sourceBlackPQ, float sourceWhitePQ, float targetBlackPQ, float targetWhitePQ )
|
||||
struct eetf_2390_t
|
||||
{
|
||||
// normalize PQ based on the mastering (source) display (E1)
|
||||
const float sourcePQScale = sourceWhitePQ - sourceBlackPQ;
|
||||
const float invSourcePQScale = 1.f / sourcePQScale;
|
||||
void init_nits( float sourceBlackNits, float sourceWhiteNits, float targetBlackNits, float targetWhiteNits )
|
||||
{
|
||||
init_pq(
|
||||
nits_to_pq( sourceBlackNits ),
|
||||
nits_to_pq( sourceWhiteNits ),
|
||||
nits_to_pq( targetBlackNits ),
|
||||
nits_to_pq( targetWhiteNits ) );
|
||||
}
|
||||
|
||||
float minLum = ( targetBlackPQ - sourceBlackPQ ) * invSourcePQScale; // TODO: Pull into precomputation?
|
||||
float maxLum = ( targetWhitePQ - sourceBlackPQ ) * invSourcePQScale; // TODO: Pull into precomputation?
|
||||
float e1 = ( valuePQ - sourceBlackPQ ) * invSourcePQScale;
|
||||
void init_pq( float sourceBlackPQ, float sourceWhitePQ, float targetBlackPQ, float targetWhitePQ )
|
||||
{
|
||||
m_sourceBlackPQ = sourceBlackPQ;
|
||||
m_sourcePQScale = sourceWhitePQ - sourceBlackPQ;
|
||||
m_invSourcePQScale = m_sourcePQScale > 0.f ? 1.f / m_sourcePQScale : 0.f;
|
||||
m_minLumPQ = ( targetBlackPQ - sourceBlackPQ ) * m_invSourcePQScale;
|
||||
m_maxLumPQ = ( targetWhitePQ - sourceBlackPQ ) * m_invSourcePQScale;
|
||||
m_ks = 1.5 * m_maxLumPQ - 0.5; // TODO : return false if ks == 1.f?
|
||||
}
|
||||
|
||||
// Knee
|
||||
float ks = 1.5 * maxLum - 0.5; // TODO: Pull into precomputation?
|
||||
float b = minLum;
|
||||
// "Max RGB" approach, as defined in "Color Volume and Hue-Preservation in HDR Tone Mapping"
|
||||
// Digital Object Identifier 10.5594/JMI.2020.2984046
|
||||
// Date of publication: 4 May 2020
|
||||
inline glm::vec3 apply_max_rgb( const glm::vec3 & inputNits )
|
||||
{
|
||||
float input_scalar_nits = std::max( inputNits.r, std::max( inputNits.g, inputNits.b ) );
|
||||
float output_scalar_nits = pq_to_nits( apply_pq( nits_to_pq( input_scalar_nits ) ) );
|
||||
float gain = input_scalar_nits > 0.f ? output_scalar_nits / input_scalar_nits : 0.f;
|
||||
return inputNits * gain;
|
||||
}
|
||||
|
||||
// Apply high end rolloff
|
||||
float e2 = e1 < ks ? e1 : eetf_2390_spline( e1, ks, maxLum );
|
||||
inline glm::vec3 apply_luma_rgb( const glm::vec3 & inputNits )
|
||||
{
|
||||
float input_scalar_nits = 0.2627f * inputNits.r + 0.6780f * inputNits.g + 0.0593f * inputNits.b;
|
||||
float output_scalar_nits = pq_to_nits( apply_pq( nits_to_pq( input_scalar_nits ) ) );
|
||||
float gain = input_scalar_nits > 0.f ? output_scalar_nits / input_scalar_nits : 0.f;
|
||||
return inputNits * gain;
|
||||
}
|
||||
|
||||
// Apply low end pedestal
|
||||
float one_min_e2 = 1.f - e2;
|
||||
float one_min_e2_sq = one_min_e2 * one_min_e2;
|
||||
float e3 = e2 + b * one_min_e2_sq * one_min_e2_sq;
|
||||
inline glm::vec3 apply_independent_rgb( const glm::vec3 & inputNits )
|
||||
{
|
||||
glm::vec3 inputPQ = nits_to_pq( inputNits );
|
||||
glm::vec3 outputPQ = { apply_pq( inputPQ.r ), apply_pq( inputPQ.g ), apply_pq( inputPQ.b ) };
|
||||
return pq_to_nits( outputPQ );
|
||||
}
|
||||
|
||||
// Re-apply mastering (source) transform
|
||||
return e3 * sourcePQScale + sourceBlackPQ;
|
||||
}
|
||||
float m_sourceBlackPQ = 0.f;
|
||||
float m_sourcePQScale = 0.f;
|
||||
float m_invSourcePQScale = 0.f;
|
||||
float m_minLumPQ = 0.f;
|
||||
float m_maxLumPQ = 0.f;
|
||||
float m_ks = 0.f;
|
||||
|
||||
// Raw PQ transfer function
|
||||
inline float apply_pq( float valuePQ )
|
||||
{
|
||||
// normalize PQ based on the mastering (source) display (E1)
|
||||
float e1 = ( valuePQ - m_sourceBlackPQ ) * m_invSourcePQScale;
|
||||
|
||||
// Apply high end rolloff
|
||||
float e2 = e1 < m_ks ? e1 : _eetf_2390_spline( e1, m_ks, m_maxLumPQ );
|
||||
|
||||
// Apply low end pedestal
|
||||
float one_min_e2 = 1.f - e2;
|
||||
float one_min_e2_sq = one_min_e2 * one_min_e2;
|
||||
float e3 = e2 + m_minLumPQ * one_min_e2_sq * one_min_e2_sq;
|
||||
|
||||
// Re-apply mastering (source) transform
|
||||
return e3 * m_sourcePQScale + m_sourceBlackPQ;
|
||||
}
|
||||
|
||||
private:
|
||||
inline float _eetf_2390_spline( float value, float ks, float maxLum )
|
||||
{
|
||||
float t = ( value - ks ) / ( 1.f - ks ); // TODO : guard against ks == 1.f?
|
||||
float t_sq = t*t;
|
||||
float t_cub = t_sq*t;
|
||||
float v1 = ( 2.f * t_cub - 3.f * t_sq + 1.f ) * ks;
|
||||
float v2 = ( t_cub - 2.f * t_sq + t ) * ( 1.f - ks );
|
||||
float v3 = (-2.f * t_cub + 3.f * t_sq ) * maxLum;
|
||||
return v1 + v2 + v3;
|
||||
}
|
||||
};
|
||||
|
||||
inline float flerp( float a, float b, float t )
|
||||
{
|
||||
|
@ -336,5 +383,3 @@ static constexpr displaycolorimetry_t displaycolorimetry_2020
|
|||
.primaries = { { 0.708f, 0.292f }, { 0.170f, 0.797f }, { 0.131f, 0.046f } },
|
||||
.white = { 0.3127f, 0.3290f }, // D65
|
||||
};
|
||||
|
||||
int color_tests();
|
229
src/color_tests.cpp
Normal file
229
src/color_tests.cpp
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include "color_helpers.h"
|
||||
#include <cstdio>
|
||||
|
||||
/*
|
||||
const uint32_t nLutSize1d = 4096;
|
||||
const uint32_t nLutEdgeSize3d = 17;
|
||||
|
||||
uint16_t lut1d[nLutSize1d*4];
|
||||
uint16_t lut3d[nLutEdgeSize3d*nLutEdgeSize3d*nLutEdgeSize3d*4];
|
||||
|
||||
lut1d_t lut1d_float;
|
||||
lut3d_t lut3d_float;
|
||||
|
||||
static void BenchmarkCalcColorTransform(EOTF inputEOTF, benchmark::State &state)
|
||||
{
|
||||
const primaries_t primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } };
|
||||
const glm::vec2 white = { 0.3070f, 0.3220f };
|
||||
|
||||
displaycolorimetry_t inputColorimetry{};
|
||||
inputColorimetry.primaries = primaries;
|
||||
inputColorimetry.white = white;
|
||||
|
||||
displaycolorimetry_t outputEncodingColorimetry{};
|
||||
outputEncodingColorimetry.primaries = primaries;
|
||||
outputEncodingColorimetry.white = white;
|
||||
|
||||
colormapping_t colorMapping{};
|
||||
|
||||
tonemapping_t tonemapping{};
|
||||
tonemapping.bUseShaper = true;
|
||||
|
||||
nightmode_t nightmode{};
|
||||
float flGain = 1.0f;
|
||||
|
||||
for (auto _ : state) {
|
||||
calcColorTransform( &lut1d_float, nLutSize1d, &lut3d_float, nLutEdgeSize3d, inputColorimetry, inputEOTF,
|
||||
outputEncodingColorimetry, EOTF_Gamma22,
|
||||
colorMapping, nightmode, tonemapping, nullptr, flGain );
|
||||
for ( size_t i=0, end = lut1d_float.dataR.size(); i<end; ++i )
|
||||
{
|
||||
lut1d[4*i+0] = drm_quantize_lut_value( lut1d_float.dataR[i] );
|
||||
lut1d[4*i+1] = drm_quantize_lut_value( lut1d_float.dataG[i] );
|
||||
lut1d[4*i+2] = drm_quantize_lut_value( lut1d_float.dataB[i] );
|
||||
lut1d[4*i+3] = 0;
|
||||
}
|
||||
for ( size_t i=0, end = lut3d_float.data.size(); i<end; ++i )
|
||||
{
|
||||
lut3d[4*i+0] = drm_quantize_lut_value( lut3d_float.data[i].r );
|
||||
lut3d[4*i+1] = drm_quantize_lut_value( lut3d_float.data[i].g );
|
||||
lut3d[4*i+2] = drm_quantize_lut_value( lut3d_float.data[i].b );
|
||||
lut3d[4*i+3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int color_tests()
|
||||
{
|
||||
#if 0
|
||||
{
|
||||
// Test normalized primary matrix
|
||||
primaries_t primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } };
|
||||
glm::vec2 white = { 0.3070f, 0.3220f };
|
||||
|
||||
glm::mat3x3 rgb_to_xyz = normalised_primary_matrix( primaries, white, 1.f );
|
||||
printf("normalised_primary_matrix rgb_to_xyz %s\n", glm::to_string(rgb_to_xyz).c_str() );
|
||||
|
||||
glm::vec3 redXYZ = rgb_to_xyz * glm::vec3(1,0,0);
|
||||
glm::vec2 redxy = XYZ_to_xy( redXYZ );
|
||||
glm::vec3 whiteXYZ = rgb_to_xyz * glm::vec3(1);
|
||||
glm::vec2 whitexy = XYZ_to_xy( whiteXYZ );
|
||||
|
||||
printf("r xy %s == %s \n", glm::to_string(primaries.r).c_str(), glm::to_string(redxy).c_str() );
|
||||
printf("w xy %s == %s \n", glm::to_string(white).c_str(), glm::to_string(whitexy).c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// chromatic adapatation
|
||||
glm::vec3 d50XYZ = glm::vec3(0.96422f, 1.00000f, 0.82521f );
|
||||
glm::vec3 d65XYZ = glm::vec3(0.95047f, 1.00000f, 1.08883f );
|
||||
printf("d50XYZ %s\n", glm::to_string(d50XYZ).c_str() );
|
||||
printf("d65XYZ %s\n", glm::to_string(d65XYZ).c_str() );
|
||||
{
|
||||
|
||||
glm::mat3x3 d65From50 = chromatic_adaptation_matrix( d50XYZ, d65XYZ, k_EChromaticAdapatationMethod_Bradford );
|
||||
printf("bradford d65From50 %s\n", glm::to_string(d65From50).c_str() );
|
||||
glm::vec3 d65_2 = d65From50 * d50XYZ;
|
||||
printf("bradford d65_2 %s\n", glm::to_string(d65_2).c_str() );
|
||||
}
|
||||
{
|
||||
|
||||
glm::mat3x3 d65From50 = chromatic_adaptation_matrix( d50XYZ, d65XYZ, k_EChromaticAdapatationMethod_XYZ );
|
||||
printf("xyzscaling d65From50 %s\n", glm::to_string(d65From50).c_str() );
|
||||
glm::vec3 d65_2 = d65From50 * d50XYZ;
|
||||
printf("xyzscaling d65_2 %s\n", glm::to_string(d65_2).c_str() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
|
||||
int nLut3DSize = 4;
|
||||
float flScale = 1.f / ( (float) nLut3DSize - 1.f );
|
||||
for (int nBlue = 0; nBlue<nLut3DSize; ++nBlue )
|
||||
{
|
||||
for (int nGreen = 0; nGreen<nLut3DSize; ++nGreen )
|
||||
{
|
||||
for (int nRed = 0; nRed<nLut3DSize; ++nRed )
|
||||
{
|
||||
glm::vec3 rgb1( nRed * flScale, nGreen * flScale, nBlue * flScale );
|
||||
glm::vec3 hsv = rgb_to_hsv( rgb1 );
|
||||
glm::vec3 rgb2 = hsv_to_rgb( hsv );
|
||||
if ( !approxEqual(rgb1, rgb2 ) )
|
||||
{
|
||||
printf("****");
|
||||
}
|
||||
printf("%s %s %s\n", glm::to_string(rgb1).c_str(), glm::to_string(hsv).c_str(), glm::to_string(rgb2).c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Generate a 1d lut
|
||||
{
|
||||
int nLutsize = 9;
|
||||
lut1d_t lut;
|
||||
lut.resize( nLutsize );
|
||||
float flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
for ( int i = 0; i<nLutsize; ++i )
|
||||
{
|
||||
float f = flScale * (float) i;
|
||||
|
||||
lut.dataR[i] = f * f;
|
||||
lut.dataG[i] = f * f;
|
||||
lut.dataB[i] = f * f;
|
||||
}
|
||||
lut.finalize();
|
||||
|
||||
glm::vec3 rgb1 = ApplyLut1D_Linear( lut, glm::vec3( -1.f, 0.5f, 2.f ) );
|
||||
printf("%s\n", glm::to_string(rgb1).c_str() );
|
||||
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%s\n", glm::to_string(rgb2).c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Generate a 1d lut with a flat spot
|
||||
{
|
||||
int nLutsize = 9;
|
||||
lut1d_t lut;
|
||||
lut.resize( nLutsize );
|
||||
float flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
printf("LUT\n");
|
||||
for ( int i = 0; i<nLutsize; ++i )
|
||||
{
|
||||
float f = std::max( 0.25f, flScale * (float) i );
|
||||
lut.dataR[i] = f * f;
|
||||
lut.dataG[i] = f * f;
|
||||
lut.dataB[i] = f * f;
|
||||
printf("%f %d %f\n", f, i, lut.dataG[i] );
|
||||
}
|
||||
lut.finalize();
|
||||
|
||||
printf("\n");
|
||||
nLutsize = 21;
|
||||
flScale = 1.f / ( (float) nLutsize - 1.f );
|
||||
for (int i=0; i<21; ++i)
|
||||
{
|
||||
float f = std::max( 0.25f, flScale * (float) i );
|
||||
glm::vec3 rgb1 = ApplyLut1D_Linear( lut, glm::vec3( f, f, f ) );
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%f %f %f\n", f, rgb1.g, rgb2.g );
|
||||
}
|
||||
/*
|
||||
printf("%s\n", glm::to_string(rgb1).c_str() );
|
||||
glm::vec3 rgb2 = ApplyLut1D_Inverse_Linear( lut, rgb1 );
|
||||
printf("%s\n", glm::to_string(rgb2).c_str() );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_eetf2390_mono()
|
||||
{
|
||||
printf("%s\n", __func__ );
|
||||
float vLumaLevels[] = { 0.0, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0, 15000.0 };
|
||||
|
||||
// map 0.01 - 10,000 -> 0.1 - 1000
|
||||
float sourceBlackNits = 0.01f;
|
||||
float sourceWhiteNits = 5000.0f;
|
||||
float sourceBlackPQ = nits_to_pq( sourceBlackNits );
|
||||
float sourceWhitePQ = nits_to_pq( sourceWhiteNits );
|
||||
|
||||
printf("source\t%0.02f - %0.01f\t\tPQ10: %0.1f %0.1f \n", sourceBlackNits, sourceWhiteNits, sourceBlackPQ * 1023.f, sourceWhitePQ * 1023.f );
|
||||
|
||||
float destBlackNits = 0.1f;
|
||||
float destWhiteNits = 1000.0f;
|
||||
float destBlackPQ = nits_to_pq( destBlackNits );
|
||||
float destWhitePQ = nits_to_pq( destWhiteNits );
|
||||
printf("dest\t%0.02f - %0.01f\t\tPQ10: %0.1f %0.1f\n", destBlackNits, destWhiteNits, destBlackPQ * 1023.f, destWhitePQ * 1023.f );
|
||||
printf("\n");
|
||||
|
||||
eetf_2390_t eetf;
|
||||
eetf.init_pq( sourceBlackPQ, sourceWhitePQ, destBlackPQ, destWhitePQ );
|
||||
|
||||
for ( size_t nLevel=0; nLevel < 12; ++nLevel )
|
||||
{
|
||||
float flInputNits = vLumaLevels[nLevel];
|
||||
float inputPQ = nits_to_pq( flInputNits );
|
||||
float tonemappedOutputPQ = eetf.apply_pq( inputPQ );
|
||||
float tonemappedOutputNits = pq_to_nits( tonemappedOutputPQ );
|
||||
printf("value\t%0.03f -> %0.03f\tPQ10: %0.1f -> %0.1f\n", flInputNits, tonemappedOutputNits, inputPQ * 1023.f, tonemappedOutputPQ * 1023.f );
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("color_tests\n");
|
||||
test_eetf2390_mono();
|
||||
return 0;
|
||||
}
|
|
@ -124,3 +124,5 @@ endif
|
|||
|
||||
benchmark_dep = dependency('benchmark')
|
||||
executable('gamescope_color_microbench', ['color_bench.cpp', 'color_helpers.cpp'], dependencies:[benchmark_dep, glm_dep])
|
||||
|
||||
executable('gamescope_color_tests', ['color_tests.cpp', 'color_helpers.cpp'], dependencies:[glm_dep])
|
||||
|
|
Loading…
Reference in a new issue