]> git.tdb.fi Git - libs/gl.git/blob - source/pipeline.cpp
Turn Effect into a Renderable
[libs/gl.git] / source / pipeline.cpp
1 #include <msp/core/maputils.h>
2 #include "blend.h"
3 #include "camera.h"
4 #include "framebuffer.h"
5 #include "lighting.h"
6 #include "pipeline.h"
7 #include "postprocessor.h"
8 #include "renderbuffer.h"
9 #include "renderer.h"
10 #include "tests.h"
11 #include "texture2d.h"
12
13 using namespace std;
14
15 namespace Msp {
16 namespace GL {
17
18 Pipeline::Pipeline(unsigned w, unsigned h, bool d):
19         camera(0),
20         width(w),
21         height(h),
22         hdr(d),
23         samples(0),
24         fbo(0),
25         color_buf(0),
26         depth_buf(0),
27         fbo_ms(0),
28         color_buf_ms(0),
29         depth_buf_ms(0)
30 { }
31
32 Pipeline::~Pipeline()
33 {
34         delete fbo;
35         delete color_buf;
36         delete depth_buf;
37 }
38
39 void Pipeline::set_hdr(bool h)
40 {
41         hdr = h;
42         if(!postproc.empty())
43                 create_fbos();
44 }
45
46 void Pipeline::set_multisample(unsigned s)
47 {
48         samples = s;
49         if(!postproc.empty())
50                 create_fbos();
51 }
52
53 void Pipeline::set_camera(const Camera *c)
54 {
55         camera = c;
56 }
57
58 PipelinePass &Pipeline::add_pass(const Tag &tag)
59 {
60         PipelinePass &pass = insert_unique(passes, tag, PipelinePass())->second;
61         pass_order.push_back(tag);
62         return pass;
63 }
64
65 PipelinePass &Pipeline::get_pass(const Tag &tag)
66 {
67         return get_item(passes, tag);
68 }
69
70 const PipelinePass &Pipeline::get_pass(const Tag &tag) const
71 {
72         return get_item(passes, tag);
73 }
74
75 void Pipeline::add_renderable(const Renderable &r)
76 {
77         for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
78                 if(i->renderable==&r)
79                 {
80                         i->passes.clear();
81                         return;
82                 }
83
84         renderables.push_back(&r);
85 }
86
87 void Pipeline::add_renderable_for_pass(const Renderable &r, const Tag &tag)
88 {
89         for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
90                 if(i->renderable==&r)
91                 {
92                         i->passes.insert(tag);
93                         return;
94                 }
95
96         renderables.push_back(&r);
97         renderables.back().passes.insert(tag);
98 }
99
100 void Pipeline::remove_renderable(const Renderable &r)
101 {
102         for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
103                 if(i->renderable==&r)
104                 {
105                         renderables.erase(i);
106                         return;
107                 }
108 }
109
110 void Pipeline::add_postprocessor(PostProcessor &pp)
111 {
112         postproc.push_back(&pp);
113         if(!fbo)
114                 create_fbos();
115         {
116         }
117 }
118
119 void Pipeline::render(Renderer &renderer, const Tag &tag) const
120 {
121         const PipelinePass &pass = get_pass(tag);
122
123         Bind bind_depth_test(pass.depth_test);
124         Bind bind_blend(pass.blend);
125         Bind bind_lighting(pass.lighting);
126
127         for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
128                 if(i->passes.empty() || i->passes.count(tag))
129                         i->renderable->render(renderer, tag);
130 }
131
132 void Pipeline::render_all() const
133 {
134         if(camera)
135                 camera->apply();
136
137         if(fbo)
138         {
139                 Framebuffer *f = (fbo_ms ? fbo_ms : fbo);
140                 f->bind();
141                 f->clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
142         }
143
144         Renderer renderer(camera);
145         for(vector<Tag>::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i)
146                 render(renderer, *i);
147
148         if(fbo)
149         {
150                 if(fbo_ms)
151                         fbo->blit_from(*fbo_ms, COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT, false);
152                 Framebuffer::unbind();
153         }
154
155         // XXX Need two color buffer textures to handle multiple post-processors correctly
156         for(vector<PostProcessor *>::const_iterator i=postproc.begin(); i!=postproc.end(); ++i)
157                 (*i)->render(*color_buf, *depth_buf);
158 }
159
160 void Pipeline::create_fbos()
161 {
162         delete fbo;
163         delete color_buf;
164         delete depth_buf;
165
166         delete fbo_ms;
167         fbo_ms = 0;
168         delete color_buf_ms;
169         color_buf_ms = 0;
170         delete depth_buf_ms;
171         depth_buf_ms = 0;
172
173         fbo = new Framebuffer;
174
175         color_buf = new Texture2D;
176         color_buf->set_min_filter(NEAREST);
177         color_buf->set_mag_filter(NEAREST);
178         color_buf->set_wrap(CLAMP_TO_EDGE);
179         color_buf->storage((hdr ? RGB16F : RGB), width, height);
180         fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0);
181
182         depth_buf = new Texture2D;
183         depth_buf->set_min_filter(NEAREST);
184         depth_buf->set_mag_filter(NEAREST);
185         depth_buf->set_wrap(CLAMP_TO_EDGE);
186         depth_buf->storage(DEPTH_COMPONENT, width, height);
187         fbo->attach(DEPTH_ATTACHMENT, *depth_buf, 0);
188
189         if(samples)
190         {
191                 fbo_ms = new Framebuffer;
192
193                 color_buf_ms = new Renderbuffer;
194                 color_buf_ms->storage_multisample(samples, (hdr ? RGB16F : RGB), width, height);
195                 fbo_ms->attach(COLOR_ATTACHMENT0, *color_buf_ms);
196
197                 depth_buf_ms = new Renderbuffer;
198                 depth_buf_ms->storage_multisample(samples, DEPTH_COMPONENT, width, height);
199                 fbo_ms->attach(DEPTH_ATTACHMENT, *depth_buf_ms);
200         }
201 }
202
203
204 Pipeline::Slot::Slot(const Renderable *r):
205         renderable(r)
206 { }
207
208 } // namespace GL
209 } // namespace Msp