Unravel Engine C++ Reference
Loading...
Searching...
No Matches
atmospheric_pass_perez.h
Go to the documentation of this file.
1/*
2 * This example demonstrates:
3 * - Usage of Perez sky model [1] to render a dynamic sky.
4 * - Rendering a mesh with a lightmap, shading of which is driven by the same parameters as the sky.
5 *
6 * Typically, the sky is rendered using cubemaps or other environment maps.
7 * This approach can provide a high-quality sky, but the downside is that the
8 * image is static. To achieve daytime changes in sky appearance, there is a need
9 * in a dynamic model.
10 *
11 * Perez "An All-Weather Model for Sky Luminance Distribution" is a simple,
12 * but good enough model which is, in essence, a function that
13 * interpolates a sky color. As input, it requires several turbidity
14 * coefficients, a color at zenith and direction to the sun.
15 * Turbidity coefficients are taken from [2], which are computed using more
16 * complex physically based models. Color at zenith depends on daytime and can
17 * vary depending on many factors.
18 *
19 * In the code below, there are two tables that contain sky and sun luminance
20 * which were computed using code from [3]. Luminance in those tables
21 * represents actual scale of light energy that comes from sun compared to
22 * the sky.
23 *
24 * The sky is driven by luminance of the sky, while the material of the
25 * landscape is driven by both, the luminance of the sky and the sun. The
26 * lightening model is very simple and consists of two parts: directional
27 * light and hemisphere light. The first is used for the sun while the second
28 * is used for the sky. Additionally, the second part is modulated by a
29 * lightmap to achieve ambient occlusion effect.
30 *
31 * References
32 * ==========
33 *
34 * [1] R. Perez, R. Seals, and J. Michalsky."An All-Weather Model for Sky Luminance Distribution".
35 * Solar Energy, Volume 50, Number 3 (March 1993), pp. 235-245.
36 *
37 * [2] A. J. Preetham, Peter Shirley, and Brian Smits. "A Practical Analytic Model for Daylight",
38 * Proceedings of the 26th Annual Conference on Computer Graphics and Interactive Techniques,
39 * 1999, pp. 91-100.
40 * https://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
41 *
42 * [3] E. Lengyel, Game Engine Gems, Volume One. Jones & Bartlett Learning, 2010. pp. 219 - 234
43 *
44 */
45
46#pragma once
47
50
55
56namespace unravel
57{
58
59namespace detail
60{
61
62// Controls sun position according to time, month, and observer's latitude.
63// Sun position computation based on Earth's orbital elements:
64// https://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html
66{
67public:
68 enum class month : int
69 {
70 january = 0,
72 march,
73 april,
74 may,
75 june,
76 july,
77 august,
79 october,
82 };
83
85 : north_dir_(1.0f, 0.0f, 0.0f)
86 , sun_dir_(0.0f, -1.0f, 0.0f)
87 , up_dir_(0.0f, 1.0f, 0.0f)
88 , latitude_(50.0f)
89 , month_(month::june)
90 , ecliptic_obliquity_(bx::toRad(23.4f))
91 , delta_(0.0f)
92 {
93 }
94
95 void update(float _time)
96 {
97 calculate_sun_orbit();
98 update_sun_position(_time - 12.0f);
99 }
100
101 bx::Vec3 north_dir_;
102 bx::Vec3 sun_dir_;
103 bx::Vec3 up_dir_;
106
107private:
108 void calculate_sun_orbit()
109 {
110 const float day = 30.0f * float(month_) + 15.0f;
111 float lambda = 280.46f + 0.9856474f * day;
112 lambda = bx::toRad(lambda);
113 delta_ = bx::asin(bx::sin(ecliptic_obliquity_) * bx::sin(lambda));
114 }
115
116 void update_sun_position(float _hour)
117 {
118 const float latitude = bx::toRad(latitude_);
119 const float hh = _hour * bx::kPi / 12.0f;
120 const float azimuth =
121 bx::atan2(bx::sin(hh), bx::cos(hh) * bx::sin(latitude) - bx::tan(delta_) * bx::cos(latitude));
122
123 const float altitude =
124 bx::asin(bx::sin(latitude) * bx::sin(delta_) + bx::cos(latitude) * bx::cos(delta_) * bx::cos(hh));
125
126 const bx::Quaternion rot0 = bx::fromAxisAngle(up_dir_, -azimuth);
127 const bx::Vec3 dir = bx::mul(north_dir_, rot0);
128 const bx::Vec3 uxd = bx::cross(up_dir_, dir);
129
130 const bx::Quaternion rot1 = bx::fromAxisAngle(uxd, altitude);
131 sun_dir_ = bx::mul(dir, rot1);
132 }
133
134 float ecliptic_obliquity_;
135 float delta_;
136};
137
138} // namespace detail
139
141{
142public:
145
147 {
148 math::vec3 light_direction = math::normalize(math::vec3(0.2f, -0.8f, 1.0f));
149
150 // [1.9 - 10.0f]
151 float turbidity = 1.9f;
152 };
153
154 auto init(rtti::context& ctx) -> bool;
155 void run(gfx::frame_buffer::ptr input, const camera& camera, gfx::render_view& rview, delta_t dt, const run_params& params);
156
157private:
158
159 struct atmospheric_program : uniforms_cache
160 {
161 void cache_uniforms()
162 {
163 cache_uniform(program.get(), u_sunLuminance, "u_sunLuminance", gfx::uniform_type::Vec4);
164 cache_uniform(program.get(), u_skyLuminanceXYZ, "u_skyLuminanceXYZ", gfx::uniform_type::Vec4);
165 cache_uniform(program.get(), u_skyLuminance, "u_skyLuminance", gfx::uniform_type::Vec4);
166 cache_uniform(program.get(), u_sunDirection, "u_sunDirection", gfx::uniform_type::Vec4);
167 cache_uniform(program.get(), u_parameters, "u_parameters", gfx::uniform_type::Vec4);
168 cache_uniform(program.get(), u_perezCoeff, "u_perezCoeff", gfx::uniform_type::Vec4);
169 }
170
171 gfx::program::uniform_ptr u_sunLuminance;
172 gfx::program::uniform_ptr u_skyLuminanceXYZ;
173 gfx::program::uniform_ptr u_skyLuminance;
174 gfx::program::uniform_ptr u_sunDirection;
175
176 gfx::program::uniform_ptr u_parameters;
177 gfx::program::uniform_ptr u_perezCoeff;
178
179 std::unique_ptr<gpu_program> program;
180
181 } atmospheric_program_;
182
183
184 std::unique_ptr<gfx::vertex_buffer> vb_;
185 std::unique_ptr<gfx::index_buffer> ib_;
186
187 detail::sun_controller sun_;
188
189 float hour_{};
190 float time_scale_{1.0f};
191
192};
193} // namespace unravel
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
std::chrono::duration< float > delta_t
Definition imgui.h:25
std::shared_ptr< uniform > uniform_ptr
Definition program.h:19
Structure for caching uniforms.
void cache_uniform(gpu_program *program, gfx::program::uniform_ptr &uniform, const hpp::string_view &name, gfx::uniform_type type, uint16_t num=1)
Caches a uniform in the GPU program.