Browse Source

Add color namespace, improve colorspace conversion functions, move colorspace and gamma functions from utility folder to new color namespace

master
C. J. Howard 4 months ago
parent
commit
81d7a863a8
11 changed files with 388 additions and 118 deletions
  1. +95
    -0
      src/color/acescg.hpp
  2. +8
    -26
      src/color/color.hpp
  3. +164
    -0
      src/color/srgb.hpp
  4. +92
    -0
      src/color/xyz.hpp
  5. +2
    -2
      src/ecs/systems/astronomy-system.cpp
  6. +0
    -4
      src/ecs/systems/weather-system.cpp
  7. +0
    -1
      src/game/states/play-state.cpp
  8. +12
    -0
      src/math/matrix-type.hpp
  9. +12
    -0
      src/math/vector-type.hpp
  10. +3
    -5
      src/renderer/passes/sky-pass.cpp
  11. +0
    -80
      src/utility/aces.hpp

+ 95
- 0
src/color/acescg.hpp View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COLOR_ACESCG_HPP
#define ANTKEEPER_COLOR_ACESCG_HPP
#include "math/math.hpp"
namespace color {
/// Functions which operate in the ACEScg colorspace.
namespace acescg {
/**
* Calculates the luminance of an ACEScg color.
*
* @param x ACEScg color.
* @return return Luminance of @p x.
*/
template <class T>
T luminance(const math::vector3<T>& x);
/**
* Transforms an ACEScg color into the linear sRGB colorspace using the Bradford chromatic adaption transform.
*
* @param x ACEScg color.
* @return return Linear sRGB color.
*
* @see https://www.colour-science.org/apps/
*/
template <class T>
math::vector3<T> to_srgb(const math::vector3<T>& x);
/**
* Transforms an ACEScg color into the CIE XYZ colorspace.
*
* @param x ACEScg color.
* @return return CIE XYZ color.
*/
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x);
template <class T>
T luminance(const math::vector3<T>& x)
{
static const math::vector3<T> luma = {0.272228716780914, 0.674081765811148, 0.053689517407937};
return math::dot(x, luma);
}
template <class T>
math::vector3<T> to_srgb(const math::vector3<T>& x)
{
static const math::matrix3<T> acescg_to_srgb
{{
{ 1.704858676289160, -0.130076824208823, -0.023964072927574},
{-0.621716021885330, 1.140735774822504, -0.128975508299318},
{-0.083299371729058, -0.010559801677511, 1.153014018916862}
}};
return acescg_to_srgb * x;
}
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x)
{
static const math::matrix3<T> acescg_to_xyz
{{
{0.662454181108505, 0.272228716780914, -0.005574649490394},
{0.134004206456433, 0.674081765811148, 0.004060733528983},
{0.156187687004908, 0.053689517407937, 1.010339100312997}
}};
return acescg_to_xyz * x;
}
} // namespace acescg
} // namespace color
#endif // ANTKEEPER_COLOR_ACESCG_HPP

src/utility/gamma.hpp → src/color/color.hpp View File

@ -17,32 +17,14 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAMMA_HPP
#define ANTKEEPER_GAMMA_HPP
#ifndef ANTKEEPER_COLOR_HPP
#define ANTKEEPER_COLOR_HPP
#include "math/vector-type.hpp"
#include <cmath>
/// Color manipulation functions.
namespace color {}
template <typename T>
T srgb_to_linear(const T& x)
{
if (x <= T(0.04045))
{
return x / T(12.92);
}
return std::pow((x + T(0.055)) / T(1.055), T(2.4));
}
#include "acescg.hpp"
#include "srgb.hpp"
#include "xyz.hpp"
template <typename T>
T linear_to_srgb(const T& x)
{
if (x <= T(0.0031308))
{
return x * T(12.92);
}
return std::pow(x, T(1.0 / 2.4)) * T(1.055) - T(0.055);
}
#endif // ANTKEEPER_GAMMA_HPP
#endif // ANTKEEPER_COLOR_HPP

+ 164
- 0
src/color/srgb.hpp View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COLOR_SRGB_HPP
#define ANTKEEPER_COLOR_SRGB_HPP
#include "math/math.hpp"
#include <cmath>
namespace color {
/// Functions which operate in the sRGB colorspace.
namespace srgb {
/**
* Performs the sRGB Electro-Optical Transfer Function (EOTF), also known as the sRGB decoding function.
*
* @param v sRGB electrical signal (gamma-encoded sRGB).
* @return Corresponding luminance of the signal (linear sRGB).
*/
/// @{
float eotf(float v);
double eotf(double v);
template <class T>
math::vector3<T> eotf(const math::vector3<T>& v);
/// @}
/**
* Performs the sRGB inverse Electro-Optical Transfer Function (EOTF), also known as the sRGB encoding function.
*
* @param l sRGB luminance (linear sRGB).
* @return Corresponding electrical signal (gamma-encoded sRGB).
*/
/// @{
float eotf_inverse(float v);
double eotf_inverse(double v);
template <class T>
math::vector3<T> eotf_inverse(const math::vector3<T>& l);
/// @}
/**
* Calculates the luminance of a linear sRGB color.
*
* @param x Linear sRGB color.
* @return return Luminance of @p x.
*/
template <class T>
T luminance(const math::vector3<T>& x);
/**
* Transforms a linear sRGB color into the ACEScg colorspace using the Bradford chromatic adaption transform.
*
* @param x Linear sRGB color.
* @return ACEScg color.
*
* @see https://www.colour-science.org/apps/
*/
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x);
/**
* Transforms a linear sRGB color into the CIE XYZ colorspace.
*
* @param x Linear sRGB color.
* @return CIE XYZ color.
*/
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x);
inline float eotf(float v)
{
return (v < 0.04045f) ? (v / 12.92f) : std::pow((v + 0.055f) / 1.055f, 2.4f);
}
inline double eotf(double v)
{
return (v < 0.04045) ? (v / 12.92) : std::pow((v + 0.055) / 1.055, 2.4);
}
template <class T>
math::vector3<T> eotf(const math::vector3<T>& v)
{
return math::vector3<T>
{
eotf(v[0]),
eotf(v[1]),
eotf(v[2])
};
}
inline float eotf_inverse(float l)
{
return (l <= 0.0031308f) ? (l * 12.92f) : (std::pow(l, 1.0f / 2.4f) * 1.055f - 0.055f);
}
inline double eotf_inverse(double l)
{
return (l <= 0.0031308) ? (l * 12.92) : (std::pow(l, 1.0 / 2.4) * 1.055 - 0.055);
}
template <class T>
math::vector3<T> eotf_inverse(const math::vector3<T>& l)
{
return math::vector3<T>
{
eotf_inverse(l[0]),
eotf_inverse(l[1]),
eotf_inverse(l[2])
};
}
template <class T>
T luminance(const math::vector3<T>& x)
{
static const math::vector3<T> luma = {0.212639005871510, 0.715168678767756, 0.072192315360734};
return math::dot(x, luma);
}
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x)
{
static const math::matrix3<T> srgb_to_acescg
{{
{0.613132422390542, 0.070124380833917, 0.020587657528185},
{0.339538015799666, 0.916394011313573, 0.109574571610682},
{0.047416696048269, 0.013451523958235, 0.869785404035327}
}};
return srgb_to_acescg * x;
}
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x)
{
static const math::matrix3<T> srgb_to_xyz
{{
{0.412390799265959, 0.212639005871510, 0.019330818715592},
{0.357584339383878, 0.715168678767756, 0.119194779794626},
{0.180480788401834, 0.072192315360734, 0.950532152249661}
}};
return srgb_to_xyz * x;
}
} // namespace srgb
} // namespace color
#endif // ANTKEEPER_COLOR_SRGB_HPP

+ 92
- 0
src/color/xyz.hpp View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COLOR_XYZ_HPP
#define ANTKEEPER_COLOR_XYZ_HPP
#include "math/math.hpp"
namespace color {
/// Functions which operate in the CIE XYZ colorspace.
namespace xyz {
/**
* Returns the luminance of a CIE XYZ color.
*
* @param x CIE XYZ color.
* @return return Luminance of @p x.
*/
template <class T>
T luminance(const math::vector3<T>& x);
/**
* Transforms a CIE XYZ color into the ACEScg colorspace.
*
* @param x CIE XYZ color.
* @return ACEScg color.
*/
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x);
/**
* Transforms a CIE XYZ color into the linear sRGB colorspace.
*
* @param x CIE XYZ color.
* @return Linear sRGB color.
*/
template <class T>
math::vector3<T> to_srgb(const math::vector3<T>& x);
template <class T>
inline T luminance(const math::vector3<T>& x)
{
return x[1];
}
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x)
{
static const math::matrix3<T> xyz_to_acescg
{{
{ 1.641023379694326 -0.663662858722983 0.011721894328375},
{-0.324803294184790 1.615331591657338 -0.008284441996237},
{-0.236424695237612, 0.016756347685530, 0.988394858539022}
}};
return xyz_to_acescg * x;
}
template <class T>
math::vector3<T> to_srgb(const math::vector3<T>& x)
{
static const math::matrix3<T> xyz_to_srgb
{{
{ 3.240969941904523, -0.969243636280880, 0.055630079696994},
{-1.537383177570094, 1.875967501507721, -0.203976958888977},
{-0.498610760293003, 0.041555057407176, 1.056971514242879}
}};
return xyz_to_srgb * x;
}
} // namespace xyz
} // namespace color
#endif // ANTKEEPER_COLOR_XYZ_HPP

+ 2
- 2
src/ecs/systems/astronomy-system.cpp View File

@ -24,7 +24,7 @@
#include "ecs/components/transform-component.hpp"
#include "renderer/passes/sky-pass.hpp"
#include "astro/blackbody.hpp"
#include "utility/aces.hpp"
#include "color/color.hpp"
#include <iostream>
namespace ecs {
@ -89,7 +89,7 @@ void astronomy_system::update(double t, double dt)
// Set sun color
float correlated_temperature = 3000.0f + std::sin(spherical.y) * 5000.0f;
float3 correlated_color = math::type_cast<float>(srgb_to_acescg(astro::blackbody(correlated_temperature)));
float3 correlated_color = math::type_cast<float>(color::srgb::to_acescg(astro::blackbody(correlated_temperature)));
sun_light->set_color(correlated_color);
// Set sun intensity (in lux)

+ 0
- 4
src/ecs/systems/weather-system.cpp View File

@ -23,10 +23,6 @@
#include "renderer/passes/sky-pass.hpp"
#include "renderer/passes/shadow-map-pass.hpp"
#include "renderer/passes/material-pass.hpp"
#include "utility/gamma.hpp"
#include "resources/image.hpp"
#include "astro/coordinates.hpp"
#include "astro/orbit.hpp"
#include <cmath>
namespace ecs {

+ 0
- 1
src/game/states/play-state.cpp View File

@ -61,7 +61,6 @@
#include "ecs/systems/astronomy-system.hpp"
#include "game/biome.hpp"
#include "utility/fundamental-types.hpp"
#include "utility/gamma.hpp"
#include "astro/blackbody.hpp"
#include "utility/bit-math.hpp"

+ 12
- 0
src/math/matrix-type.hpp View File

@ -43,6 +43,18 @@ struct matrix
inline constexpr const row_type& operator[](std::size_t i) const noexcept { return columns[i]; }
};
/// 2x2 matrix.
template <typename T>
using matrix2 = matrix<T, 2, 2>;
/// 3x3 matrix.
template <typename T>
using matrix3 = matrix<T, 3, 3>;
/// 4x4 matrix.
template <typename T>
using matrix4 = matrix<T, 4, 4>;
} // namespace math
#endif // ANTKEEPER_MATH_MATRIX_TYPE_HPP

+ 12
- 0
src/math/vector-type.hpp View File

@ -118,6 +118,18 @@ struct vector
inline constexpr std::size_t size() const noexcept { return 4; };
};
/// 2D vector.
template <typename T>
using vector2 = vector<T, 2>;
/// 3D vector.
template <typename T>
using vector3 = vector<T, 3>;
/// 4D vector.
template <typename T>
using vector4 = vector<T, 4>;
} // namespace math
#endif // ANTKEEPER_MATH_VECTOR_TYPE_HPP

+ 3
- 5
src/renderer/passes/sky-pass.cpp View File

@ -37,7 +37,7 @@
#include "renderer/material.hpp"
#include "scene/camera.hpp"
#include "utility/fundamental-types.hpp"
#include "utility/aces.hpp"
#include "color/color.hpp"
#include "math/interpolation.hpp"
#include "astro/astro.hpp"
#include <cmath>
@ -118,16 +118,14 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe
double3 color_srgb = astro::blackbody(color_temperature);
// Transform to ACEScg colorspace
double3 color_acescg = srgb_to_acescg(color_srgb);
double3 color_acescg = color::srgb::to_acescg(color_srgb);
// Calculate color luminance
double color_luminance = acescg_to_luminance(color_acescg);
double color_luminance = color::acescg::luminance(color_acescg);
// Convert apparent magnitude to lux
double vmag_lux = astro::vmag_to_lux(vmag);
std::cout << "mag: " << vmag << "; lux: " << vmag_lux << "remag: " << (astro::lux_to_vmag(vmag_lux)) << std::endl;
// Normalized color luminance and scale by apparent magnitude
double3 scaled_color = color_acescg * ((1.0 / color_luminance) * vmag_lux);

+ 0
- 80
src/utility/aces.hpp View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ACES_HPP
#define ANTKEEPER_ACES_HPP
#include "math/vector-type.hpp"
/**
* Transforms a linear sRGB color into the ACEScg colorspace, using the Bradford chromatic adaption transform.
*
* @param x Linear sRGB color.
* @return Linear ACEScg color.
*
* @see https://www.colour-science.org/apps/
*/
template <class T>
math::vector<T, 3> srgb_to_acescg(const math::vector<T, 3>& x)
{
static const math::matrix<T, 3, 3> matrix
{{
{0.6131324224, 0.0701243808, 0.0205876575},
{0.3395380158, 0.9163940113, 0.1095745716},
{0.0474166960, 0.0134515240, 0.8697854040}
}};
return matrix * x;
}
/**
* Transforms an ACEScg color into the linear sRGB colorspace, using the Bradford chromatic adaption transform.
*
* @param x Linear ACEScg color.
* @param return Linear sRGB color.
*
* @see https://www.colour-science.org/apps/
*/
template <class T>
math::vector<T, 3> acescg_to_srgb(const math::vector<T, 3>& x)
{
static const math::matrix<T, 3, 3> matrix
{{
{ 1.7048586763, -0.1300768242, -0.0239640729},
{-0.6217160219, 1.1407357748, -0.1289755083},
{-0.0832993717, -0.0105598017, 1.1530140189}
}};
return matrix * x;
}
/**
* Calculates the luminance of an ACEScg color.
*
* @param x Linear ACEScg color.
* @param return Luminance of @p x.
*/
template <class T>
T acescg_to_luminance(const math::vector<T, 3>& x)
{
static const math::vector<T, 3> luma = {0.2722287168, 0.6740817658, 0.0536895174};
return math::dot(x, luma);
}
#endif // ANTKEEPER_ACES_HPP

Loading…
Cancel
Save