Browse Source

Remove excessive namespaces from color namespace. Add color temperature method to light classes. Clean up cascaded shadow map pass.

master
C. J. Howard 8 months ago
parent
commit
f3ee05dfc5
33 changed files with 605 additions and 555 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +11
    -11
      src/engine/color/aces.hpp
  3. +8
    -12
      src/engine/color/cat.hpp
  4. +7
    -8
      src/engine/color/cct.hpp
  5. +2
    -2
      src/engine/color/color.hpp
  6. +0
    -152
      src/engine/color/illuminant.hpp
  7. +148
    -0
      src/engine/color/illuminants.hpp
  8. +4
    -3
      src/engine/color/index.hpp
  9. +11
    -10
      src/engine/color/rgb.hpp
  10. +8
    -3
      src/engine/color/srgb.hpp
  11. +5
    -4
      src/engine/color/ucs.hpp
  12. +10
    -6
      src/engine/color/xyy.hpp
  13. +13
    -16
      src/engine/color/xyz.hpp
  14. +14
    -0
      src/engine/config.hpp.in
  15. +100
    -55
      src/engine/render/passes/cascaded-shadow-map-pass.cpp
  16. +105
    -0
      src/engine/render/passes/cascaded-shadow-map-pass.hpp
  17. +0
    -77
      src/engine/render/passes/shadow-map-pass.hpp
  18. +0
    -3
      src/engine/render/passes/sky-pass.cpp
  19. +30
    -3
      src/engine/scene/directional-light.cpp
  20. +17
    -14
      src/engine/scene/directional-light.hpp
  21. +13
    -0
      src/engine/scene/light.cpp
  22. +27
    -0
      src/engine/scene/light.hpp
  23. +2
    -2
      src/engine/scene/point-light.cpp
  24. +5
    -23
      src/engine/scene/point-light.hpp
  25. +19
    -14
      src/engine/scene/rectangle-light.cpp
  26. +18
    -22
      src/engine/scene/rectangle-light.hpp
  27. +4
    -10
      src/game/game.cpp
  28. +2
    -3
      src/game/game.hpp
  29. +7
    -67
      src/game/states/experiments/treadmill-experiment-state.cpp
  30. +0
    -2
      src/game/states/nest-view-state.cpp
  31. +5
    -12
      src/game/systems/blackbody-system.cpp
  32. +0
    -9
      src/game/systems/blackbody-system.hpp
  33. +10
    -11
      src/game/world.cpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.25)
option(APPLICATION_NAME "Application name" "Antkeeper")
option(APPLICATION_VERSION "Application version string" "0.0.0")
option(APPLICATION_AUTHOR "Application author" "C. J. Howard")

+ 11
- 11
src/engine/color/aces.hpp View File

@ -26,33 +26,33 @@
namespace color {
/// ACES color spaces.
namespace aces {
/// @name ACES color spaces
/// @{
/// CIE xy chromaticity coordinates of the ACES white point (~D60).
template <class T>
constexpr math::vec2<T> white_point = {T{0.32168}, T{0.33767}};
constexpr math::vec2<T> aces_white_point = {T{0.32168}, T{0.33767}};
/// ACES AP0 color space.
template <class T>
constexpr rgb::color_space<T> ap0
constexpr rgb_color_space<T> aces_ap0
(
{T{0.7347}, T{ 0.2653}},
{T{0.0000}, T{ 1.0000}},
{T{0.0001}, T{-0.0770}},
aces::white_point<T>,
aces_white_point<T>,
nullptr,
nullptr
);
/// ACES AP1 color space.
template <class T>
constexpr rgb::color_space<T> ap1
constexpr rgb_color_space<T> aces_ap1
(
{T{0.713}, T{0.293}},
{T{0.165}, T{0.830}},
{T{0.128}, T{0.044}},
aces::white_point<T>,
aces_white_point<T>,
nullptr,
nullptr
);
@ -66,7 +66,7 @@ constexpr rgb::color_space ap1
* @return Saturation adjustment matrix.
*/
template <class T>
[[nodiscard]] constexpr math::mat3<T> adjust_saturation(T s, const math::vec3<T>& to_y) noexcept
[[nodiscard]] constexpr math::mat3<T> aces_adjust_saturation(T s, const math::vec3<T>& to_y) noexcept
{
const math::vec3<T> v = to_y * (T{1} - s);
return math::mat3<T>
@ -79,13 +79,13 @@ template
/// ACES AP1 RRT saturation adjustment matrix.
template <class T>
constexpr math::mat3<T> ap1_rrt_sat = aces::adjust_saturation(T{0.96}, ap1<T>.to_y);
constexpr math::mat3<T> aces_ap1_rrt_sat = aces_adjust_saturation(T{0.96}, ap1<T>.to_y);
/// ACES AP1 ODT saturation adjustment matrix.
template <class T>
constexpr math::mat3<T> ap1_odt_sat = aces::adjust_saturation(T{0.93}, ap1<T>.to_y);
constexpr math::mat3<T> aces_ap1_odt_sat = aces_adjust_saturation(T{0.93}, ap1<T>.to_y);
} // namespace aces
/// @}
} // namespace color

+ 8
- 12
src/engine/color/cat.hpp View File

@ -25,8 +25,8 @@
namespace color {
/// Chromatic adaption transforms (CAT).
namespace cat {
/// @name Chromatic adaption transforms (CAT)
/// @{
/**
* Bradford cone response matrix.
@ -35,7 +35,7 @@ namespace cat {
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::mat3<T> bradford =
constexpr math::mat3<T> bradford_cone_response =
{
T{ 0.8951}, T{-0.7502}, T{ 0.0389},
T{ 0.2664}, T{ 1.7135}, T{-0.0685},
@ -48,7 +48,7 @@ constexpr math::mat3 bradford =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::mat3<T> von_kries =
constexpr math::mat3<T> von_kries_cone_response =
{
T{ 0.40024}, T{-0.22630}, T{0.00000},
T{ 0.70760}, T{ 1.16532}, T{0.00000},
@ -61,12 +61,7 @@ constexpr math::mat3 von_kries =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::mat3<T> xyz_scaling =
{
T{1}, T{0}, T{0},
T{0}, T{1}, T{0},
T{0}, T{0}, T{1}
};
constexpr math::mat3<T> xyz_scaling_cone_response = math::mat3<T>::identity();
/**
* Constructs a chromatic adaptation transform (CAT) matrix.
@ -81,7 +76,7 @@ constexpr math::mat3 xyz_scaling =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
[[nodiscard]] constexpr math::mat3<T> matrix(const math::vec2<T>& w0, const math::vec2<T>& w1, const math::mat3<T>& cone_response = bradford<T>) noexcept
[[nodiscard]] constexpr math::mat3<T> cat_matrix(const math::vec2<T>& w0, const math::vec2<T>& w1, const math::mat3<T>& cone_response = bradford_cone_response<T>) noexcept
{
// Convert CIE xy chromaticity coordinates to CIE XYZ colors
const math::vec3<T> w0_xyz = {w0[0] / w0[1], T{1}, (T{1} - w0[0] - w0[1]) / w0[1]};
@ -101,7 +96,8 @@ template
return math::inverse(cone_response) * scale * cone_response;
}
} // namespace cat
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_CAT_HPP

+ 7
- 8
src/engine/color/cct.hpp View File

@ -26,8 +26,8 @@
namespace color {
/// Correlated color temperature (CCT).
namespace cct {
/// @name Correlated color temperature (CCT)
/// @{
/**
* Calculates CIE 1960 UCS colorspace chromaticity coordinates given a correlated color temperature using Krystek's algorithm.
@ -38,7 +38,7 @@ namespace cct {
* @see Krystek, M. (1985), An algorithm to calculate correlated colour temperature. Color Res. Appl., 10: 38-40.
*/
template <class T>
[[nodiscard]] math::vec2<T> to_ucs(T t) noexcept
[[nodiscard]] math::vec2<T> cct_to_ucs(T t) noexcept
{
const T tt = t * t;
return math::vec2<T>
@ -55,9 +55,9 @@ template
* @return CIE xyY color with `Y = 1`.
*/
template <class T>
math::vec3<T> to_xyy(T t)
math::vec3<T> cct_to_xyy(T t)
{
return ucs::to_xyy(to_ucs(t), T{1});
return ucs_to_xyy(cct_to_ucs(t), T{1});
}
/**
@ -67,12 +67,11 @@ math::vec3 to_xyy(T t)
* @return CIE XYZ color with `Y = 1`.
*/
template <class T>
math::vec3<T> to_xyz(T t)
math::vec3<T> cct_to_xyz(T t)
{
return xyy::to_xyz(to_xyy(t));
return xyy_to_xyz(cct_to_xyy(t));
}
} // namespace cct
} // namespace color
#endif // ANTKEEPER_COLOR_CCT_HPP

+ 2
- 2
src/engine/color/color.hpp View File

@ -20,13 +20,13 @@
#ifndef ANTKEEPER_COLOR_HPP
#define ANTKEEPER_COLOR_HPP
/// Color manipulation.
/// Color science.
namespace color {}
#include <engine/color/aces.hpp>
#include <engine/color/cat.hpp>
#include <engine/color/cct.hpp>
#include <engine/color/illuminant.hpp>
#include <engine/color/illuminants.hpp>
#include <engine/color/index.hpp>
#include <engine/color/rgb.hpp>
#include <engine/color/srgb.hpp>

+ 0
- 152
src/engine/color/illuminant.hpp View File

@ -1,152 +0,0 @@
/*
* Copyright (C) 2023 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_ILLUMINANT_HPP
#define ANTKEEPER_COLOR_ILLUMINANT_HPP
#include <engine/math/vector.hpp>
namespace color {
/**
* CIE standard illuminants.
*
* @see https://en.wikipedia.org/wiki/Standard_illuminant
*/
namespace illuminant {
/// CIE 1931 2 Degree Standard Observer illuminants.
namespace deg2 {
template <class T>
constexpr math::vec2<T> a = {T{0.44757}, T{0.40745}};
template <class T>
constexpr math::vec2<T> b = {T{0.34842}, T{0.35161}};
template <class T>
constexpr math::vec2<T> c = {T{0.31006}, T{0.31616}};
template <class T>
constexpr math::vec2<T> d50 = {T{0.34567}, T{0.35850}};
template <class T>
constexpr math::vec2<T> d55 = {T{0.33242}, T{0.34743}};
template <class T>
constexpr math::vec2<T> d65 = {T{0.31271}, T{0.32902}};
template <class T>
constexpr math::vec2<T> d75 = {T{0.29902}, T{0.31485}};
template <class T>
constexpr math::vec2<T> d93 = {T{0.28315}, T{0.29711}};
template <class T>
constexpr math::vec2<T> e = {T{0.33333}, T{0.33333}};
template <class T>
constexpr math::vec2<T> f1 = {T{0.31310}, T{0.33727}};
template <class T>
constexpr math::vec2<T> f2 = {T{0.37208}, T{0.37529}};
template <class T>
constexpr math::vec2<T> f3 = {T{0.40910}, T{0.39430}};
template <class T>
constexpr math::vec2<T> f4 = {T{0.44018}, T{0.40329}};
template <class T>
constexpr math::vec2<T> f5 = {T{0.31379}, T{0.34531}};
template <class T>
constexpr math::vec2<T> f6 = {T{0.37790}, T{0.38835}};
template <class T>
constexpr math::vec2<T> f7 = {T{0.31292}, T{0.32933}};
template <class T>
constexpr math::vec2<T> f8 = {T{0.34588}, T{0.35875}};
template <class T>
constexpr math::vec2<T> f9 = {T{0.37417}, T{0.37281}};
template <class T>
constexpr math::vec2<T> f10 = {T{0.34609}, T{0.35986}};
template <class T>
constexpr math::vec2<T> f11 = {T{0.38052}, T{0.37713}};
template <class T>
constexpr math::vec2<T> f12 = {T{0.43695}, T{0.40441}};
template <class T>
constexpr math::vec2<T> led_b1 = {T{0.4560}, T{0.4078}};
template <class T>
constexpr math::vec2<T> led_b2 = {T{0.4357}, T{0.4012}};
template <class T>
constexpr math::vec2<T> led_b3 = {T{0.3756}, T{0.3723}};
template <class T>
constexpr math::vec2<T> led_b4 = {T{0.3422}, T{0.3502}};
template <class T>
constexpr math::vec2<T> led_b5 = {T{0.3118}, T{0.3236}};
template <class T>
constexpr math::vec2<T> led_bh1 = {T{0.4474}, T{0.4066}};
template <class T>
constexpr math::vec2<T> led_rgb1 = {T{0.4557}, T{0.4211}};
template <class T>
constexpr math::vec2<T> led_v1 = {T{0.4560}, T{0.4548}};
template <class T>
constexpr math::vec2<T> led_v2 = {T{0.3781}, T{0.3775}};
} // deg2
/// CIE 1964 10 Degree Standard Observer illuminants.
namespace deg10 {
template <class T>
constexpr math::vec2<T> a = {T{0.45117}, T{0.40594}};
template <class T>
constexpr math::vec2<T> b = {T{0.34980}, T{0.35270}};
template <class T>
constexpr math::vec2<T> c = {T{0.31039}, T{0.31905}};
template <class T>
constexpr math::vec2<T> d50 = {T{0.34773}, T{0.35952}};
template <class T>
constexpr math::vec2<T> d55 = {T{0.33411}, T{0.34877}};
template <class T>
constexpr math::vec2<T> d65 = {T{0.31382}, T{0.33100}};
template <class T>
constexpr math::vec2<T> d75 = {T{0.29968}, T{0.31740}};
template <class T>
constexpr math::vec2<T> d93 = {T{0.28327}, T{0.30043}};
template <class T>
constexpr math::vec2<T> e = {T{0.33333}, T{0.33333}};
template <class T>
constexpr math::vec2<T> f1 = {T{0.31811}, T{0.33559}};
template <class T>
constexpr math::vec2<T> f2 = {T{0.37925}, T{0.36733}};
template <class T>
constexpr math::vec2<T> f3 = {T{0.41761}, T{0.38324}};
template <class T>
constexpr math::vec2<T> f4 = {T{0.44920}, T{0.39074}};
template <class T>
constexpr math::vec2<T> f5 = {T{0.31975}, T{0.34246}};
template <class T>
constexpr math::vec2<T> f6 = {T{0.38660}, T{0.37847}};
template <class T>
constexpr math::vec2<T> f7 = {T{0.31569}, T{0.32960}};
template <class T>
constexpr math::vec2<T> f8 = {T{0.34902}, T{0.35939}};
template <class T>
constexpr math::vec2<T> f9 = {T{0.37829}, T{0.37045}};
template <class T>
constexpr math::vec2<T> f10 = {T{0.35090}, T{0.35444}};
template <class T>
constexpr math::vec2<T> f11 = {T{0.38541}, T{0.37123}};
template <class T>
constexpr math::vec2<T> f12 = {T{0.44256}, T{0.39717}};
} // namespace deg10
} // namespace illuminant
} // namespace color
#endif // ANTKEEPER_COLOR_ILLUMINANT_HPP

+ 148
- 0
src/engine/color/illuminants.hpp View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2023 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_ILLUMINANTS_HPP
#define ANTKEEPER_COLOR_ILLUMINANTS_HPP
#include <engine/math/vector.hpp>
namespace color {
/// @name CIE standard illuminants
/// @{
/// @name CIE 1931 2 Degree Standard Observer illuminants
/// @{
template <class T>
inline constexpr math::vec2<T> deg2_a = {T{0.44757}, T{0.40745}};
template <class T>
inline constexpr math::vec2<T> deg2_b = {T{0.34842}, T{0.35161}};
template <class T>
inline constexpr math::vec2<T> deg2_c = {T{0.31006}, T{0.31616}};
template <class T>
inline constexpr math::vec2<T> deg2_d50 = {T{0.34567}, T{0.35850}};
template <class T>
inline constexpr math::vec2<T> deg2_d55 = {T{0.33242}, T{0.34743}};
template <class T>
inline constexpr math::vec2<T> deg2_d65 = {T{0.31271}, T{0.32902}};
template <class T>
inline constexpr math::vec2<T> deg2_d75 = {T{0.29902}, T{0.31485}};
template <class T>
inline constexpr math::vec2<T> deg2_d93 = {T{0.28315}, T{0.29711}};
template <class T>
inline constexpr math::vec2<T> deg2_e = {T{0.33333}, T{0.33333}};
template <class T>
inline constexpr math::vec2<T> deg2_f1 = {T{0.31310}, T{0.33727}};
template <class T>
inline constexpr math::vec2<T> deg2_f2 = {T{0.37208}, T{0.37529}};
template <class T>
inline constexpr math::vec2<T> deg2_f3 = {T{0.40910}, T{0.39430}};
template <class T>
inline constexpr math::vec2<T> deg2_f4 = {T{0.44018}, T{0.40329}};
template <class T>
inline constexpr math::vec2<T> deg2_f5 = {T{0.31379}, T{0.34531}};
template <class T>
inline constexpr math::vec2<T> deg2_f6 = {T{0.37790}, T{0.38835}};
template <class T>
inline constexpr math::vec2<T> deg2_f7 = {T{0.31292}, T{0.32933}};
template <class T>
inline constexpr math::vec2<T> deg2_f8 = {T{0.34588}, T{0.35875}};
template <class T>
inline constexpr math::vec2<T> deg2_f9 = {T{0.37417}, T{0.37281}};
template <class T>
inline constexpr math::vec2<T> deg2_f10 = {T{0.34609}, T{0.35986}};
template <class T>
inline constexpr math::vec2<T> deg2_f11 = {T{0.38052}, T{0.37713}};
template <class T>
inline constexpr math::vec2<T> deg2_f12 = {T{0.43695}, T{0.40441}};
template <class T>
inline constexpr math::vec2<T> deg2_led_b1 = {T{0.4560}, T{0.4078}};
template <class T>
inline constexpr math::vec2<T> deg2_led_b2 = {T{0.4357}, T{0.4012}};
template <class T>
inline constexpr math::vec2<T> deg2_led_b3 = {T{0.3756}, T{0.3723}};
template <class T>
inline constexpr math::vec2<T> deg2_led_b4 = {T{0.3422}, T{0.3502}};
template <class T>
inline constexpr math::vec2<T> deg2_led_b5 = {T{0.3118}, T{0.3236}};
template <class T>
inline constexpr math::vec2<T> deg2_led_bh1 = {T{0.4474}, T{0.4066}};
template <class T>
inline constexpr math::vec2<T> deg2_led_rgb1 = {T{0.4557}, T{0.4211}};
template <class T>
inline constexpr math::vec2<T> deg2_led_v1 = {T{0.4560}, T{0.4548}};
template <class T>
inline constexpr math::vec2<T> deg2_led_v2 = {T{0.3781}, T{0.3775}};
/// @}
/// @name CIE 1964 10 Degree Standard Observer illuminants
/// @{
template <class T>
inline constexpr math::vec2<T> deg10_a = {T{0.45117}, T{0.40594}};
template <class T>
inline constexpr math::vec2<T> deg10_b = {T{0.34980}, T{0.35270}};
template <class T>
inline constexpr math::vec2<T> deg10_c = {T{0.31039}, T{0.31905}};
template <class T>
inline constexpr math::vec2<T> deg10_d50 = {T{0.34773}, T{0.35952}};
template <class T>
inline constexpr math::vec2<T> deg10_d55 = {T{0.33411}, T{0.34877}};
template <class T>
inline constexpr math::vec2<T> deg10_d65 = {T{0.31382}, T{0.33100}};
template <class T>
inline constexpr math::vec2<T> deg10_d75 = {T{0.29968}, T{0.31740}};
template <class T>
inline constexpr math::vec2<T> deg10_d93 = {T{0.28327}, T{0.30043}};
template <class T>
inline constexpr math::vec2<T> deg10_e = {T{0.33333}, T{0.33333}};
template <class T>
inline constexpr math::vec2<T> deg10_f1 = {T{0.31811}, T{0.33559}};
template <class T>
inline constexpr math::vec2<T> deg10_f2 = {T{0.37925}, T{0.36733}};
template <class T>
inline constexpr math::vec2<T> deg10_f3 = {T{0.41761}, T{0.38324}};
template <class T>
inline constexpr math::vec2<T> deg10_f4 = {T{0.44920}, T{0.39074}};
template <class T>
inline constexpr math::vec2<T> deg10_f5 = {T{0.31975}, T{0.34246}};
template <class T>
inline constexpr math::vec2<T> deg10_f6 = {T{0.38660}, T{0.37847}};
template <class T>
inline constexpr math::vec2<T> deg10_f7 = {T{0.31569}, T{0.32960}};
template <class T>
inline constexpr math::vec2<T> deg10_f8 = {T{0.34902}, T{0.35939}};
template <class T>
inline constexpr math::vec2<T> deg10_f9 = {T{0.37829}, T{0.37045}};
template <class T>
inline constexpr math::vec2<T> deg10_f10 = {T{0.35090}, T{0.35444}};
template <class T>
inline constexpr math::vec2<T> deg10_f11 = {T{0.38541}, T{0.37123}};
template <class T>
inline constexpr math::vec2<T> deg10_f12 = {T{0.44256}, T{0.39717}};
/// @}
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_ILLUMINANTS_HPP

+ 4
- 3
src/engine/color/index.hpp View File

@ -22,8 +22,8 @@
namespace color {
/// Color indices.
namespace index {
/// @name Color indices.
/// @{
/**
* Approximates the temperature of a star, given its B-V index.
@ -39,7 +39,8 @@ template
return T{4600} * (T{1} / (T{0.92} * bv + T{1.7}) + T{1} / (T{0.92} * bv + T{0.62}));
}
} // namespace index
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_INDEX_HPP

+ 11
- 10
src/engine/color/rgb.hpp View File

@ -26,8 +26,8 @@
namespace color {
/// RGB color spaces.
namespace rgb {
/// @name RGB color spaces
/// @{
/**
* Constructs a matrix which transforms an RGB color into a CIE XYZ color.
@ -43,7 +43,7 @@ namespace rgb {
* @see https://mina86.com/2019/srgb-xyz-matrix/
*/
template <class T>
[[nodiscard]] constexpr math::mat3<T> to_xyz(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w)
[[nodiscard]] constexpr math::mat3<T> rgb_to_xyz(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w)
{
const math::mat3<T> m =
{
@ -66,10 +66,10 @@ template
* RGB color space.
*/
template <class T>
struct color_space
struct rgb_color_space
{
/// Transfer function function pointer type.
typedef math::vec3<T> (*transfer_function_type)(const math::vec3<T>&);
using transfer_function_type = math::vec3<T> (*)(const math::vec3<T>&);
/// CIE xy chromaticity coordinates of the red primary.
const math::vec2<T> r;
@ -106,14 +106,14 @@ struct color_space
* @param b CIE xy chromaticity coordinates of the blue primary.
* @param w CIE xy chromaticity coordinates of the white point.
*/
constexpr color_space(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w, transfer_function_type eotf, transfer_function_type oetf):
constexpr rgb_color_space(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w, transfer_function_type eotf, transfer_function_type oetf):
r(r),
g(g),
b(b),
w(w),
eotf(eotf),
oetf(oetf),
to_xyz(color::rgb::to_xyz<T>(r, g, b, w)),
to_xyz(rgb_to_xyz<T>(r, g, b, w)),
from_xyz(math::inverse(to_xyz)),
to_y{to_xyz[0][1], to_xyz[1][1], to_xyz[2][1]}
{}
@ -140,12 +140,13 @@ struct color_space
* @return Color space transformation matrix.
*/
template <class T>
[[nodiscard]] constexpr math::mat3<T> to_rgb(const color_space<T>& s0, const color_space<T>& s1, const math::mat3<T>& cone_response = color::cat::bradford<T>)
[[nodiscard]] constexpr math::mat3<T> rgb_to_rgb(const rgb_color_space<T>& s0, const rgb_color_space<T>& s1, const math::mat3<T>& cone_response = bradford_cone_response<T>)
{
return s1.from_xyz * color::cat::matrix(s0.w, s1.w, cone_response) * s0.to_xyz;
return s1.from_xyz * cat_matrix(s0.w, s1.w, cone_response) * s0.to_xyz;
}
} // namespace rgb
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_RGB_HPP

+ 8
- 3
src/engine/color/srgb.hpp View File

@ -21,12 +21,15 @@
#define ANTKEEPER_COLOR_SRGB_HPP
#include <engine/color/rgb.hpp>
#include <engine/color/illuminant.hpp>
#include <engine/color/illuminants.hpp>
#include <engine/math/vector.hpp>
#include <cmath>
namespace color {
/// @name sRGB color space
/// @{
/**
* sRGB opto-electronic transfer function (OETF). Maps a linear sRGB color to a non-linear sRGB signal.
*
@ -69,16 +72,18 @@ template
/// sRGB color space.
template <class T>
constexpr rgb::color_space<T> srgb
constexpr rgb_color_space<T> srgb
(
{T{0.64}, T{0.33}},
{T{0.30}, T{0.60}},
{T{0.15}, T{0.06}},
color::illuminant::deg2::d65<T>,
deg2_d65<T>,
&srgb_eotf<T>,
&srgb_oetf<T>
);
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_SRGB_HPP

+ 5
- 4
src/engine/color/ucs.hpp View File

@ -24,8 +24,8 @@
namespace color {
/// CIE 1960 UCS color space.
namespace ucs {
/// @name CIE 1960 UCS color space
/// @{
/**
* Transforms CIE 1960 UCS chromaticity coordinates into the CIE xyY colorspace.
@ -35,13 +35,14 @@ namespace ucs {
* @return CIE xyY color.
*/
template <class T>
[[nodiscard]] constexpr math::vec3<T> to_xyy(const math::vec2<T>& uv, T y = T{1}) noexcept
[[nodiscard]] constexpr math::vec3<T> ucs_to_xyy(const math::vec2<T>& uv, T y = T{1}) noexcept
{
const T d = T{1} / (T{2} * uv[0] - T{8} * uv[1] + T{4});
return math::vec3<T>{(T{3} * uv[0]) * d, (T{2} * uv[1]) * d, y};
}
} // namespace ucs
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_UCS_HPP

+ 10
- 6
src/engine/color/xyy.hpp View File

@ -24,17 +24,18 @@
namespace color {
/// CIE xyY color space.
namespace xyy {
/// @name CIE xyY color space.
/// @{
/**
* Returns the luminance of a CIE xyY color.
*
* @param x CIE xyY color.
*
* @return return Luminance of @p x.
*/
template <class T>
[[nodiscard]] inline constexpr T luminance(const math::vec3<T>& x) noexcept
[[nodiscard]] inline constexpr T xyy_to_luminance(const math::vec3<T>& x) noexcept
{
return x[2];
}
@ -43,10 +44,11 @@ template
* Transforms a CIE xyY color into the CIE 1960 UCS colorspace.
*
* @param x CIE xyY color.
*
* @return CIE 1960 UCS color.
*/
template <class T>
[[nodiscard]] constexpr math::vec2<T> to_ucs(const math::vec3<T>& x) noexcept
[[nodiscard]] constexpr math::vec2<T> xyy_to_ucs(const math::vec3<T>& x) noexcept
{
const T d = (T{1} / (T{-2} * x[0] + T{12} * x[1] + T{3}));
return math::vec2<T>{(T{4} * x[0]) * d, (T{6} * x[1]) * d};
@ -56,15 +58,17 @@ template
* Transforms a CIE xyY color into the CIE XYZ colorspace.
*
* @param x CIE xyY color.
*
* @return CIE XYZ color.
*/
template <class T>
[[nodiscard]] constexpr math::vec3<T> to_xyz(const math::vec3<T>& x) noexcept
[[nodiscard]] constexpr math::vec3<T> xyy_to_xyz(const math::vec3<T>& x) noexcept
{
return math::vec3<T>{(x[0] * x[2]) / x[1], x[2], ((T{1} - x[0] - x[1]) * x[2]) / x[1]};
}
} // namespace xyy
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_XYY_HPP

+ 13
- 16
src/engine/color/xyz.hpp View File

@ -24,12 +24,8 @@
namespace color {
/**
* CIE XYZ color space.
*
* @see https://en.wikipedia.org/wiki/CIE_1931_color_space
*/
namespace xyz {
/// @name CIE XYZ color space
/// @{
/**
* Returns the luminance of a CIE XYZ color.
@ -38,7 +34,7 @@ namespace xyz {
* @return return Luminance of @p x.
*/
template <class T>
[[nodiscard]] inline constexpr T luminance(const math::vec3<T>& x) noexcept
[[nodiscard]] inline constexpr T xyz_to_luminance(const math::vec3<T>& x) noexcept
{
return x[1];
}
@ -50,7 +46,7 @@ template
* @return CIE xyY color.
*/
template <class T>
[[nodiscard]] constexpr math::vec3<T> to_xyy(const math::vec3<T>& x) noexcept
[[nodiscard]] constexpr math::vec3<T> xyz_to_xyy(const math::vec3<T>& x) noexcept
{
const T sum = x[0] + x[1] + x[2];
return math::vec3<T>{x[0] / sum, x[1] / sum, x[1]};
@ -65,7 +61,7 @@ template
* @see match(T)
*/
template <class T>
[[nodiscard]] T match_x(T lambda)
[[nodiscard]] T xyz_match_x(T lambda)
{
const T t0 = (lambda - T{442.0}) * ((lambda < T{442.0}) ? T{0.0624} : T{0.0374});
const T t1 = (lambda - T{599.8}) * ((lambda < T{599.8}) ? T{0.0264} : T{0.0323});
@ -87,7 +83,7 @@ template
* @see match(T)
*/
template <class T>
[[nodiscard]] T match_y(T lambda)
[[nodiscard]] T xyz_match_y(T lambda)
{
const T t0 = (lambda - T{568.8}) * ((lambda < T{568.8}) ? T{0.0213} : T{0.0247});
const T t1 = (lambda - T{530.9}) * ((lambda < T{530.9}) ? T{0.0613} : T{0.0322});
@ -107,7 +103,7 @@ template
* @see match(T)
*/
template <class T>
[[nodiscard]] T match_z(T lambda)
[[nodiscard]] T xyz_match_z(T lambda)
{
const T t0 = (lambda - T{437.0}) * ((lambda < T{437.0}) ? T{0.0845} : T{0.0278});
const T t1 = (lambda - T{459.0}) * ((lambda < T{459.0}) ? T{0.0385} : T{0.0725});
@ -131,17 +127,18 @@ template
* @see Wyman, C., Sloan, P.J., & Shirley, P. (2013). Simple Analytic Approximations to the CIE XYZ Color Matching Functions.
*/
template <class T>
[[nodiscard]] math::vec3<T> match(T lambda)
[[nodiscard]] math::vec3<T> xyz_match(T lambda)
{
return math::vec3<T>
{
match_x<T>(lambda),
match_y<T>(lambda),
match_z<T>(lambda)
xyz_match_x<T>(lambda),
xyz_match_y<T>(lambda),
xyz_match_z<T>(lambda)
};
}
} // namespace xyz
/// @}
} // namespace color
#endif // ANTKEEPER_COLOR_XYZ_HPP

+ 14
- 0
src/engine/config.hpp.in View File

@ -28,6 +28,7 @@
#endif
#include <engine/math/vector.hpp>
#include <engine/color/aces.hpp>
/// Global configuration constants.
namespace config {
@ -92,6 +93,19 @@ inline constexpr int opengl_min_stencil_size = 0;
/// @}
/// @name Rendering config
/// @{
/**
* Scene-linear color space.
*
* @tparam T Scalar type.
*/
template <class T>
inline constexpr color::rgb_color_space<T> scene_linear_color_space = color::aces_ap1<T>;
/// @}
inline constexpr math::vector<float, 3> global_forward = {0.0f, 0.0f, -1.0f};
inline constexpr math::vector<float, 3> global_up = {0.0f, 1.0f, 0.0f};
inline constexpr math::vector<float, 3> global_right = {1.0f, 0.0f, 0.0f};

src/engine/render/passes/shadow-map-pass.cpp → src/engine/render/passes/cascaded-shadow-map-pass.cpp View File

@ -17,7 +17,7 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include <engine/render/passes/shadow-map-pass.hpp>
#include <engine/render/passes/cascaded-shadow-map-pass.hpp>
#include <engine/resources/resource-manager.hpp>
#include <engine/gl/rasterizer.hpp>
#include <engine/gl/framebuffer.hpp>
@ -44,47 +44,40 @@ namespace render {
static bool operation_compare(const render::operation* a, const render::operation* b);
shadow_map_pass::shadow_map_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager):
cascaded_shadow_map_pass::cascaded_shadow_map_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager):
pass(rasterizer, nullptr)
{
std::unordered_map<std::string, std::string> definitions;
definitions["VERTEX_POSITION"] = std::to_string(vertex_attribute::position);
definitions["VERTEX_UV"] = std::to_string(vertex_attribute::uv);
definitions["VERTEX_NORMAL"] = std::to_string(vertex_attribute::normal);
definitions["VERTEX_TANGENT"] = std::to_string(vertex_attribute::tangent);
definitions["VERTEX_COLOR"] = std::to_string(vertex_attribute::color);
definitions["VERTEX_BONE_INDEX"] = std::to_string(vertex_attribute::bone_index);
definitions["VERTEX_BONE_WEIGHT"] = std::to_string(vertex_attribute::bone_weight);
definitions["VERTEX_BONE_WEIGHT"] = std::to_string(vertex_attribute::bone_weight);
definitions["MAX_BONE_COUNT"] = std::to_string(64);
// Init shader template definitions
m_shader_template_definitions["VERTEX_POSITION"] = std::to_string(vertex_attribute::position);
m_shader_template_definitions["VERTEX_UV"] = std::to_string(vertex_attribute::uv);
m_shader_template_definitions["VERTEX_NORMAL"] = std::to_string(vertex_attribute::normal);
m_shader_template_definitions["VERTEX_TANGENT"] = std::to_string(vertex_attribute::tangent);
m_shader_template_definitions["VERTEX_COLOR"] = std::to_string(vertex_attribute::color);
m_shader_template_definitions["VERTEX_BONE_INDEX"] = std::to_string(vertex_attribute::bone_index);
m_shader_template_definitions["VERTEX_BONE_WEIGHT"] = std::to_string(vertex_attribute::bone_weight);
m_shader_template_definitions["VERTEX_BONE_WEIGHT"] = std::to_string(vertex_attribute::bone_weight);
m_shader_template_definitions["MAX_BONE_COUNT"] = std::to_string(m_max_bone_count);
// Load unskinned shader template
auto unskinned_shader_template = resource_manager->load<gl::shader_template>("depth-unskinned.glsl");
// Build unskinned shader program
unskinned_shader_program = unskinned_shader_template->build(definitions);
if (!unskinned_shader_program->linked())
// Static mesh shader
{
debug::log::error("Failed to build unskinned shadow map shader program: {}", unskinned_shader_program->info());
debug::log::warning("{}", unskinned_shader_template->configure(gl::shader_stage::vertex));
// Load static mesh shader template
m_static_mesh_shader_template = resource_manager->load<gl::shader_template>("shadow-cascade-static-mesh.glsl");
// Build static mesh shader program
rebuild_static_mesh_shader_program();
}
unskinned_model_view_projection_var = unskinned_shader_program->variable("model_view_projection");
// Load skinned shader template
auto skinned_shader_template = resource_manager->load<gl::shader_template>("depth-skinned.glsl");
// Build skinned shader program
skinned_shader_program = skinned_shader_template->build(definitions);
if (!skinned_shader_program->linked())
// Skeletal mesh shader
{
debug::log::error("Failed to build skinned shadow map shader program: {}", skinned_shader_program->info());
debug::log::warning("{}", skinned_shader_template->configure(gl::shader_stage::vertex));
// Load skeletal mesh shader template
m_skeletal_mesh_shader_template = resource_manager->load<gl::shader_template>("shadow-cascade-skeletal-mesh.glsl");
// Build static mesh shader program
rebuild_skeletal_mesh_shader_program();
}
skinned_model_view_projection_var = skinned_shader_program->variable("model_view_projection");
skinned_matrix_palette_var = skinned_shader_program->variable("matrix_palette");
}
void shadow_map_pass::render(render::context& ctx)
void cascaded_shadow_map_pass::render(render::context& ctx)
{
// For each light
const auto& lights = ctx.collection->get_objects(scene::light::object_type_id);
@ -104,29 +97,39 @@ void shadow_map_pass::render(render::context& ctx)
continue;
}
// Ignore lights that don't share a common layer with the camera
if (!(directional_light.get_layer_mask() & ctx.camera->get_layer_mask()))
{
return;
}
// Ignore improperly-configured lights
if (!directional_light.get_shadow_framebuffer() || !directional_light.get_shadow_cascade_count())
if (!directional_light.get_shadow_framebuffer())
{
continue;
}
// Render cascaded shadow maps
render_csm(directional_light, ctx);
// Render shadow atlas
render_atlas(directional_light, ctx);
}
}
void shadow_map_pass::render_csm(scene::directional_light& light, render::context& ctx)
void cascaded_shadow_map_pass::set_max_bone_count(std::size_t bone_count)
{
// Get light layer mask
const auto light_layer_mask = light.get_layer_mask();
if (!(light_layer_mask & ctx.camera->get_layer_mask()))
if (m_max_bone_count != bone_count)
{
return;
m_max_bone_count = bone_count;
// Update max bone count shader template definition
m_shader_template_definitions["MAX_BONE_COUNT"] = std::to_string(m_max_bone_count);
// Rebuild skeletal mesh shader
rebuild_skeletal_mesh_shader_program();
}
rasterizer->use_framebuffer(*light.get_shadow_framebuffer());
}
void cascaded_shadow_map_pass::render_atlas(scene::directional_light& light, render::context& ctx)
{
// Disable blending
glDisable(GL_BLEND);
@ -140,11 +143,19 @@ void shadow_map_pass::render_csm(scene::directional_light& light, render::contex
glCullFace(GL_BACK);
bool two_sided = false;
// Bind and clear shadow atlas framebuffer
rasterizer->use_framebuffer(*light.get_shadow_framebuffer());
rasterizer->clear_framebuffer(false, true, false);
// Get light layer mask
const auto light_layer_mask = light.get_layer_mask();
// Get camera
const scene::camera& camera = *ctx.camera;
// Calculate distance to shadow cascade depth clipping planes
const float shadow_clip_far = math::lerp(camera.get_clip_near(), camera.get_clip_far(), light.get_shadow_cascade_coverage());
const auto shadow_clip_near = camera.get_clip_near();
const auto shadow_clip_far = camera.get_clip_near() + light.get_shadow_distance();
// Get light shadow cascade distances and matrices
const auto cascade_count = light.get_shadow_cascade_count();
@ -157,11 +168,11 @@ void shadow_map_pass::render_csm(scene::directional_light& light, render::contex
{
const float weight = static_cast<float>(i + 1) / static_cast<float>(cascade_count);
// Calculate linear and logarithmic distribution distances
const float linear_distance = math::lerp(camera.get_clip_near(), shadow_clip_far, weight);
const float log_distance = math::log_lerp(camera.get_clip_near(), shadow_clip_far, weight);
// Calculate linear and logarithmic split distances
const float linear_distance = math::lerp(shadow_clip_near, shadow_clip_far, weight);
const float log_distance = math::log_lerp(shadow_clip_near, shadow_clip_far, weight);
// Interpolate between linear and logarithmic distribution distances
// Interpolate between linear and logarithmic split distances
cascade_distances[i] = math::lerp(linear_distance, log_distance, light.get_shadow_cascade_distribution());
}
@ -276,7 +287,7 @@ void shadow_map_pass::render_csm(scene::directional_light& light, render::contex
}
// Switch shader programs if necessary
gl::shader_program* shader_program = (operation->matrix_palette.empty()) ? unskinned_shader_program.get() : skinned_shader_program.get();
gl::shader_program* shader_program = (operation->matrix_palette.empty()) ? m_static_mesh_shader_program.get() : m_skeletal_mesh_shader_program.get();
if (active_shader_program != shader_program)
{
active_shader_program = shader_program;
@ -287,14 +298,14 @@ void shadow_map_pass::render_csm(scene::directional_light& light, render::contex
math::fmat4 model_view_projection = light_view_projection * operation->transform;
// Upload operation-dependent parameters to shader program
if (active_shader_program == unskinned_shader_program.get())
if (active_shader_program == m_static_mesh_shader_program.get())
{
unskinned_model_view_projection_var->update(model_view_projection);
m_static_mesh_model_view_projection_var->update(model_view_projection);
}
else if (active_shader_program == skinned_shader_program.get())
else if (active_shader_program == m_skeletal_mesh_shader_program.get())
{
skinned_model_view_projection_var->update(model_view_projection);
skinned_matrix_palette_var->update(operation->matrix_palette);
m_skeletal_mesh_model_view_projection_var->update(model_view_projection);
m_skeletal_mesh_matrix_palette_var->update(operation->matrix_palette);
}
// Draw geometry
@ -303,6 +314,40 @@ void shadow_map_pass::render_csm(scene::directional_light& light, render::contex
}
}
void cascaded_shadow_map_pass::rebuild_static_mesh_shader_program()
{
m_static_mesh_shader_program = m_static_mesh_shader_template->build(m_shader_template_definitions);
if (!m_static_mesh_shader_program->linked())
{
debug::log::error("Failed to build cascaded shadow map shader program for static meshes: {}", m_static_mesh_shader_program->info());
debug::log::warning("{}", m_static_mesh_shader_template->configure(gl::shader_stage::vertex));
m_static_mesh_model_view_projection_var = nullptr;
}
else
{
m_static_mesh_model_view_projection_var = m_static_mesh_shader_program->variable("model_view_projection");
}
}
void cascaded_shadow_map_pass::rebuild_skeletal_mesh_shader_program()
{
m_skeletal_mesh_shader_program = m_skeletal_mesh_shader_template->build(m_shader_template_definitions);
if (!m_skeletal_mesh_shader_program->linked())
{
debug::log::error("Failed to build cascaded shadow map shader program for skeletal meshes: {}", m_skeletal_mesh_shader_program->info());
debug::log::warning("{}", m_skeletal_mesh_shader_template->configure(gl::shader_stage::vertex));
m_skeletal_mesh_model_view_projection_var = nullptr;
m_skeletal_mesh_matrix_palette_var = nullptr;
}
else
{
m_skeletal_mesh_model_view_projection_var = m_skeletal_mesh_shader_program->variable("model_view_projection");
m_skeletal_mesh_matrix_palette_var = m_skeletal_mesh_shader_program->variable("matrix_palette");
}
}
bool operation_compare(const render::operation* a, const render::operation* b)
{
const bool skinned_a = !a->matrix_palette.empty();

+ 105
- 0
src/engine/render/passes/cascaded-shadow-map-pass.hpp View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2023 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_RENDER_CASCADED_SHADOW_MAP_PASS_HPP
#define ANTKEEPER_RENDER_CASCADED_SHADOW_MAP_PASS_HPP
#include <engine/render/pass.hpp>
#include <engine/math/vector.hpp>
#include <engine/scene/directional-light.hpp>
#include <engine/gl/shader-program.hpp>
#include <engine/gl/shader-variable.hpp>
#include <memory>
#include <string>
#include <unordered_map>
class resource_manager;
namespace render {
/**
* Renders cascaded shadow maps for directional lights.
*/
class cascaded_shadow_map_pass: public pass
{
public:
/**
* Constructs a shadow map pass.
*
* @param rasterizer Rasterizer.
* @param framebuffer Shadow map framebuffer.
* @param resource_manage Resource manager.
*/
cascaded_shadow_map_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager);
/**
* Renders shadow maps for a single camera.
*
* @param ctx Render context.
* @param queue Render queue.
*/
void render(render::context& ctx) override;
/**
* Sets the maximum bone count for shadow-casting skeletal meshes.
*
* @param bone_count Max bone count.
*
* @warning Triggers rebuilding of skeletal mesh shader.
*/
void set_max_bone_count(std::size_t bone_count);
/// Returns the maximum bone count for shadow-casting skeletal meshes.
[[nodiscard]] inline constexpr std::size_t get_max_bone_count() const noexcept
{
return m_max_bone_count;
}
private:
/**
* Renders an atlas of cascaded shadow maps for a single directional light.
*
* @param light Shadow-casting directional light.
* @param ctx Render context.
*/
void render_atlas(scene::directional_light& light, render::context& ctx);
/// Rebuilds the shader program for static meshes.
void rebuild_static_mesh_shader_program();
/// Rebuilds the shader program for skeletal meshes.
void rebuild_skeletal_mesh_shader_program();
std::size_t m_max_bone_count{64};
std::unordered_map<std::string, std::string> m_shader_template_definitions;
std::shared_ptr<gl::shader_template> m_static_mesh_shader_template;
std::unique_ptr<gl::shader_program> m_static_mesh_shader_program;
const gl::shader_variable* m_static_mesh_model_view_projection_var;
std::shared_ptr<gl::shader_template> m_skeletal_mesh_shader_template;
std::unique_ptr<gl::shader_program> m_skeletal_mesh_shader_program;
const gl::shader_variable* m_skeletal_mesh_model_view_projection_var;
const gl::shader_variable* m_skeletal_mesh_matrix_palette_var;
};
} // namespace render
#endif // ANTKEEPER_RENDER_CASCADED_SHADOW_MAP_PASS_HPP

+ 0
- 77
src/engine/render/passes/shadow-map-pass.hpp View File

@ -1,77 +0,0 @@
/*
* Copyright (C) 2023 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_RENDER_SHADOW_MAP_PASS_HPP
#define ANTKEEPER_RENDER_SHADOW_MAP_PASS_HPP
#include <engine/render/pass.hpp>
#include <engine/math/vector.hpp>
#include <engine/scene/directional-light.hpp>
#include <engine/gl/shader-program.hpp>
#include <engine/gl/shader-variable.hpp>
#include <memory>
class resource_manager;
namespace render {
/**
* Renders shadow maps.
*/
class shadow_map_pass: public pass
{
public:
/**
* Constructs a shadow map pass.
*
* @param rasterizer Rasterizer.
* @param framebuffer Shadow map framebuffer.
* @param resource_manage Resource manager.
*/
shadow_map_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager);
/**
* Renders shadow maps for a single camera.
*
* @param ctx Render context.
* @param queue Render queue.
*/
void render(render::context& ctx) override;
private:
/**
* Renders cascaded shadow maps for a single directional light.
*
* @param light Shadow-casting directional light.
* @param ctx Render context.
* @param queue Render queue.
*/
void render_csm(scene::directional_light& light, render::context& ctx);
std::unique_ptr<gl::shader_program> unskinned_shader_program;
const gl::shader_variable* unskinned_model_view_projection_var;
std::unique_ptr<gl::shader_program> skinned_shader_program;
const gl::shader_variable* skinned_model_view_projection_var;
const gl::shader_variable* skinned_matrix_palette_var;
};
} // namespace render
#endif // ANTKEEPER_RENDER_SHADOW_MAP_PASS_HPP

+ 0
- 3
src/engine/render/passes/sky-pass.cpp View File

@ -255,9 +255,6 @@ void sky_pass::render(render::context& ctx)
math::fvec3 moon_illuminance = moon_illuminance_tween.interpolate(ctx.alpha) * camera_exposure;
float moon_angular_radius = moon_angular_radius_tween.interpolate(ctx.alpha) * magnification;
float sun_y = color::aces::ap1<float>.luminance(sun_transmitted_illuminance);
float moon_y = color::aces::ap1<float>.luminance(moon_transmitted_illuminance);
// if (math::max(sun_illuminance) > math::max(moon_illuminance))
// {
dominant_light_direction = sun_direction;

+ 30
- 3
src/engine/scene/directional-light.cpp View File

@ -27,6 +27,7 @@ directional_light::directional_light():
m_shadow_scale_bias_matrices(m_shadow_cascade_count)
{
set_shadow_bias(m_shadow_bias);
update_shadow_cascade_distances();
}
void directional_light::set_direction(const math::fvec3& direction)
@ -52,21 +53,24 @@ void directional_light::set_shadow_bias(float bias) noexcept
void directional_light::set_shadow_cascade_count(unsigned int count) noexcept
{
m_shadow_cascade_count = count;
m_shadow_cascade_count = std::min(std::max(count, 1u), 4u);
m_shadow_cascade_distances.resize(m_shadow_cascade_count);
m_shadow_cascade_matrices.resize(m_shadow_cascade_count);
m_shadow_scale_bias_matrices.resize(m_shadow_cascade_count);
update_shadow_scale_bias_matrices();
update_shadow_cascade_distances();
}
void directional_light::set_shadow_cascade_coverage(float factor) noexcept
void directional_light::set_shadow_distance(float distance) noexcept
{
m_shadow_cascade_coverage = factor;
m_shadow_distance = distance;
update_shadow_cascade_distances();
}
void directional_light::set_shadow_cascade_distribution(float weight) noexcept
{
m_shadow_cascade_distribution = weight;
update_shadow_cascade_distances();
}
void directional_light::transformed()
@ -102,4 +106,27 @@ void directional_light::update_shadow_scale_bias_matrices()
}
}
void directional_light::update_shadow_cascade_distances()
{
if (!m_shadow_cascade_count)
{
return;
}
m_shadow_cascade_distances[m_shadow_cascade_count - 1] = m_shadow_distance;
for (unsigned int i = 0; i < m_shadow_cascade_count - 1; ++i)
{
const auto weight = static_cast<float>(i + 1) / static_cast<float>(m_shadow_cascade_count);
// Calculate linear and logarithmic distribution distances
const auto linear_distance = m_shadow_distance * weight;
// const auto log_distance = math::log_lerp(0.0f, m_shadow_distance, weight);
// Interpolate between linear and logarithmic distribution distances
// cascade_distances[i] = math::lerp(linear_distance, log_distance, light.get_shadow_cascade_distribution());
m_shadow_cascade_distances[i] = linear_distance;
}
}
} // namespace scene

+ 17
- 14
src/engine/scene/directional-light.hpp View File

@ -129,16 +129,18 @@ public:
/**
* Sets the number of shadow cascades.
*
* @param count Number of shadow cascades.
* @param count Number of shadow cascades, on `[1, 4]`.
*
* @note The number of shadow cascades will be clamped to `[1, 4]`.
*/
void set_shadow_cascade_count(unsigned int count) noexcept;
/**
* Sets the shadow cascade coverage factor.
* Sets the distance from the camera up to which shadows are visible.
*
* @param factor Percentage of the view frustum clipping range covered by shadow cascades. A value of `1.0` results in full coverage of the view frustum clipping range, `0.5` results in coverage of half of the clipping range, etc.
* @param distance Shadow distance.
*/
void set_shadow_cascade_coverage(float factor) noexcept;
void set_shadow_distance(float distance) noexcept;
/**
* Sets the shadow cascade distribution.
@ -148,37 +150,37 @@ public:
void set_shadow_cascade_distribution(float weight) noexcept;
/// Returns `true` if the light casts shadows, `false` otherwise.
[[nodiscard]] inline bool is_shadow_caster() const noexcept
[[nodiscard]] inline constexpr bool is_shadow_caster() const noexcept
{
return m_shadow_caster;
}
/// Returns the shadow map framebuffer, of `nullptr` if no shadow map framebuffer is set.
[[nodiscard]] inline const std::shared_ptr<gl::framebuffer>& get_shadow_framebuffer() const noexcept
[[nodiscard]] inline constexpr const std::shared_ptr<gl::framebuffer>& get_shadow_framebuffer() const noexcept
{
return m_shadow_framebuffer;
}
/// Returns the shadow bias factor.
[[nodiscard]] inline float get_shadow_bias() const noexcept
[[nodiscard]] inline constexpr float get_shadow_bias() const noexcept
{
return m_shadow_bias;
}
/// Returns the number of shadow cascades.
[[nodiscard]] inline unsigned int get_shadow_cascade_count() const noexcept
[[nodiscard]] inline constexpr unsigned int get_shadow_cascade_count() const noexcept
{
return m_shadow_cascade_count;
}
/// Returns the shadow cascade coverage factor.
[[nodiscard]] inline float get_shadow_cascade_coverage() const noexcept
/// Returns the distance from the camera up to which shadows are visible.
[[nodiscard]] inline constexpr float get_shadow_distance() const noexcept
{
return m_shadow_cascade_coverage;
return m_shadow_distance;
}
/// Returns the shadow cascade distribution weight.
[[nodiscard]] inline float get_shadow_cascade_distribution() const noexcept
[[nodiscard]] inline constexpr float get_shadow_cascade_distribution() const noexcept
{
return m_shadow_cascade_distribution;
}
@ -220,6 +222,7 @@ private:
void color_updated();
void illuminance_updated();
void update_shadow_scale_bias_matrices();
void update_shadow_cascade_distances();
math::fvec3 m_direction{0.0f, 0.0f, -1.0f};
math::fvec3 m_color{1.0f, 1.0f, 1.0f};
@ -228,9 +231,9 @@ private:
bool m_shadow_caster{false};
std::shared_ptr<gl::framebuffer> m_shadow_framebuffer{nullptr};
float m_shadow_bias{0.001f};
float m_shadow_bias{0.005f};
unsigned int m_shadow_cascade_count{4};
float m_shadow_cascade_coverage{1.0f};
float m_shadow_distance{1000.0f};
float m_shadow_cascade_distribution{0.8f};
std::vector<float> m_shadow_cascade_distances;
std::vector<math::fmat4> m_shadow_cascade_matrices;

+ 13
- 0
src/engine/scene/light.cpp View File

@ -18,9 +18,22 @@
*/
#include <engine/scene/light.hpp>
#include <engine/config.hpp>
#include <engine/color/cct.hpp>
namespace scene {
void light::set_color(const math::fvec3& color)
{
m_color = color;
color_updated();
}
void light::set_color_temperature(float temperature)
{
set_color(config::scene_linear_color_space<float>.from_xyz * color::cct_to_xyz(temperature));
}
void light::transformed()
{
m_bounds = {get_translation(), get_translation()};

+ 27
- 0
src/engine/scene/light.hpp View File

@ -38,10 +38,37 @@ public:
{
return m_bounds;
}
/**
* Sets the color of the light.
*
* @param color Scene-linear RGB color, on `[0, 1]`.
*/
void set_color(const math::fvec3& color);
/**
* Sets the color of the light from a color temperature.
*
* @param temperature Color temperature, in Kelvin.
*/
void set_color_temperature(float temperature);
/// Returns the scene-linear RGB color of the light.
[[nodiscard]] inline constexpr const math::fvec3& get_color() const noexcept
{
return m_color;
}
protected:
/// Called each time the light color is modified.
inline virtual void color_updated() {};
private:
void transformed() override;
aabb_type m_bounds{};
math::fvec3 m_color{1.0f, 1.0f, 1.0f};
};
} // namespace scene

+ 2
- 2
src/engine/scene/point-light.cpp View File

@ -23,12 +23,12 @@ namespace scene {
void point_light::color_updated()
{
m_colored_luminous_flux = m_color * m_luminous_flux;
m_colored_luminous_flux = get_color() * m_luminous_flux;
}
void point_light::luminous_flux_updated()
{
m_colored_luminous_flux = m_color * m_luminous_flux;
m_colored_luminous_flux = get_color() * m_luminous_flux;
}
} // namespace scene

+ 5
- 23
src/engine/scene/point-light.hpp View File

@ -37,17 +37,6 @@ public:
return light_type::point;
}
/**
* Sets the color of the light.
*
* @param color Light color.
*/
inline void set_color(const math::fvec3& color) noexcept
{
m_color = color;
color_updated();
}
/**
* Sets the luminous flux of the light.
*
@ -59,29 +48,22 @@ public:
luminous_flux_updated();
}
/// Returns the color of the light.
[[nodiscard]] inline const math::fvec3& get_color() const noexcept
{
return m_color;
}
/// Returns the luminous flux of the light.
[[nodiscard]] inline float get_luminous_flux() const noexcept
[[nodiscard]] inline constexpr float get_luminous_flux() const noexcept
{
return m_luminous_flux;
}
/// Returns the color-modulated luminous flux of light.
[[nodiscard]] inline const math::fvec3& get_colored_luminous_flux() const noexcept
/// Returns the color-modulated luminous flux of the light.
[[nodiscard]] inline constexpr const math::fvec3& get_colored_luminous_flux() const noexcept
{
return m_colored_luminous_flux;
}
private:
void color_updated();
void luminous_flux_updated();
void color_updated() override;
void luminous_flux_updated() noexcept;
math::fvec3 m_color{1.0f, 1.0f, 1.0f};
float m_luminous_flux{};
math::fvec3 m_colored_luminous_flux{};
};

+ 19
- 14
src/engine/scene/rectangle-light.cpp View File

@ -27,6 +27,11 @@ rectangle_light::rectangle_light()
transformed();
}
void rectangle_light::set_size(const math::fvec2& size)
{
set_scale({size.x(), size.y(), 1.0f});
}
void rectangle_light::transformed()
{
const auto& transform = get_transform();
@ -42,39 +47,39 @@ void rectangle_light::transformed()
m_corners[3] = transform * math::fvec3{ 0.5f, -0.5f, 0.0f};
// Update area
m_area = get_scale().x() * get_scale().z();
m_area = get_scale().x() * get_scale().y();
area_updated();
}
void rectangle_light::area_updated()
void rectangle_light::color_updated()
{
// Calculate luminance from luminous flux
m_luminance = m_luminous_flux / (m_area * math::pi<float>);
m_colored_luminance = m_color * m_luminance;
m_colored_luminous_flux = get_color() * m_luminous_flux;
m_colored_luminance = get_color() * m_luminance;
}
void rectangle_light::color_updated()
void rectangle_light::area_updated() noexcept
{
m_colored_luminous_flux = m_color * m_luminous_flux;
m_colored_luminance = m_color * m_luminance;
// Calculate luminance from luminous flux
m_luminance = m_luminous_flux / (m_area * math::pi<float>);
m_colored_luminance = get_color() * m_luminance;
}
void rectangle_light::luminous_flux_updated()
void rectangle_light::luminous_flux_updated() noexcept
{
m_colored_luminous_flux = m_color * m_luminous_flux;
m_colored_luminous_flux = get_color() * m_luminous_flux;
// Calculate luminance from luminous flux
m_luminance = m_luminous_flux / (m_area * math::pi<float>);
m_colored_luminance = m_color * m_luminance;
m_colored_luminance = get_color() * m_luminance;
}
void rectangle_light::luminance_updated()
void rectangle_light::luminance_updated() noexcept
{
m_colored_luminance = m_color * m_luminance;
m_colored_luminance = get_color() * m_luminance;
// Calculate luminous flux from luminance
m_luminous_flux = m_luminance * (m_area * math::pi<float>);
m_colored_luminous_flux = m_color * m_luminous_flux;
m_colored_luminous_flux = get_color() * m_luminous_flux;
}
} // namespace scene

+ 18
- 22
src/engine/scene/rectangle-light.hpp View File

@ -31,6 +31,7 @@ namespace scene {
class rectangle_light: public light
{
public:
/// Constructs a rectangular area light.
rectangle_light();
/// Returns light_type::rectangle.
@ -40,15 +41,11 @@ public:
}
/**
* Sets the color of the light.
* Sets the size of the light.
*
* @param color Light color.
* @param size Dimensions of the light.
*/
inline void set_color(const math::fvec3& color) noexcept
{
m_color = color;
color_updated();
}
void set_size(const math::fvec2& size);
/**
* Sets the luminous flux of the light.
@ -72,56 +69,55 @@ public:
luminance_updated();
}
/// Returns the color of the light.
[[nodiscard]] inline const math::fvec3& get_color() const noexcept
/// Returns the dimensions of the light.
[[nodiscard]] inline constexpr math::fvec2 get_size() const noexcept
{
return m_color;
return math::fvec2(get_scale());
}
/// Returns the luminous flux of the light.
[[nodiscard]] inline float get_luminous_flux() const noexcept
[[nodiscard]] inline constexpr float get_luminous_flux() const noexcept
{
return m_luminous_flux;
}
/// Returns the color-modulated luminous flux of the light.
[[nodiscard]] inline const math::fvec3& get_colored_luminous_flux() const noexcept
[[nodiscard]] inline constexpr const math::fvec3& get_colored_luminous_flux() const noexcept
{
return m_colored_luminous_flux;
}
/// Returns the luminance of the light.
[[nodiscard]] inline float get_luminance() const noexcept
[[nodiscard]] inline constexpr float get_luminance() const noexcept
{
return m_luminance;
}
/// Returns the color-modulated luminance of the light.
[[nodiscard]] inline const math::fvec3& get_colored_luminance() const noexcept
[[nodiscard]] inline constexpr const math::fvec3& get_colored_luminance() const noexcept
{
return m_colored_luminance;
}
/// Returns the positions of the light corners.
[[nodiscard]] inline std::span<const math::fvec3, 4> get_corners() const noexcept
/// Returns the world-space positions of the light corners.
[[nodiscard]] inline constexpr std::span<const math::fvec3, 4> get_corners() const noexcept
{
return m_corners;
}
private:
void transformed() override;
void area_updated();
void color_updated();
void luminous_flux_updated();
void luminance_updated();
void color_updated() override;
void area_updated() noexcept;
void luminous_flux_updated() noexcept;
void luminance_updated() noexcept;
float m_area{1.0f};
math::fvec3 m_corners[4];
math::fvec3 m_color{1.0f, 1.0f, 1.0f};
float m_luminous_flux{};
math::fvec3 m_colored_luminous_flux{};
float m_luminance{};
math::fvec3 m_colored_luminance;
math::fvec3 m_colored_luminance{};
};
} // namespace scene

+ 4
- 10
src/game/game.cpp View File

@ -85,7 +85,7 @@
#include <engine/render/passes/material-pass.hpp>
#include <engine/render/passes/outline-pass.hpp>
#include <engine/render/passes/resample-pass.hpp>
#include <engine/render/passes/shadow-map-pass.hpp>
#include <engine/render/passes/cascaded-shadow-map-pass.hpp>
#include <engine/render/passes/sky-pass.hpp>
#include <engine/render/renderer.hpp>
#include <engine/render/vertex-attribute.hpp>
@ -735,11 +735,7 @@ void game::setup_rendering()
// Setup surface compositor
{
surface_shadow_map_clear_pass = std::make_unique<render::clear_pass>(window->get_rasterizer(), shadow_map_framebuffer.get());
surface_shadow_map_clear_pass->set_cleared_buffers(false, true, false);
surface_shadow_map_clear_pass->set_clear_depth(0.0f);
surface_shadow_map_pass = std::make_unique<render::shadow_map_pass>(window->get_rasterizer(), resource_manager.get());
surface_cascaded_shadow_map_pass = std::make_unique<render::cascaded_shadow_map_pass>(window->get_rasterizer(), resource_manager.get());
surface_clear_pass = std::make_unique<render::clear_pass>(window->get_rasterizer(), hdr_framebuffer.get());
surface_clear_pass->set_clear_color({0.0f, 0.0f, 0.0f, 1.0f});
@ -758,8 +754,7 @@ void game::setup_rendering()
surface_outline_pass->set_outline_color(math::fvec4{1.0f, 1.0f, 1.0f, 1.0f});
surface_compositor = std::make_unique<render::compositor>();
surface_compositor->add_pass(surface_shadow_map_clear_pass.get());
surface_compositor->add_pass(surface_shadow_map_pass.get());
surface_compositor->add_pass(surface_cascaded_shadow_map_pass.get());
surface_compositor->add_pass(surface_clear_pass.get());
surface_compositor->add_pass(sky_pass.get());
surface_compositor->add_pass(surface_material_pass.get());
@ -812,7 +807,7 @@ void game::setup_scenes()
// Allocate and init surface camera
surface_camera = std::make_shared<scene::camera>();
surface_camera->set_perspective(math::radians<float>(45.0f), viewport_aspect_ratio, 0.1f, 1000.0f);
surface_camera->set_perspective(math::radians<float>(45.0f), viewport_aspect_ratio, 0.5f, 1000.0f);
surface_camera->set_compositor(surface_compositor.get());
surface_camera->set_composite_index(0);
@ -1091,7 +1086,6 @@ void game::setup_systems()
// Setup blackbody system
blackbody_system = std::make_unique<::blackbody_system>(*entity_registry);
blackbody_system->set_illuminant(color::illuminant::deg2::d55<double>);
// Setup atmosphere system
atmosphere_system = std::make_unique<::atmosphere_system>(*entity_registry);

+ 2
- 3
src/game/game.hpp View File

@ -90,7 +90,7 @@ namespace render
class material_pass;
class renderer;
class outline_pass;
class shadow_map_pass;
class cascaded_shadow_map_pass;
class simple_render_pass;
class sky_pass;
}
@ -333,8 +333,7 @@ public:
std::unique_ptr<render::clear_pass> underground_clear_pass;
std::unique_ptr<render::material_pass> underground_material_pass;
std::unique_ptr<render::compositor> underground_compositor;
std::unique_ptr<render::clear_pass> surface_shadow_map_clear_pass;
std::unique_ptr<render::shadow_map_pass> surface_shadow_map_pass;
std::unique_ptr<render::cascaded_shadow_map_pass> surface_cascaded_shadow_map_pass;
std::unique_ptr<render::clear_pass> surface_clear_pass;
std::unique_ptr<render::sky_pass> sky_pass;
std::unique_ptr<render::material_pass> surface_material_pass;

+ 7
- 67
src/game/states/experiments/treadmill-experiment-state.cpp View File

@ -114,74 +114,13 @@ treadmill_experiment_state::treadmill_experiment_state(::game& ctx):
std::shared_ptr<render::model> worker_model = ant_morphogenesis(*worker_phenome);
debug::log::trace("Generated worker model");
// Create directional light
// ctx.underground_directional_light = std::make_unique<scene::directional_light>();
// ctx.underground_directional_light->set_color({1.0f, 1.0f, 1.0f});
// ctx.underground_directional_light->set_illuminance(2.0f);
// ctx.underground_directional_light->set_direction(math::normalize(math::fvec3{0, -1, 0}));
// ctx.underground_directional_light->set_shadow_caster(true);
// ctx.underground_directional_light->set_shadow_framebuffer(ctx.shadow_map_framebuffer);
// ctx.underground_directional_light->set_shadow_bias(0.005f);
// ctx.underground_directional_light->set_shadow_cascade_count(4);
// ctx.underground_directional_light->set_shadow_cascade_coverage(0.15f);
// ctx.underground_directional_light->set_shadow_cascade_distribution(0.8f);
// ctx.underground_scene->add_object(*ctx.underground_directional_light);
// ctx.underground_clear_pass->set_clear_color({0.214f, 0.214f, 0.214f, 1.0f});
// ctx.underground_clear_pass->set_clear_color({});
// light_probe = std::make_shared<scene::light_probe>();
// light_probe->set_luminance_texture(ctx.resource_manager->load<gl::texture_cube>("grey-furnace.tex"));
// ctx.underground_scene->add_object(*light_probe);
//const float color_temperature = 5000.0f;
//const math::fvec3 light_color = color::aces::ap1<float>.from_xyz * color::cat::matrix(color::illuminant::deg2::d50<float>, color::aces::white_point<float>) * color::cct::to_xyz(color_temperature);
// const math::fvec3 light_color{1.0f, 1.0f, 1.0f};
// Create rectangle light
// ctx.underground_rectangle_light = std::make_unique<scene::rectangle_light>();
// ctx.underground_rectangle_light->set_color(light_color);
// ctx.underground_rectangle_light->set_luminous_flux(1500.0f);
// ctx.underground_rectangle_light->set_translation({0.0f, 10.0f, 0.0f});
// ctx.underground_rectangle_light->set_rotation(math::fquat::rotate_x(math::radians(90.0f)));
// ctx.underground_rectangle_light->set_scale(7.0f);
// ctx.underground_scene->add_object(*ctx.underground_rectangle_light);
// Create light rectangle
// auto light_rectangle_model = ctx.resource_manager->load<render::model>("light-rectangle.mdl");
// auto light_rectangle_material = std::make_shared<render::material>(*light_rectangle_model->get_groups().front().material);
// light_rectangle_emissive = std::static_pointer_cast<render::matvar_fvec3>(light_rectangle_material->get_variable("emissive"));
// light_rectangle_emissive->set(ctx.underground_rectangle_light->get_colored_luminance());
// auto light_rectangle_static_mesh = std::make_shared<scene::static_mesh>(light_rectangle_model);
// light_rectangle_static_mesh->set_material(0, light_rectangle_material);
// auto light_rectangle_eid = ctx.entity_registry->create();
// ctx.entity_registry->emplace<scene_component>(light_rectangle_eid, std::move(light_rectangle_static_mesh), std::uint8_t{1});
// ctx.entity_registry->patch<scene_component>
// (
// light_rectangle_eid,
// [&](auto& component)
// {
// component.object->set_transform(ctx.underground_rectangle_light->get_transform());
// }
// );
// Create nest exterior
// {
// scene_component nest_exterior_scene_component;
// nest_exterior_scene_component.object = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("round-petri-dish-nest-100mm-exterior.mdl"));
// nest_exterior_scene_component.layer_mask = 1;
// auto nest_exterior_eid = ctx.entity_registry->create();
// ctx.entity_registry->emplace<scene_component>(nest_exterior_eid, std::move(nest_exterior_scene_component));
// }
// Create nest exterior
{
scene_component nest_exterior_scene_component;
nest_exterior_scene_component.object = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("sphere-nest-100mm-exterior.mdl"));
nest_exterior_scene_component.object = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("cube-nest-200mm-exterior.mdl"));
nest_exterior_scene_component.layer_mask = 1;
auto nest_exterior_mesh = ctx.resource_manager->load<geom::brep_mesh>("sphere-nest-100mm-exterior.msh");
auto nest_exterior_mesh = ctx.resource_manager->load<geom::brep_mesh>("cube-nest-200mm-exterior.msh");
auto nest_exterior_rigid_body = std::make_unique<physics::rigid_body>();
nest_exterior_rigid_body->set_mass(0.0f);
@ -195,11 +134,11 @@ treadmill_experiment_state::treadmill_experiment_state(::game& ctx):
// Create nest interior
{
scene_component nest_interior_scene_component;
nest_interior_scene_component.object = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("sphere-nest-100mm-interior.mdl"));
nest_interior_scene_component.object = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("soil-nest.mdl"));
nest_interior_scene_component.object->set_layer_mask(0b10);
nest_interior_scene_component.layer_mask = 1;
auto nest_interior_mesh = ctx.resource_manager->load<geom::brep_mesh>("sphere-nest-100mm-interior.msh");
auto nest_interior_mesh = ctx.resource_manager->load<geom::brep_mesh>("soil-nest.msh");
auto nest_interior_rigid_body = std::make_unique<physics::rigid_body>();
nest_interior_rigid_body->set_mass(0.0f);
@ -215,10 +154,11 @@ treadmill_experiment_state::treadmill_experiment_state(::game& ctx):
// Create rectangle light
{
area_light = std::make_unique<scene::rectangle_light>();
area_light->set_luminous_flux(5000000.0f);
area_light->set_luminous_flux(12.57f * 100.0f);
area_light->set_color_temperature(20000.0f);
area_light->set_translation({0.0f, 0.0f, 0.0f});
area_light->set_rotation(math::fquat::rotate_x(math::radians(90.0f)));
area_light->set_scale(5.0f);
area_light->set_size({1.0f, 2.0f});
area_light->set_layer_mask(0b10);
ctx.surface_scene->add_object(*area_light);

+ 0
- 2
src/game/states/nest-view-state.cpp View File

@ -132,8 +132,6 @@ nest_view_state::nest_view_state(::game& ctx):
light_probe->set_luminance_texture(ctx.resource_manager->load<gl::texture_cube>("grey-furnace.tex"));
ctx.underground_scene->add_object(*light_probe);
//const float color_temperature = 5000.0f;
//const math::fvec3 light_color = color::aces::ap1<float>.from_xyz * color::cat::matrix(color::illuminant::deg2::d50<float>, color::aces::white_point<float>) * color::cct::to_xyz(color_temperature);
const math::fvec3 light_color{1.0f, 1.0f, 1.0f};
// Create rectangle light

+ 5
- 12
src/game/systems/blackbody-system.cpp View File

@ -18,10 +18,11 @@
*/
#include "game/systems/blackbody-system.hpp"
#include <engine/color/color.hpp>
#include <engine/physics/light/blackbody.hpp>
#include <engine/physics/light/photometry.hpp>
#include <engine/math/quadrature.hpp>
#include <engine/config.hpp>
#include <engine/color/xyz.hpp>
#include <numeric>
blackbody_system::blackbody_system(entity::registry& registry):
@ -31,9 +32,6 @@ blackbody_system::blackbody_system(entity::registry& registry):
m_visible_wavelengths_nm.resize(780 - 280);
std::iota(m_visible_wavelengths_nm.begin(), m_visible_wavelengths_nm.end(), 280);
// Set illuminant
set_illuminant(color::illuminant::deg2::d50<double>);
registry.on_construct<::blackbody_component>().connect<&blackbody_system::on_blackbody_construct>(this);
registry.on_update<::blackbody_component>().connect<&blackbody_system::on_blackbody_update>(this);
}
@ -47,12 +45,6 @@ blackbody_system::~blackbody_system()
void blackbody_system::update(float t, float dt)
{}
void blackbody_system::set_illuminant(const math::vec2<double>& illuminant)
{
m_illuminant = illuminant;
m_xyz_to_rgb = color::aces::ap1<double>.from_xyz * color::cat::matrix(m_illuminant, color::aces::white_point<double>);
}
void blackbody_system::update_blackbody(entity::id entity_id)
{
// Get blackbody component
@ -71,10 +63,11 @@ void blackbody_system::update_blackbody(entity::id entity_id)
const double spectral_luminance = spectral_radiance * 1e-9 * physics::light::max_luminous_efficacy<double>;
// Calculate the XYZ color of the wavelength using CIE color matching functions then transform to RGB
const math::dvec3 rgb_color = m_xyz_to_rgb * color::xyz::match(wavelength_nm);
const auto color_xyz = color::xyz_match(wavelength_nm);
const auto color_rgb = config::scene_linear_color_space<double>.from_xyz * color_xyz;
// Scale RGB color by spectral luminance
return rgb_color * spectral_luminance;
return color_rgb * spectral_luminance;
};
// Integrate the blackbody RGB spectral luminance over wavelengths in the visible spectrum

+ 0
- 9
src/game/systems/blackbody-system.hpp View File

@ -39,13 +39,6 @@ public:
void update(float t, float dt) override;
/**
* Sets the blackbody illuminant.
*
* @param illuminant CIE chromaticity coordinates of an illuminant.
*/
void set_illuminant(const math::vec2<double>& illuminant);
private:
void update_blackbody(entity::id entity_id);
@ -53,8 +46,6 @@ private:
void on_blackbody_update(entity::registry& registry, entity::id entity_id);
std::vector<double> m_visible_wavelengths_nm;
math::vec2<double> m_illuminant;
math::mat3<double> m_xyz_to_rgb;
};

+ 10
- 11
src/game/world.cpp View File

@ -55,7 +55,6 @@
#include <engine/render/material-flags.hpp>
#include <engine/render/material.hpp>
#include <engine/render/model.hpp>
#include <engine/render/passes/shadow-map-pass.hpp>
#include <engine/render/passes/sky-pass.hpp>
#include <engine/render/vertex-attribute.hpp>
#include <engine/utility/image.hpp>
@ -265,13 +264,13 @@ void create_stars(::game& ctx)
math::fvec3 position = physics::orbit::frame::bci::cartesian(math::fvec3{1.0f, dec, ra});
// Convert color index to color temperature
float cct = color::index::bv_to_cct(bv);
float cct = color::bv_to_cct(bv);
// Calculate XYZ color from color temperature
math::fvec3 color_xyz = color::cct::to_xyz(cct);
math::fvec3 color_xyz = color::cct_to_xyz(cct);
// Transform XYZ color to ACEScg colorspace
math::fvec3 color_acescg = color::aces::ap1<float>.from_xyz * color_xyz;
// Transform XYZ color to RGB
math::fvec3 color_rgb = config::scene_linear_color_space<float>.from_xyz * color_xyz;
// Convert apparent magnitude to brightness factor relative to a 0th magnitude star
float brightness = physics::light::vmag::to_brightness(vmag);
@ -280,13 +279,13 @@ void create_stars(::game& ctx)
*(star_vertex++) = position.x();
*(star_vertex++) = position.y();
*(star_vertex++) = position.z();
*(star_vertex++) = color_acescg.x();
*(star_vertex++) = color_acescg.y();
*(star_vertex++) = color_acescg.z();
*(star_vertex++) = color_rgb.x();
*(star_vertex++) = color_rgb.y();
*(star_vertex++) = color_rgb.z();
*(star_vertex++) = brightness;
// Calculate spectral illuminance
math::dvec3 illuminance = math::dvec3(color_acescg * physics::light::vmag::to_illuminance(vmag));
math::dvec3 illuminance = math::dvec3(color_rgb * physics::light::vmag::to_illuminance(vmag));
// Add spectral illuminance to total starlight illuminance
starlight_illuminance += illuminance;
@ -362,9 +361,9 @@ void create_sun(::game& ctx)
ctx.sun_light = std::make_unique<scene::directional_light>();
ctx.sun_light->set_shadow_caster(true);
ctx.sun_light->set_shadow_framebuffer(ctx.shadow_map_framebuffer);
ctx.sun_light->set_shadow_bias(0.0025f);
ctx.sun_light->set_shadow_bias(0.005f);
ctx.sun_light->set_shadow_distance(50.0f);
ctx.sun_light->set_shadow_cascade_count(4);
ctx.sun_light->set_shadow_cascade_coverage(0.05f);
ctx.sun_light->set_shadow_cascade_distribution(0.8f);
// Add sun light scene objects to surface scene

Loading…
Cancel
Save