]> git.tdb.fi Git - libs/gl.git/blob - source/effects/environmentmap.cpp
Load various built-in things through Resources
[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                 fbo[i].attach(COLOR_ATTACHMENT0, env_tex, TextureCube::enumerate_faces(i), 0);
27                 fbo[i].attach(DEPTH_ATTACHMENT, depth_buf);
28                 fbo[i].require_complete();
29         }
30
31         camera.set_field_of_view(Geometry::Angle<float>::right());
32         camera.set_aspect_ratio(1);
33         camera.set_depth_clip(0.1, 100);
34 }
35
36 void EnvironmentMap::set_depth_clip(float n, float f)
37 {
38         camera.set_depth_clip(n, f);
39 }
40
41 void EnvironmentMap::set_update_interval(unsigned i)
42 {
43         update_interval = i;
44         update_delay = min(update_delay, update_interval-1);
45 }
46
47 void EnvironmentMap::queue_update()
48 {
49         update_delay = 0;
50 }
51
52 void EnvironmentMap::setup_frame(Renderer &renderer)
53 {
54         if(rendered)
55                 return;
56
57         rendered = true;
58         renderable.setup_frame(renderer);
59
60         if(update_delay)
61         {
62                 if(update_interval)
63                         --update_delay;
64                 return;
65         }
66         update_delay = update_interval-1;
67         environment.setup_frame(renderer);
68
69         const Matrix *matrix = renderable.get_matrix();
70         if(!matrix)
71                 return;
72
73         Renderer::Push push(renderer);
74         Renderer::Exclude exclude1(renderer, renderable);
75         Renderer::Exclude exclude2(renderer, *this);
76
77         camera.set_position(matrix->column(3).slice<3>(0));
78
79         BindRestore bind_fbo(fbo[0]);
80         for(unsigned i=0; i<6; ++i)
81         {
82                 TextureCubeFace face = TextureCube::enumerate_faces(i);
83                 fbo[i].bind();
84                 fbo[i].clear();
85                 camera.set_look_direction(TextureCube::get_face_direction(face));
86                 camera.set_up_direction(TextureCube::get_t_direction(face));
87                 renderer.set_camera(camera);
88                 renderer.render(environment);
89         }
90 }
91
92 void EnvironmentMap::finish_frame()
93 {
94         if(rendered)
95         {
96                 rendered = false;
97                 renderable.finish_frame();
98                 environment.finish_frame();
99         }
100 }
101
102 void EnvironmentMap::render(Renderer &renderer, const Tag &tag) const
103 {
104         if(!enabled_passes.count(tag))
105                 return renderer.render(renderable, tag);
106
107         Renderer::Push _push_rend(renderer);
108
109         unsigned unit = renderer.allocate_effect_texunit();
110         shdata.uniform("environment", static_cast<int>(unit));
111         Bind _bind_sampler(sampler, unit);
112         Bind _bind_env(env_tex, unit);
113
114         const Matrix &camera_matrix = renderer.get_camera()->get_object_matrix();
115         shdata.uniform("env_eye_matrix", camera_matrix.block<3, 3>(0, 0));
116
117         renderer.add_shader_data(shdata);
118         renderer.render(renderable, tag);
119 }
120
121 } // namespace GL
122 } // namespace Msp