Unravel Engine C++ Reference
Loading...
Searching...
No Matches
atmospheric_pass_perez.cpp
Go to the documentation of this file.
4#include <graphics/texture.h>
5
6namespace unravel
7{
8
9namespace
10{
11#ifndef ANONYMOUS
12#define ANONYMOUS anonymous
13#endif
14namespace ANONYMOUS
15{
16// Represents color. Color-space depends on context.
17// In the code below, used to represent color in XYZ, and RGB color-space
18typedef bx::Vec3 Color;
19
20// Performs piecewise linear interpolation of a Color parameter.
21class dynamic_value_controller
22{
23 using value_type = Color;
24 using key_map = std::map<float, value_type>;
25
26public:
27 dynamic_value_controller(const key_map& keymap) : key_map_(keymap)
28 {
29 }
30
31 value_type get_value(float time) const
32 {
33 auto itUpper = key_map_.upper_bound(time + 1e-6f);
34 auto itLower = itUpper;
35 --itLower;
36
37 if(itLower == key_map_.end())
38 {
39 return itUpper->second;
40 }
41
42 if(itUpper == key_map_.end())
43 {
44 return itLower->second;
45 }
46
47 float lowerTime = itLower->first;
48 const auto& lowerVal = itLower->second;
49 float upperTime = itUpper->first;
50 const auto& upperVal = itUpper->second;
51
52 if(lowerTime == upperTime)
53 {
54 return lowerVal;
55 }
56
57 return interpolate(lowerTime, lowerVal, upperTime, upperVal, time);
58 };
59
60private:
61 value_type interpolate(float lowerTime,
62 const value_type& lowerVal,
63 float upperTime,
64 const value_type& upperVal,
65 float time) const
66 {
67 const float tt = (time - lowerTime) / (upperTime - lowerTime);
68 const auto result = bx::lerp(lowerVal, upperVal, tt);
69 return result;
70 };
71
72 const key_map& key_map_;
73};
74
75// HDTV rec. 709 matrix.
76static constexpr float M_XYZ2RGB[] = {
77 3.240479f,
78 -0.969256f,
79 0.055648f,
80 -1.53715f,
81 1.875991f,
82 -0.204043f,
83 -0.49853f,
84 0.041556f,
85 1.057311f,
86};
87
88// Converts color representation from CIE XYZ to RGB color-space.
89Color xyzToRgb(const Color& xyz)
90{
91 Color rgb(bx::InitNone);
92 rgb.x = M_XYZ2RGB[0] * xyz.x + M_XYZ2RGB[3] * xyz.y + M_XYZ2RGB[6] * xyz.z;
93 rgb.y = M_XYZ2RGB[1] * xyz.x + M_XYZ2RGB[4] * xyz.y + M_XYZ2RGB[7] * xyz.z;
94 rgb.z = M_XYZ2RGB[2] * xyz.x + M_XYZ2RGB[5] * xyz.y + M_XYZ2RGB[8] * xyz.z;
95 return rgb;
96};
97
98// Precomputed luminance of sunlight in XYZ colorspace.
99// Computed using code from Game Engine Gems, Volume One, chapter 15. Implementation based on Dr. Richard Bird model.
100// This table is used for piecewise linear interpolation. Transitions from and to 0.0 at sunset and sunrise are highly
101// inaccurate
102static std::map<float, Color> sunLuminanceXYZTable = {
103 {5.0f, {0.000000f, 0.000000f, 0.000000f}},
104 {7.0f, {12.703322f, 12.989393f, 9.100411f}},
105 {8.0f, {13.202644f, 13.597814f, 11.524929f}},
106 {9.0f, {13.192974f, 13.597458f, 12.264488f}},
107 {10.0f, {13.132943f, 13.535914f, 12.560032f}},
108 {11.0f, {13.088722f, 13.489535f, 12.692996f}},
109 {12.0f, {13.067827f, 13.467483f, 12.745179f}},
110 {13.0f, {13.069653f, 13.469413f, 12.740822f}},
111 {14.0f, {13.094319f, 13.495428f, 12.678066f}},
112 {15.0f, {13.142133f, 13.545483f, 12.526785f}},
113 {16.0f, {13.201734f, 13.606017f, 12.188001f}},
114 {17.0f, {13.182774f, 13.572725f, 11.311157f}},
115 {18.0f, {12.448635f, 12.672520f, 8.267771f}},
116 {20.0f, {0.000000f, 0.000000f, 0.000000f}},
117};
118
119// Precomputed luminance of sky in the zenith point in XYZ colorspace.
120// Computed using code from Game Engine Gems, Volume One, chapter 15. Implementation based on Dr. Richard Bird model.
121// This table is used for piecewise linear interpolation. Day/night transitions are highly inaccurate.
122// The scale of luminance change in Day/night transitions is not preserved.
123// Luminance at night was increased to eliminate need the of HDR render.
124static std::map<float, Color> skyLuminanceXYZTable = {
125 {0.0f, bx::mul({0.308f, 0.308f, 0.411f}, 0.0f)},
126 //{1.0f, {0.308f, 0.308f, 0.410f}},
127 //{2.0f, {0.301f, 0.301f, 0.402f}},
128 //{3.0f, {0.287f, 0.287f, 0.382f}},
129 {4.0f, bx::mul({0.258f, 0.258f, 0.344f}, 0.05f)},
130 {5.0f, {0.258f, 0.258f, 0.344f}},
131 {7.0f, {0.962851f, 1.000000f, 1.747835f}},
132 {8.0f, {0.967787f, 1.000000f, 1.776762f}},
133 {9.0f, {0.970173f, 1.000000f, 1.788413f}},
134 {10.0f, {0.971431f, 1.000000f, 1.794102f}},
135 {11.0f, {0.972099f, 1.000000f, 1.797096f}},
136 {12.0f, {0.972385f, 1.000000f, 1.798389f}},
137 {13.0f, {0.972361f, 1.000000f, 1.798278f}},
138 {14.0f, {0.972020f, 1.000000f, 1.796740f}},
139 {15.0f, {0.971275f, 1.000000f, 1.793407f}},
140 {16.0f, {0.969885f, 1.000000f, 1.787078f}},
141 {17.0f, {0.967216f, 1.000000f, 1.773758f}},
142 {18.0f, {0.961668f, 1.000000f, 1.739891f}},
143 {20.0f, {0.264f, 0.264f, 0.352f}},
144 {21.0f, bx::mul({0.264f, 0.264f, 0.352f}, 0.05f)},
145 //{22.0f, {0.290f, 0.290f, 0.386f}},
146 {23.0f, bx::mul({0.308f, 0.308f, 0.411f}, 0.0f)},
147 {24.0f, bx::mul({0.308f, 0.308f, 0.411f}, 0.0f)},
148};
149
150// Turbidity tables. Taken from:
151// A. J. Preetham, P. Shirley, and B. Smits. A Practical Analytic Model for Daylight. SIGGRAPH '99
152// Coefficients correspond to xyY colorspace.
153static constexpr Color ABCDE[] = {
154 {-0.2592f, -0.2608f, -1.4630f},
155 {0.0008f, 0.0092f, 0.4275f},
156 {0.2125f, 0.2102f, 5.3251f},
157 {-0.8989f, -1.6537f, -2.5771f},
158 {0.0452f, 0.0529f, 0.3703f},
159};
160
161static constexpr Color ABCDE_t[] = {
162 {-0.0193f, -0.0167f, 0.1787f},
163 {-0.0665f, -0.0950f, -0.3554f},
164 {-0.0004f, -0.0079f, -0.0227f},
165 {-0.0641f, -0.0441f, 0.1206f},
166 {-0.0033f, -0.0109f, -0.0670f},
167};
168
169void compute_perez_coeff(float _turbidity, float* _outPerezCoeff)
170{
171 const bx::Vec3 turbidity = {_turbidity, _turbidity, _turbidity};
172 for(uint32_t ii = 0; ii < 5; ++ii)
173 {
174 const bx::Vec3 tmp = bx::mad(ABCDE_t[ii], turbidity, ABCDE[ii]);
175 float* out = _outPerezCoeff + 4 * ii;
176 bx::store(out, tmp);
177 out[3] = 0.0f;
178 }
179}
180
181float hour_of_day(math::vec3 sun_dir)
182{
183 // Define the ground normal vector (assuming flat and horizontal ground)
184 math::vec3 normal(0.0, -1.0, 0.0);
185
186 auto v1 = sun_dir;
187 auto v2 = normal;
188 auto ref = math::vec3(-1.0f, 0.0f, 0.0f);
189
190 float angle = math::orientedAngle(v1, v2, ref); // angle in [-pi, pi]
191 angle = math::mod(angle, 2 * math::pi<float>()); // angle in [0, 2pi]
192 angle = math::degrees(angle);
193 // The hour angle is 0 at 6:00, 90 at 12:00, and 180 at 18:00
194 // Therefore, we can use a simple linear formula to map the hour angle to the hour of day
195 float hour_of_day = angle / 15;
196
197 // Return the hour of day
198 return hour_of_day;
199}
200}
201} // namespace
202
204{
205 vb_.reset();
206 ib_.reset();
207}
208
210{
211 auto& am = ctx.get_cached<asset_manager>();
212 auto vs_sky = am.get_asset<gfx::shader>("engine:/data/shaders/atmospherics/vs_sky.sc");
213 auto fs_sky = am.get_asset<gfx::shader>("engine:/data/shaders/atmospherics/fs_sky.sc");
214
215 atmospheric_program_.program = std::make_unique<gpu_program>(vs_sky, fs_sky);
216 atmospheric_program_.cache_uniforms();
217
218 int vertical_count = 32;
219 int horizontal_count = 32;
220 std::vector<gfx::screen_pos_vertex> vertices(vertical_count * horizontal_count);
221
222 for(int i = 0; i < vertical_count; i++)
223 {
224 for(int j = 0; j < horizontal_count; j++)
225 {
226 gfx::screen_pos_vertex& v = vertices[i * vertical_count + j];
227 v.x = float(j) / (horizontal_count - 1) * 2.0f - 1.0f;
228 v.y = float(i) / (vertical_count - 1) * 2.0f - 1.0f;
229 }
230 }
231
232 std::vector<uint16_t> indices((vertical_count - 1) * (horizontal_count - 1) * 6);
233
234 int k = 0;
235 for(int i = 0; i < vertical_count - 1; i++)
236 {
237 for(int j = 0; j < horizontal_count - 1; j++)
238 {
239 indices[k++] = (uint16_t)(j + 0 + horizontal_count * (i + 0));
240 indices[k++] = (uint16_t)(j + 1 + horizontal_count * (i + 0));
241 indices[k++] = (uint16_t)(j + 0 + horizontal_count * (i + 1));
242
243 indices[k++] = (uint16_t)(j + 1 + horizontal_count * (i + 0));
244 indices[k++] = (uint16_t)(j + 1 + horizontal_count * (i + 1));
245 indices[k++] = (uint16_t)(j + 0 + horizontal_count * (i + 1));
246 }
247 }
248
249 vb_ = std::make_unique<gfx::vertex_buffer>(
250 gfx::copy(vertices.data(), sizeof(gfx::screen_pos_vertex) * vertical_count * horizontal_count),
252 ib_ = std::make_unique<gfx::index_buffer>(gfx::copy(indices.data(), sizeof(uint16_t) * k));
253
254 sun_.update(0);
255
256 return true;
257}
258
260 const camera& camera,
261 gfx::render_view& rview,
262 delta_t dt,
263 const run_params& params)
264{
265 hour_ += time_scale_ * dt.count();
266 hour_ = bx::mod(hour_, 24.0f);
267 sun_.update(hour_);
268
269 const auto& view = camera.get_view_relative();
270 const auto& proj = camera.get_projection();
271
272 const auto surface = input.get();
273 const auto output_size = surface->get_size();
274 gfx::render_pass pass("atmospherics_pass");
275 pass.bind(surface);
276 pass.set_view_proj(view, proj);
277
278 if(atmospheric_program_.program->is_valid())
279 {
280 atmospheric_program_.program->begin();
281
282 math::vec3 sun_dir(-params.light_direction.x, -params.light_direction.y, -params.light_direction.z);
283 hour_ = ANONYMOUS::hour_of_day(-params.light_direction);
284 // APPLOG_TRACE("Time Of Day {}", hour_);
285
286 ANONYMOUS::dynamic_value_controller sun_luminance_dc(ANONYMOUS::sunLuminanceXYZTable);
287 ANONYMOUS::dynamic_value_controller sky_luminance_dc(ANONYMOUS::skyLuminanceXYZTable);
288
289 auto sunLuminanceXYZ = sun_luminance_dc.get_value(hour_);
290 auto sunLuminanceRGB = ANONYMOUS::xyzToRgb(sunLuminanceXYZ);
291 math::vec3 sun_luminance_rgb(sunLuminanceRGB.x, sunLuminanceRGB.y, sunLuminanceRGB.z);
292
293 auto skyLuminanceXYZ = sky_luminance_dc.get_value(hour_);
294 math::vec3 sky_luminance_xyz(skyLuminanceXYZ.x, skyLuminanceXYZ.y, skyLuminanceXYZ.z);
295 auto skyLuminanceRGB = ANONYMOUS::xyzToRgb(skyLuminanceXYZ);
296 math::vec3 sky_luminance_rgb(skyLuminanceRGB.x, skyLuminanceRGB.y, skyLuminanceRGB.z);
297
298 float exposition[4] = {0.02f, 3.0f, 0.1f, hour_};
299 float perezCoeff[4 * 5];
300 ANONYMOUS::compute_perez_coeff(params.turbidity, perezCoeff);
301
302
303 gfx::set_uniform(atmospheric_program_.u_sunLuminance, sun_luminance_rgb);
304 gfx::set_uniform(atmospheric_program_.u_skyLuminanceXYZ, sky_luminance_xyz);
305 gfx::set_uniform(atmospheric_program_.u_skyLuminance, sky_luminance_rgb);
306 gfx::set_uniform(atmospheric_program_.u_sunDirection, sun_dir);
307 gfx::set_uniform(atmospheric_program_.u_parameters, exposition);
308 gfx::set_uniform(atmospheric_program_.u_perezCoeff, perezCoeff, 5);
309
310
311 irect32_t rect(0, 0, irect32_t::value_type(output_size.width), irect32_t::value_type(output_size.height));
313
314 gfx::set_state(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_EQUAL);
315 gfx::set_index_buffer(ib_->native_handle());
316 gfx::set_vertex_buffer(0, vb_->native_handle());
317 gfx::submit(pass.id, atmospheric_program_.program->native_handle());
318
319 gfx::set_state(BGFX_STATE_DEFAULT);
320 atmospheric_program_.program->end();
321 }
322
323 gfx::discard();
324}
325} // namespace unravel
btVector3 normal
Manages assets, including loading, unloading, and storage.
auto get_asset(const std::string &key, load_flags flags=load_flags::standard) -> asset_handle< T >
Gets an asset by its key.
auto init(rtti::context &ctx) -> bool
void run(gfx::frame_buffer::ptr input, const camera &camera, gfx::render_view &rview, delta_t dt, const run_params &params)
Class representing a camera. Contains functionality for manipulating and updating a camera....
Definition camera.h:35
auto get_projection() const -> const math::transform &
Retrieves the current projection matrix.
Definition camera.cpp:203
auto get_view_relative() const -> const math::transform &
Definition camera.cpp:286
std::chrono::duration< float > delta_t
void submit(view_id _id, program_handle _handle, int32_t _depth, bool _preserveState)
Definition graphics.cpp:899
uint16_t set_scissor(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
Definition graphics.cpp:778
void set_state(uint64_t _state, uint32_t _rgba)
Definition graphics.cpp:763
void set_vertex_buffer(uint8_t _stream, vertex_buffer_handle _handle)
Definition graphics.cpp:838
void discard(uint8_t _flags)
Definition graphics.cpp:968
const memory_view * copy(const void *_data, uint32_t _size)
Definition graphics.cpp:301
void set_uniform(uniform_handle _handle, const void *_value, uint16_t _num)
Definition graphics.cpp:803
void set_index_buffer(index_buffer_handle _handle)
Definition graphics.cpp:808
void set_view_proj(const float *v, const float *p)
gfx::view_id id
Definition render_pass.h:98
void bind(const frame_buffer *fb=nullptr) const
static auto get_layout() -> const vertex_layout &
Definition vertex_decl.h:15
T width() const
std::int32_t value_type
T height() const