]> git.tdb.fi Git - libs/gl.git/blob - source/render/sequence.cpp
9a50b8f6f405648ff7b857af03f394b4a85d2eb7
[libs/gl.git] / source / render / sequence.cpp
1 #include <msp/core/maputils.h>
2 #include "blend.h"
3 #include "framebuffer.h"
4 #include "lighting.h"
5 #include "postprocessor.h"
6 #include "renderer.h"
7 #include "sequence.h"
8 #include "texture2d.h"
9 #include "view.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace GL {
15
16 Sequence::Sequence(unsigned w, unsigned h, bool d)
17 {
18         init(w, h);
19         hdr = d;
20 }
21
22 Sequence::Sequence(const View &view)
23 {
24         init(view.get_width(), view.get_height());
25 }
26
27 Sequence::Sequence(const Framebuffer &fbo)
28 {
29         init(fbo.get_width(), fbo.get_height());
30 }
31
32 void Sequence::init(unsigned w, unsigned h)
33 {
34         width = w;
35         height = h;
36         hdr = false;
37         alpha = false;
38         samples = 0;
39         target_ms = 0;
40         target[0] = 0;
41         target[1] = 0;
42 }
43
44 Sequence::~Sequence()
45 {
46         for(vector<PostProcStep>::iterator i=postproc.begin(); i!=postproc.end(); ++i)
47                 if(i->owned)
48                         delete i->postproc;
49         delete target[0];
50         delete target[1];
51         delete target_ms;
52 }
53
54 void Sequence::set_hdr(bool h)
55 {
56         if(h==hdr)
57                 return;
58
59         bool old_hdr = hdr;
60         hdr = h;
61         try
62         {
63                 create_targets(2);
64         }
65         catch(...)
66         {
67                 hdr = old_hdr;
68                 throw;
69         }
70 }
71
72 void Sequence::set_alpha(bool a)
73 {
74         if(a==alpha)
75                 return;
76
77         bool old_alpha = alpha;
78         alpha = a;
79         try
80         {
81                 create_targets(2);
82         }
83         catch(...)
84         {
85                 alpha = old_alpha;
86                 throw;
87         }
88 }
89
90 void Sequence::set_multisample(unsigned s)
91 {
92         if(s==samples)
93                 return;
94
95         unsigned old_samples = samples;
96         samples = s;
97         try
98         {
99                 create_targets(1);
100         }
101         catch(...)
102         {
103                 samples = old_samples;
104                 throw;
105         }
106 }
107
108 Sequence::Step &Sequence::add_step(Tag tag, Renderable &r)
109 {
110         steps.push_back(Step(tag, &r));
111         return steps.back();
112 }
113
114 void Sequence::add_postprocessor(PostProcessor &pp)
115 {
116         add_postprocessor(&pp, false);
117 }
118
119 void Sequence::add_postprocessor_owned(PostProcessor *pp)
120 {
121         add_postprocessor(pp, true);
122 }
123
124 void Sequence::add_postprocessor(PostProcessor *pp, bool owned)
125 {
126         postproc.push_back(PostProcStep(pp, owned));
127         try
128         {
129                 create_targets(0);
130         }
131         catch(...)
132         {
133                 if(owned)
134                         delete pp;
135                 postproc.pop_back();
136                 throw;
137         }
138 }
139
140 void Sequence::setup_frame(Renderer &renderer)
141 {
142         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
143                 if(Renderable *renderable = i->get_renderable())
144                         renderable->setup_frame(renderer);
145 }
146
147 void Sequence::finish_frame()
148 {
149         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
150                 if(Renderable *renderable = i->get_renderable())
151                         renderable->finish_frame();
152 }
153
154 void Sequence::render(Renderer &renderer, Tag tag) const
155 {
156         if(tag.id)
157                 return;
158
159         Renderer::Push _push(renderer);
160
161         const Framebuffer *out_fbo = renderer.get_framebuffer();
162
163         if(target[0])
164         {
165                 renderer.set_framebuffer(&(samples ? target_ms : target[0])->get_framebuffer());
166                 renderer.clear();
167         }
168
169         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
170         {
171                 Renderer::Push _push2(renderer);
172
173                 renderer.set_depth_test(&i->get_depth_test());
174                 renderer.set_stencil_test(&i->get_stencil_test());
175                 renderer.set_blend(&i->get_blend());
176
177                 if (const Lighting *lighting = i->get_lighting())
178                         renderer.add_shader_data(lighting->get_shader_data());
179                 renderer.set_clipping(i->get_clipping());
180
181                 if(const Renderable *renderable = i->get_renderable())
182                         renderer.render(*renderable, i->get_tag());
183         }
184
185         if(target[0])
186         {
187                 if(samples)
188                         renderer.resolve_multisample(target[0]->get_framebuffer(), COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
189
190                 renderer.set_depth_test(0);
191                 renderer.set_stencil_test(0);
192                 renderer.set_blend(0);
193
194                 for(unsigned i=0; i<postproc.size(); ++i)
195                 {
196                         unsigned j = i%2;
197                         renderer.set_framebuffer(i+1<postproc.size() ? &target[1-j]->get_framebuffer() : out_fbo);
198                         const Texture2D &color = target[j]->get_target_texture(COLOR_ATTACHMENT);
199                         const Texture2D &depth = target[j]->get_target_texture(DEPTH_ATTACHMENT);
200                         postproc[i].postproc->render(renderer, color, depth);
201                 }
202         }
203 }
204
205 void Sequence::create_targets(unsigned recreate)
206 {
207         if(recreate>=2)
208         {
209                 delete target[0];
210                 delete target[1];
211                 target[0] = 0;
212                 target[1] = 0;
213         }
214         if(recreate>=1)
215         {
216                 delete target_ms;
217                 target_ms = 0;
218         }
219
220         PixelFormat color_pf = (hdr ? (alpha ? RGBA16F : RGB16F) : (alpha ? RGBA8 : RGB8));
221         FrameFormat fmt = (COLOR_ATTACHMENT,color_pf, DEPTH_ATTACHMENT);
222         if(!postproc.empty() || samples)
223         {
224                 if(!target[0])
225                         target[0] = new RenderTarget(width, height, fmt);
226                 if(!target[1] && postproc.size()>1)
227                         target[1] = new RenderTarget(width, height, fmt);
228         }
229
230         if(!target_ms && samples)
231                 target_ms = new RenderTarget(width, height, fmt.set_samples(samples));
232
233 #ifdef DEBUG
234         if(!debug_name.empty())
235                 set_target_debug_names();
236 #endif
237 }
238
239 void Sequence::set_debug_name(const string &name)
240 {
241 #ifdef DEBUG
242         debug_name = name;
243         if(!name.empty())
244                 set_target_debug_names();
245 #else
246         (void)name;
247 #endif
248 }
249
250 void Sequence::set_target_debug_names()
251 {
252 #ifdef DEBUG
253         for(unsigned i=0; i<2; ++i)
254                 if(target[i])
255                         target[i]->set_debug_name(format("%s [RT:%d]", debug_name, i));
256         if(target_ms)
257                 target_ms->set_debug_name(debug_name+" [RT:ms]");
258 #endif
259 }
260
261
262 Sequence::Step::Step(Tag t, Renderable *r):
263         tag(t),
264         lighting(0),
265         clipping(0),
266         renderable(r)
267 { }
268
269 void Sequence::Step::set_lighting(const Lighting *l)
270 {
271         lighting = l;
272 }
273
274 void Sequence::Step::set_depth_test(const DepthTest &dt)
275 {
276         depth_test = dt;
277 }
278
279 void Sequence::Step::set_stencil_test(const StencilTest &st)
280 {
281         stencil_test = st;
282 }
283
284 void Sequence::Step::set_blend(const Blend &b)
285 {
286         blend = b;
287 }
288
289 void Sequence::Step::set_clipping(const Clipping *c)
290 {
291         clipping = c;
292 }
293
294 } // namespace GL
295 } // namespace Msp