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
154 int cloud_mode = 2;
156 float cloud_coverage = 0.52f;
158 float cloud_base_altitude = 27500.0f;
160 float cloud_top_altitude = 35000.0f;
162 float cloud_time = 0.0f;
164 float cloud_density = 1.5f;
166 float cloud_absorption = 0.08f;
170 float sky_brightness = 1.0f;
172 float irradiance_intensity = 0.15f;
173
175 float cloud_vol_uv_scale = 0.00008f;
176 float cloud_vol_edge_width = 0.20f;
182 float cloud_vol_base_mix = 0.45f;
184 };
185
186 auto init(rtti::context& ctx) -> bool;
187 void run(gfx::frame_buffer::ptr input, const camera& camera, gfx::render_view& rview, delta_t dt, const run_params& params);
188
189private:
190
191 struct atmospheric_program : uniforms_cache
192 {
193 void cache_uniforms()
194 {
195 cache_uniform(program.get(), u_sunLuminance, "u_sunLuminance", gfx::uniform_type::Vec4);
196 cache_uniform(program.get(), u_skyLuminanceXYZ, "u_skyLuminanceXYZ", gfx::uniform_type::Vec4);
197 cache_uniform(program.get(), u_skyLuminance, "u_skyLuminance", gfx::uniform_type::Vec4);
198 cache_uniform(program.get(), u_sunDirection, "u_sunDirection", gfx::uniform_type::Vec4);
199 cache_uniform(program.get(), u_parameters, "u_parameters", gfx::uniform_type::Vec4);
200 cache_uniform(program.get(), u_perezCoeff, "u_perezCoeff", gfx::uniform_type::Vec4);
201 cache_uniform(program.get(), u_cloudParams, "u_cloudParams", gfx::uniform_type::Vec4);
202 cache_uniform(program.get(), u_cloudParams2, "u_cloudParams2", gfx::uniform_type::Vec4);
203 cache_uniform(program.get(), s_cloudTex, "s_cloudTex", gfx::uniform_type::Sampler);
204 cache_uniform(program.get(), s_cloudNoise2D, "s_cloudNoise2D", gfx::uniform_type::Sampler);
205 }
206
207 gfx::program::uniform_ptr u_sunLuminance;
208 gfx::program::uniform_ptr u_skyLuminanceXYZ;
209 gfx::program::uniform_ptr u_skyLuminance;
210 gfx::program::uniform_ptr u_sunDirection;
211
212 gfx::program::uniform_ptr u_parameters;
213 gfx::program::uniform_ptr u_perezCoeff;
214 gfx::program::uniform_ptr u_cloudParams;
215 gfx::program::uniform_ptr u_cloudParams2;
216 gfx::program::uniform_ptr s_cloudTex;
217 gfx::program::uniform_ptr s_cloudNoise2D;
218
219 std::unique_ptr<gpu_program> program;
220
221 } atmospheric_program_;
222
223 struct cloud_program : uniforms_cache
224 {
225 void cache_uniforms()
226 {
227 cache_uniform(program.get(), u_skyLuminanceXYZ, "u_skyLuminanceXYZ", gfx::uniform_type::Vec4);
228 cache_uniform(program.get(), u_skyLuminance, "u_skyLuminance", gfx::uniform_type::Vec4);
229 cache_uniform(program.get(), u_sunLuminance, "u_sunLuminance", gfx::uniform_type::Vec4);
230 cache_uniform(program.get(), u_sunDirection, "u_sunDirection", gfx::uniform_type::Vec4);
231 cache_uniform(program.get(), u_parameters, "u_parameters", gfx::uniform_type::Vec4);
232 cache_uniform(program.get(), u_perezCoeff, "u_perezCoeff", gfx::uniform_type::Vec4);
233 cache_uniform(program.get(), u_cloudParams, "u_cloudParams", gfx::uniform_type::Vec4);
234 cache_uniform(program.get(), u_cloudParams2, "u_cloudParams2", gfx::uniform_type::Vec4);
235 cache_uniform(program.get(), u_cloudParams3, "u_cloudParams3", gfx::uniform_type::Vec4);
236 cache_uniform(program.get(), u_cloudParams4, "u_cloudParams4", gfx::uniform_type::Vec4);
237 cache_uniform(program.get(), s_cloudNoise, "s_cloudNoise", gfx::uniform_type::Sampler);
238 cache_uniform(program.get(), s_cloudHistory, "s_cloudHistory", gfx::uniform_type::Sampler);
239 cache_uniform(program.get(), u_cloudFrame, "u_cloudFrame", gfx::uniform_type::Vec4);
240 cache_uniform(program.get(), u_prevViewProj, "u_prevViewProj", gfx::uniform_type::Mat4);
241 }
242
243 gfx::program::uniform_ptr u_skyLuminanceXYZ;
244 gfx::program::uniform_ptr u_skyLuminance;
245 gfx::program::uniform_ptr u_sunLuminance;
246 gfx::program::uniform_ptr u_sunDirection;
247 gfx::program::uniform_ptr u_parameters;
248 gfx::program::uniform_ptr u_perezCoeff;
249 gfx::program::uniform_ptr u_cloudParams;
250 gfx::program::uniform_ptr u_cloudParams2;
251 gfx::program::uniform_ptr u_cloudParams3;
252 gfx::program::uniform_ptr u_cloudParams4;
253 gfx::program::uniform_ptr u_cloudFrame;
254 gfx::program::uniform_ptr u_prevViewProj;
255 gfx::program::uniform_ptr s_cloudNoise;
256 gfx::program::uniform_ptr s_cloudHistory;
257
258 std::unique_ptr<gpu_program> program;
259
260 } cloud_program_;
261
262
263 std::unique_ptr<gfx::vertex_buffer> vb_;
264 std::unique_ptr<gfx::index_buffer> ib_;
265
266 detail::sun_controller sun_;
267};
268} // 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:62
std::chrono::duration< float > delta_t
Definition imgui.h:25
std::shared_ptr< uniform > uniform_ptr
Definition program.h:19
float cloud_vol_uv_scale
Volumetric cloud u_cloudParams3: uv scale, edge width, shape power, detail erode.
float cloud_density
Cloud density/opacity multiplier.
float irradiance_intensity
Irradiance intensity. Scales cloud ambient (sky-scattered light into clouds).
float cloud_absorption
Beer-Lambert extinction coefficient [0.01-0.5].
float cloud_light_absorption
Light absorption / self-shadow strength [0.01-0.5].
float cloud_vol_macro_strength
Volumetric cloud u_cloudParams4: macro strength, coarse scale, base mix, sun intensity.
float cloud_top_altitude
Cloud top altitude in world units. Vol: slab top. Flat: ignored.
float cloud_coverage
Cloud coverage [0.0 = clear sky, 1.0 = overcast]. Controls the density threshold.
int cloud_mode
Cloud mode: 0=none, 1=flat, 2=volumetric.
float cloud_time
Accumulated elapsed time (seconds) for cloud animation.
float sky_brightness
Sky brightness multiplier (1.0 = neutral). Affects visible sky and irradiance.
float cloud_base_altitude
Cloud base altitude in world units. Vol: slab bottom. Flat: projection height.
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.