From 81d7a863a8ace5963b7fd5b297b533bd3b73fc91 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Sat, 8 May 2021 15:28:35 +0800 Subject: [PATCH] Add color namespace, improve colorspace conversion functions, move colorspace and gamma functions from utility folder to new color namespace --- src/color/acescg.hpp | 95 ++++++++++++ src/{utility/gamma.hpp => color/color.hpp} | 34 +---- src/color/srgb.hpp | 164 +++++++++++++++++++++ src/color/xyz.hpp | 92 ++++++++++++ src/ecs/systems/astronomy-system.cpp | 4 +- src/ecs/systems/weather-system.cpp | 4 - src/game/states/play-state.cpp | 1 - src/math/matrix-type.hpp | 12 ++ src/math/vector-type.hpp | 12 ++ src/renderer/passes/sky-pass.cpp | 8 +- src/utility/aces.hpp | 80 ---------- 11 files changed, 388 insertions(+), 118 deletions(-) create mode 100644 src/color/acescg.hpp rename src/{utility/gamma.hpp => color/color.hpp} (62%) create mode 100644 src/color/srgb.hpp create mode 100644 src/color/xyz.hpp delete mode 100644 src/utility/aces.hpp diff --git a/src/color/acescg.hpp b/src/color/acescg.hpp new file mode 100644 index 0000000..71c8ec3 --- /dev/null +++ b/src/color/acescg.hpp @@ -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 . + */ + +#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 +T luminance(const math::vector3& 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 +math::vector3 to_srgb(const math::vector3& x); + +/** + * Transforms an ACEScg color into the CIE XYZ colorspace. + * + * @param x ACEScg color. + * @return return CIE XYZ color. + */ +template +math::vector3 to_xyz(const math::vector3& x); + +template +T luminance(const math::vector3& x) +{ + static const math::vector3 luma = {0.272228716780914, 0.674081765811148, 0.053689517407937}; + return math::dot(x, luma); +} + +template +math::vector3 to_srgb(const math::vector3& x) +{ + static const math::matrix3 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 +math::vector3 to_xyz(const math::vector3& x) +{ + static const math::matrix3 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 diff --git a/src/utility/gamma.hpp b/src/color/color.hpp similarity index 62% rename from src/utility/gamma.hpp rename to src/color/color.hpp index a42e512..82f83d6 100644 --- a/src/utility/gamma.hpp +++ b/src/color/color.hpp @@ -17,32 +17,14 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GAMMA_HPP -#define ANTKEEPER_GAMMA_HPP +#ifndef ANTKEEPER_COLOR_HPP +#define ANTKEEPER_COLOR_HPP -#include "math/vector-type.hpp" -#include +/// Color manipulation functions. +namespace color {} -template -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 -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 diff --git a/src/color/srgb.hpp b/src/color/srgb.hpp new file mode 100644 index 0000000..98ac149 --- /dev/null +++ b/src/color/srgb.hpp @@ -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 . + */ + +#ifndef ANTKEEPER_COLOR_SRGB_HPP +#define ANTKEEPER_COLOR_SRGB_HPP + +#include "math/math.hpp" +#include + +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 +math::vector3 eotf(const math::vector3& 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 +math::vector3 eotf_inverse(const math::vector3& l); +/// @} + +/** + * Calculates the luminance of a linear sRGB color. + * + * @param x Linear sRGB color. + * @return return Luminance of @p x. + */ +template +T luminance(const math::vector3& 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 +math::vector3 to_acescg(const math::vector3& x); + +/** + * Transforms a linear sRGB color into the CIE XYZ colorspace. + * + * @param x Linear sRGB color. + * @return CIE XYZ color. + */ +template +math::vector3 to_xyz(const math::vector3& 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 +math::vector3 eotf(const math::vector3& v) +{ + return math::vector3 + { + 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 +math::vector3 eotf_inverse(const math::vector3& l) +{ + return math::vector3 + { + eotf_inverse(l[0]), + eotf_inverse(l[1]), + eotf_inverse(l[2]) + }; +} + +template +T luminance(const math::vector3& x) +{ + static const math::vector3 luma = {0.212639005871510, 0.715168678767756, 0.072192315360734}; + return math::dot(x, luma); +} + +template +math::vector3 to_acescg(const math::vector3& x) +{ + static const math::matrix3 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 +math::vector3 to_xyz(const math::vector3& x) +{ + static const math::matrix3 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 diff --git a/src/color/xyz.hpp b/src/color/xyz.hpp new file mode 100644 index 0000000..1c79531 --- /dev/null +++ b/src/color/xyz.hpp @@ -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 . + */ + +#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 +T luminance(const math::vector3& x); + +/** + * Transforms a CIE XYZ color into the ACEScg colorspace. + * + * @param x CIE XYZ color. + * @return ACEScg color. + */ +template +math::vector3 to_acescg(const math::vector3& x); + +/** + * Transforms a CIE XYZ color into the linear sRGB colorspace. + * + * @param x CIE XYZ color. + * @return Linear sRGB color. + */ +template +math::vector3 to_srgb(const math::vector3& x); + +template +inline T luminance(const math::vector3& x) +{ + return x[1]; +} + +template +math::vector3 to_acescg(const math::vector3& x) +{ + static const math::matrix3 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 +math::vector3 to_srgb(const math::vector3& x) +{ + static const math::matrix3 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 diff --git a/src/ecs/systems/astronomy-system.cpp b/src/ecs/systems/astronomy-system.cpp index 0788572..4faff90 100644 --- a/src/ecs/systems/astronomy-system.cpp +++ b/src/ecs/systems/astronomy-system.cpp @@ -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 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(srgb_to_acescg(astro::blackbody(correlated_temperature))); + float3 correlated_color = math::type_cast(color::srgb::to_acescg(astro::blackbody(correlated_temperature))); sun_light->set_color(correlated_color); // Set sun intensity (in lux) diff --git a/src/ecs/systems/weather-system.cpp b/src/ecs/systems/weather-system.cpp index 6447f48..0cf1729 100644 --- a/src/ecs/systems/weather-system.cpp +++ b/src/ecs/systems/weather-system.cpp @@ -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 namespace ecs { diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 0f62e69..2c3b7ee 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -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" diff --git a/src/math/matrix-type.hpp b/src/math/matrix-type.hpp index 9f8a469..d60d1f1 100644 --- a/src/math/matrix-type.hpp +++ b/src/math/matrix-type.hpp @@ -43,6 +43,18 @@ struct matrix inline constexpr const row_type& operator[](std::size_t i) const noexcept { return columns[i]; } }; +/// 2x2 matrix. +template +using matrix2 = matrix; + +/// 3x3 matrix. +template +using matrix3 = matrix; + +/// 4x4 matrix. +template +using matrix4 = matrix; + } // namespace math #endif // ANTKEEPER_MATH_MATRIX_TYPE_HPP diff --git a/src/math/vector-type.hpp b/src/math/vector-type.hpp index 80aa108..6ea755d 100644 --- a/src/math/vector-type.hpp +++ b/src/math/vector-type.hpp @@ -118,6 +118,18 @@ struct vector inline constexpr std::size_t size() const noexcept { return 4; }; }; +/// 2D vector. +template +using vector2 = vector; + +/// 3D vector. +template +using vector3 = vector; + +/// 4D vector. +template +using vector4 = vector; + } // namespace math #endif // ANTKEEPER_MATH_VECTOR_TYPE_HPP diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index 42820a7..b5c4e69 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -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 @@ -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); diff --git a/src/utility/aces.hpp b/src/utility/aces.hpp deleted file mode 100644 index 4c3232b..0000000 --- a/src/utility/aces.hpp +++ /dev/null @@ -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 . - */ - -#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 -math::vector srgb_to_acescg(const math::vector& x) -{ - static const math::matrix 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 -math::vector acescg_to_srgb(const math::vector& x) -{ - static const math::matrix 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 -T acescg_to_luminance(const math::vector& x) -{ - static const math::vector luma = {0.2722287168, 0.6740817658, 0.0536895174}; - return math::dot(x, luma); -} - -#endif // ANTKEEPER_ACES_HPP