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