]> git.tdb.fi Git - libs/gl.git/blob - demos/desertpillars/source/desertpillars.cpp
Add a moving point light to the night phase of desertpillars
[libs/gl.git] / demos / desertpillars / source / desertpillars.cpp
1 #include <msp/fs/dir.h>
2 #include <msp/gl/directionallight.h>
3 #include <msp/gl/lighting.h>
4 #include <msp/gl/sequencebuilder.h>
5 #include <msp/gl/pointlight.h>
6 #include <msp/gl/renderer.h>
7 #include <msp/gl/tests.h>
8 #include <msp/input/keys.h>
9 #include <msp/time/utils.h>
10 #include "desertpillars.h"
11
12 using namespace std;
13 using namespace Msp;
14
15 DesertPillars::Options::Options()
16 {
17         wnd_opts.width = 1920;
18         wnd_opts.height = 1080;
19         gl_opts.gl_version_major = Graphics::GLOptions::LATEST_VERSION;
20         gl_opts.core_profile = true;
21 }
22
23
24 DesertPillars::DesertPillars(int, char **):
25         window(display, opts.wnd_opts),
26         gl_ctx(window, opts.gl_opts),
27         keyboard(window),
28         view(window, gl_ctx),
29         camera(resources.get<GL::Camera>("Camera.camera")),
30         lighting(resources.get<GL::Lighting>("Desert.lightn")),
31         sphere(resources.get<GL::Object>("Sphere.object")),
32         sphere_morph(0.0f),
33         sphere_frozen(false),
34         sphere_stopped(false),
35         sun(resources.get<GL::DirectionalLight>("Sun.light")),
36         sun_angle(Geometry::Angle<float>::from_turns(0.1f)),
37         wisp(resources.get<GL::PointLight>("Wisp.light")),
38         flare(resources.get<GL::Object>("Flare.object"), lighting.find_light_index(wisp)),
39         camera_stopped(false)
40 {
41         window.set_title("Desert Pillars");
42         window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &DesertPillars::exit), 0));
43         keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
44
45         env_seq = make_unique<GL::Sequence>();
46         env_seq->set_clear_enabled(true);
47         env_seq->set_debug_name("Environment sequence");
48
49         global_env = make_unique<GL::EnvironmentMap>(32, GL::RGB16F, 2, content, *env_seq);
50         global_env->set_fixed_position(GL::Vector3(0.0f, 0.0f, 0.0f));
51         global_env->set_debug_name("Global environment");
52
53         sky = make_unique<GL::Sky>(*global_env, sun);
54         sky->set_debug_name("Sky");
55
56         shadow_seq = make_unique<GL::Sequence>();
57         shadow_seq->set_clear_enabled(true);
58         shadow_seq->set_debug_name("Shadow sequence");
59         GL::Sequence::Step *step = &shadow_seq->add_step("shadow", content);
60         step->set_depth_test(GL::LEQUAL);
61
62         shadow_seq_thsm = make_unique<GL::Sequence>();
63         shadow_seq_thsm->set_clear_enabled(true);
64         shadow_seq_thsm->set_debug_name("Shadow sequence");
65         step = &shadow_seq_thsm->add_step("shadow_thsm", content);
66         step->set_depth_test(GL::LEQUAL);
67
68         shadow_map = make_unique<GL::ShadowMap>(6144, 4096, *sky, lighting);
69         shadow_map->set_debug_name("Shadow map");
70         shadow_map->add_light(sun, 4096, *shadow_seq);
71         shadow_map->add_light(resources.get<GL::PointLight>("Wisp.light"), 2048, *shadow_seq_thsm);
72         shadow_map->set_target(GL::Vector3(0.0f, 0.0f, 0.0f), 20.0f);
73
74         GL::SequenceBuilder seq_bld(resources.get<GL::SequenceTemplate>("Desert.seq"));
75         seq_bld.set_renderable("content", *shadow_map);
76         seq_bld.set_debug_name("Main sequence");
77         sequence.reset(seq_bld.build(view));
78
79         step = &env_seq->add_step("", *shadow_map);
80         step->set_lighting(&lighting);
81         step->set_depth_test(GL::LEQUAL);
82
83         env_map = make_unique<GL::EnvironmentMap>(256, GL::RGB16F, 7, sphere, *env_seq);
84         env_map->set_debug_name("Environment map");
85         sphere.set_matrix(GL::Matrix::translation(GL::Vector3(0.0f, 0.0f, 3.3f)));
86
87         content.add(resources.get<GL::Scene>("Background.scene"));
88         content.add(*env_map);
89         content.add(flare);
90
91         camera.set_debug_name("Main camera");
92
93         view.set_content(sequence.get());
94         view.set_camera(&camera);
95
96         const GL::Vector3 &sun_direction = sun.get_direction();
97         sun_node = normalize(GL::Vector3(sun_direction.y, -sun_direction.x, 0.0f));
98         sun_axis = normalize(cross(sun_direction, sun_node));
99
100         wisp_base_color = wisp.get_color();
101
102         const GL::Vector3 &cam_pos = camera.get_position();
103         camera_distance = cam_pos.norm();
104         camera_angle = Geometry::atan2(cam_pos.y, cam_pos.x);
105         camera_base_height = Geometry::atan2(cam_pos.z, cam_pos.slice<2>(0).norm());
106 }
107
108 int DesertPillars::main()
109 {
110         window.show();
111         return Application::main();
112 }
113
114 void DesertPillars::tick()
115 {
116         Time::TimeStamp t = Time::now();
117         Time::TimeDelta dt = (last_tick ? t-last_tick : Time::zero);
118         last_tick = t;
119
120         if(!sphere_frozen)
121         {
122                 sphere_morph += dt/Time::sec;
123                 sphere.set_morph(sphere_morph);
124         }
125
126         if(!sphere_stopped)
127         {
128                 sphere_angle += Geometry::Angle<float>::from_degrees(36*dt/Time::sec);
129                 sphere.set_matrix(GL::Matrix().translate(GL::Vector3(0.0f, 0.0f, 3.3f))
130                         .rotate(sphere_angle, GL::Vector3(0.0f, 0.0f, 1.0f)).rotate(sphere_angle*0.5f, GL::Vector3(1.0f, 0.0f, 0.0f)));
131         }
132
133         if(!camera_stopped)
134         {
135                 camera_angle += Geometry::Angle<float>::from_degrees(12*dt/Time::sec);
136                 Geometry::Angle<float> cam_height = camera_base_height+Geometry::Angle<float>::from_degrees(15.0f*cos(camera_angle*1.5f));
137                 GL::Vector3 cam_dir(cos(camera_angle)*cos(cam_height), sin(camera_angle)*cos(cam_height), sin(cam_height));
138                 camera.set_position(GL::Vector3(0.0f, 0.0f, 2.0f)+cam_dir*camera_distance);
139                 camera.set_look_direction(-cam_dir);
140         }
141
142         sun_angle += Geometry::Angle<float>::from_degrees(4*dt/Time::sec);
143         sun.set_direction(GL::Matrix::rotation(sun_angle, sun_axis)*-sun_node);
144
145         wisp_angle += Geometry::Angle<float>::from_degrees(6*dt/Time::sec);
146         float r = 3.1f+1.1f*cos(4.0f*wisp_angle);
147         GL::Vector3 p(cos(wisp_angle)*r, sin(wisp_angle)*r, 3.6f+0.4f*sin(1.6f*wisp_angle));
148         wisp.set_position(p);
149         float twilight = 0.8f-min(max(sin(sun_angle), -0.05f), 0.2f)*4.0f;
150         wisp.set_color(wisp_base_color*((3.0f-2.0f*twilight)*twilight*twilight));
151         flare.set_matrix(GL::Matrix::translation(p));
152
153         display.tick();
154         view.render();
155 }
156
157 void DesertPillars::key_press(unsigned key)
158 {
159         if(key==Input::KEY_ESC)
160                 exit(0);
161         else if(key==Input::KEY_SPACE)
162                 camera_stopped = !camera_stopped;
163         else if(key==Input::KEY_F)
164                 sphere_frozen = !sphere_frozen;
165         else if(key==Input::KEY_S)
166                 sphere_stopped = !sphere_stopped;
167 }
168
169
170 DesertPillars::Resources::Resources()
171 {
172         FS::Path base_dir = FS::get_sys_data_dir()/"demos"/"desertpillars"/"data";
173         source.add_directory(base_dir);
174         source.add_directory(base_dir/"textures");
175         source.add_directory(base_dir/"exported");
176         add_source(source);
177 }
178
179
180 void DesertPillars::MorphSphere::set_morph(float m)
181 {
182         shdata.uniform("morph", m);
183 }
184
185 void DesertPillars::MorphSphere::setup_render(GL::Renderer &renderer, GL::Tag tag) const
186 {
187         ObjectInstance::setup_render(renderer, tag);
188         renderer.add_shader_data(shdata);
189 }
190
191
192 DesertPillars::LightFlare::LightFlare(const GL::Object &o, unsigned i):
193         ObjectInstance(o)
194 {
195         shdata.uniform("flare_light_index", static_cast<int>(i));
196 }
197
198 void DesertPillars::LightFlare::setup_render(GL::Renderer &renderer, GL::Tag tag) const
199 {
200         ObjectInstance::setup_render(renderer, tag);
201         renderer.add_shader_data(shdata);
202 }