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