]> git.tdb.fi Git - libs/gl.git/blob - source/effects/sky.cpp
baf4864ad02256b1b83a332541369241c5e8f019
[libs/gl.git] / source / effects / sky.cpp
1 #include "light.h"
2 #include "mesh.h"
3 #include "renderer.h"
4 #include "resources.h"
5 #include "sky.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 Sky::Sky(Renderable &r, const Light &s):
13         Effect(r),
14         sun(s),
15         transmittance_lookup(128, 64, (RENDER_COLOR, RGB16F)),
16         transmittance_shprog(Resources::get_global().get<Program>("_sky_transmittance.glsl.shader")),
17         transmittance_lookup_dirty(true),
18         distant(256, 128, (RENDER_COLOR, RGB16F)),
19         distant_shprog(Resources::get_global().get<Program>("_sky_distant.glsl.shader")),
20         fullscreen_mesh(Resources::get_global().get<Mesh>("_fullscreen_quad.mesh")),
21         backdrop_shprog(Resources::get_global().get<Program>("_sky_backdrop.glsl.shader")),
22         sampler(Resources::get_global().get<Sampler>("_linear_clamp.samp")),
23         wrap_sampler(Resources::get_global().get<Sampler>("_linear_clamp_v.samp")),
24         rendered(false)
25 {
26         shdata.uniform("n_steps", 50);
27
28         set_planet(Planet::earth());
29         set_view_height(5.0f);
30 }
31
32 void Sky::set_planet(const Planet &planet)
33 {
34         shdata.uniform("events.rayleigh_scatter", planet.rayleigh_scatter.r, planet.rayleigh_scatter.g, planet.rayleigh_scatter.b);
35         shdata.uniform("events.mie_scatter", planet.mie_scatter.r, planet.mie_scatter.g, planet.mie_scatter.b);
36         shdata.uniform("events.mie_absorb", planet.mie_absorb.r, planet.mie_absorb.g, planet.mie_absorb.b);
37         shdata.uniform("events.ozone_absorb", planet.ozone_absorb.r, planet.ozone_absorb.g, planet.ozone_absorb.b);
38         shdata.uniform("rayleigh_density_decay", planet.rayleigh_density_decay);
39         shdata.uniform("mie_density_decay", planet.mie_density_decay);
40         shdata.uniform("ozone_band_center", planet.ozone_band_center);
41         shdata.uniform("ozone_band_extent", planet.ozone_band_extent);
42         shdata.uniform("atmosphere_thickness", planet.atmosphere_thickness);
43         shdata.uniform("planet_radius", planet.planet_radius);
44         shdata.uniform("ground_albedo", planet.ground_albedo.r, planet.ground_albedo.g, planet.ground_albedo.b);
45 }
46
47 void Sky::set_view_height(float h)
48 {
49         shdata.uniform("view_height", h);
50 }
51
52 void Sky::setup_frame(Renderer &renderer)
53 {
54         if(rendered)
55                 return;
56
57         rendered = true;
58
59         shdata.uniform("light_color", sun.get_color());
60         shdata.uniform("light_dir", sun.get_position().slice<3>(0));
61
62         Renderer::Push push(renderer);
63
64         if(transmittance_lookup_dirty)
65         {
66                 transmittance_lookup_dirty = false;
67                 Bind bind_fbo(transmittance_lookup.get_framebuffer());
68                 renderer.set_shader_program(&transmittance_shprog, &shdata);
69                 fullscreen_mesh.draw(renderer);
70         }
71
72         Bind bind_fbo(distant.get_framebuffer());
73         renderer.set_shader_program(&distant_shprog, &shdata);
74         renderer.set_texture("transmittance_lookup", &transmittance_lookup.get_target_texture(0), &sampler);
75         fullscreen_mesh.draw(renderer);
76
77         renderable.setup_frame(renderer);
78 }
79
80 void Sky::finish_frame()
81 {
82         if(rendered)
83         {
84                 rendered = false;
85                 renderable.finish_frame();
86         }
87 }
88
89 void Sky::render(Renderer &renderer, Tag tag) const
90 {
91         renderable.render(renderer, tag);
92
93         Renderer::Push push(renderer);
94
95         renderer.set_shader_program(&backdrop_shprog, &shdata);
96         renderer.set_texture("distant", &distant.get_target_texture(0), &wrap_sampler);
97         fullscreen_mesh.draw(renderer);
98 }
99
100
101 Sky::Planet::Planet():
102         rayleigh_scatter(0.0f),
103         mie_scatter(0.0f),
104         mie_absorb(0.0f),
105         ozone_absorb(0.0f),
106         rayleigh_density_decay(1e3f),
107         mie_density_decay(1e3f),
108         ozone_band_center(1e4f),
109         ozone_band_extent(1e2f),
110         atmosphere_thickness(2e4f),
111         planet_radius(1e6f)
112 { }
113
114 Sky::Planet Sky::Planet::earth()
115 {
116         Planet planet;
117         planet.rayleigh_scatter = Color(5.802e-6f, 13.558e-6f, 33.1e-6f);
118         planet.mie_scatter = Color(3.996e-6f, 3.996e-6f, 3.996e-6f);
119         planet.mie_absorb = Color(4.4e-6f, 4.4e-6f, 4.4e-6f);
120         planet.ozone_absorb = Color(0.65e-6f, 1.881e-6f, 0.085e-6f);
121         planet.rayleigh_density_decay = -8e3f;
122         planet.mie_density_decay = -1.2e3f;
123         planet.ozone_band_center = 25e3f;
124         planet.ozone_band_extent = 15e3f;
125         planet.atmosphere_thickness = 1e5f;
126         planet.planet_radius = 6.36e6f;
127         return planet;
128 }
129
130 } // namespace GL
131 } // namespace Msp