gdk-graphics 0b051eb9b5c1eaa0658babaa4463dd7a80aa9d2c
Loading...
Searching...
No Matches
volumetric_lighting.h
1// © Joseph Cameron - All Rights Reserved
2
3#ifndef GDK_GFX_VOLUMETRIC_LIGHTING_H
4#define GDK_GFX_VOLUMETRIC_LIGHTING_H
5
6#include <gdk/color.h>
7#include <gdk/graphics_constraints.h>
8#include <gdk/texture_data.h>
9#include <jfc/cube_array.h>
10
11#include <algorithm>
12#include <array>
13
14namespace gdk {
17 template<size_t size_param>
18 class volumetric_lighting final {
19 public:
20 static constexpr size_t size = size_param;
21 static constexpr size_t size_1d = size * size * size;
22 static constexpr size_t size_2d = std::sqrt(size_1d);
23
24 static_assert(is_power_of_two(size));
25 static_assert(is_power_of_two(size_1d));
26 static_assert(is_power_of_two(size_2d));
27
28 static constexpr size_t CHANNELS_PER_COLOR = 3;
29
30 using texture_data_type = std::array<gdk::texture_data::channel_type, size_1d * CHANNELS_PER_COLOR>;
31 using texture_data_view_pair = std::pair<gdk::texture_data::view, std::shared_ptr<texture_data_type>>;
32 using local_space_component_type = int;
33
34 private:
36
37 void add(const local_space_component_type aX, const local_space_component_type aY, const local_space_component_type aZ,
38 const gdk::color &aColor) {
39 if (aX < 0 || aX >= size) return;
40 if (aY < 0 || aY >= size) return;
41 if (aZ < 0 || aZ >= size) return;
42
43 auto &light = m_Data.at(aX, aY, aZ);
44 light += aColor;
45 light.clamp();
46 }
47
48 public:
49 // \brief applies a uniform light to the whole volume
50 void add_global(const gdk::color &aColor) {
51 for (size_t x(0); x < size_param; ++x)
52 for (size_t y(0); y < size_param; ++y)
53 for (size_t z(0); z < size_param; ++z)
54 add(x, y, z, aColor);
55 }
56
58 void add_point_light(graphics_intvector3_type aLightPosition, const float aSize, const gdk::color &aColor) {
59 const gdk::vector3<float> CENTRE(aSize/2.f);
60 const auto HALF(aSize/2.f);
61
62 aLightPosition.x -= HALF;
63 aLightPosition.y -= HALF;
64 aLightPosition.z -= HALF;
65
66 for (int x(0); x < aSize; ++x) for (int y(0); y < aSize; ++y) for (int z(0); z < aSize; ++z) {
67 float distanceFromCentre = CENTRE.distance(gdk::vector3<float>(x,y,z));
68 float normalizedHalfDistanceFromCentre = distanceFromCentre / HALF;
69 float intensity = (1.0f / std::sqrt(normalizedHalfDistanceFromCentre)) - 1.0f;
70 intensity = std::clamp(intensity, 0.0f, 1.0f);
71
72 auto color(aColor);
73 color.r *= intensity;
74 color.g *= intensity;
75 color.b *= intensity;
76
77 add(aLightPosition.x + x, aLightPosition.y + y, aLightPosition.z + z, color);
78 }
79 }
80
81 // \brief Writes the lighting data to a 2d texture, for use with shaders etc
82 texture_data_view_pair to_texture_data() const {
83 texture_data_type textureData;
84
85 size_t i(0);
86 for (size_t j(0); j < size_1d; ++j) {
87 textureData[i + 0] = m_Data.data()[j].r * 255; //Converting normalized floating-point light values
88 textureData[i + 1] = m_Data.data()[j].g * 255; //to unsigned char values
89 textureData[i + 2] = m_Data.data()[j].b * 255;
90 i += CHANNELS_PER_COLOR;
91 }
92
93 auto pTextureData = std::make_shared<texture_data_type>(std::move(textureData));
94
95 texture_data::view view;
96 view.width = size_2d;
97 view.height = size_2d;
98 view.format = texture::format::rgb;
99 view.data = &(pTextureData->front());
100
101 return { view, pTextureData };
102 }
103 };
104}
105
106#endif
107
@ rgb
a sequence of 3 channels, single byte colors: red, green, blue, ...
Definition texture.h:26
cubic volume of diffuse lighting data
Definition volumetric_lighting.h:18
void add_point_light(graphics_intvector3_type aLightPosition, const float aSize, const gdk::color &aColor)
add a pointlight to the light volume
Definition volumetric_lighting.h:58
3d array where its length width and height are equal
Definition cube_array.h:12
Represents a 4 channel color: {Red, Green, Blue, Alpha}. TODO: channel values should be limited to th...
Definition color.h:11
void clamp()
clamp each channel to the [0 - 1] range