]> git.tdb.fi Git - libs/gl.git/blob - source/effects/environmentmap.cpp
Use persistent cameras in effects
[libs/gl.git] / source / effects / environmentmap.cpp
1 #include <algorithm>
2 #include <cmath>
3 #include "environmentmap.h"
4 #include "renderer.h"
5 #include "resources.h"
6 #include "texunit.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 EnvironmentMap::EnvironmentMap(Resources &resources, unsigned s, Renderable &r, Renderable &e):
14         Effect(r),
15         size(s),
16         environment(e),
17         sampler(resources.get<Sampler>("_linear_clamp.samp")),
18         rendered(false),
19         update_interval(1),
20         update_delay(0)
21 {
22         env_tex.storage(RGB8, size, 1);
23         depth_buf.storage(DEPTH_COMPONENT32F, size, size);
24         for(unsigned i=0; i<6; ++i)
25         {
26                 TextureCubeFace face = TextureCube::enumerate_faces(i);
27                 faces[i].fbo.attach(COLOR_ATTACHMENT0, env_tex, face, 0);
28                 faces[i].fbo.attach(DEPTH_ATTACHMENT, depth_buf);
29                 faces[i].fbo.require_complete();
30                 faces[i].camera.set_look_direction(TextureCube::get_face_direction(face));
31                 faces[i].camera.set_up_direction(TextureCube::get_t_direction(face));
32                 faces[i].camera.set_field_of_view(Geometry::Angle<float>::right());
33                 faces[i].camera.set_aspect_ratio(1);
34                 faces[i].camera.set_depth_clip(0.1, 100);
35         }
36 }
37
38 void EnvironmentMap::set_depth_clip(float n, float f)
39 {
40         for(unsigned i=0; i<6; ++i)
41                 faces[i].camera.set_depth_clip(n, f);
42 }
43
44 void EnvironmentMap::set_update_interval(unsigned i)
45 {
46         update_interval = i;
47         update_delay = min(update_delay, update_interval-1);
48 }
49
50 void EnvironmentMap::queue_update()
51 {
52         update_delay = 0;
53 }
54
55 void EnvironmentMap::setup_frame(Renderer &renderer)
56 {
57         if(rendered)
58                 return;
59
60         rendered = true;
61         renderable.setup_frame(renderer);
62
63         if(update_delay)
64         {
65                 if(update_interval)
66                         --update_delay;
67                 return;
68         }
69         update_delay = update_interval-1;
70         environment.setup_frame(renderer);
71
72         const Matrix *matrix = renderable.get_matrix();
73         if(!matrix)
74                 return;
75
76         Renderer::Push push(renderer);
77         Renderer::Exclude exclude1(renderer, renderable);
78         Renderer::Exclude exclude2(renderer, *this);
79
80         Vector3 center = matrix->column(3).slice<3>(0);
81
82         BindRestore bind_fbo(faces[0].fbo);
83         for(unsigned i=0; i<6; ++i)
84         {
85                 faces[i].camera.set_position(center);
86                 faces[i].fbo.bind();
87                 faces[i].fbo.clear();
88                 renderer.set_camera(faces[i].camera);
89                 renderer.render(environment);
90         }
91 }
92
93 void EnvironmentMap::finish_frame()
94 {
95         if(rendered)
96         {
97                 rendered = false;
98                 renderable.finish_frame();
99                 environment.finish_frame();
100         }
101 }
102
103 void EnvironmentMap::render(Renderer &renderer, Tag tag) const
104 {
105         if(!enabled_passes.count(tag))
106                 return renderer.render(renderable, tag);
107
108         Renderer::Push _push_rend(renderer);
109
110         const Matrix &camera_matrix = renderer.get_camera()->get_object_matrix();
111         shdata.uniform("env_eye_matrix", camera_matrix.block<3, 3>(0, 0));
112
113         renderer.set_texture("environment_map", &env_tex, &sampler);
114         renderer.add_shader_data(shdata);
115         renderer.render(renderable, tag);
116 }
117
118 } // namespace GL
119 } // namespace Msp