3 This file is part of libmspgl
4 Copyright © 2009-2011 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
12 #include "framebuffer.h"
15 #include "postprocessor.h"
16 #include "renderbuffer.h"
19 #include "texture2d.h"
26 Pipeline::Pipeline(unsigned w, unsigned h, bool d):
47 void Pipeline::set_hdr(bool h)
54 void Pipeline::set_multisample(unsigned s)
61 void Pipeline::set_camera(const Camera *c)
66 PipelinePass &Pipeline::add_pass(const Tag &tag)
69 throw KeyError("Pass already exists");
71 PipelinePass &pass = passes[tag];
72 pass_order.push_back(tag);
76 PipelinePass &Pipeline::get_pass(const Tag &tag)
78 PassMap::iterator i = passes.find(tag);
80 throw KeyError("Unknown pass");
84 const PipelinePass &Pipeline::get_pass(const Tag &tag) const
86 PassMap::const_iterator i = passes.find(tag);
88 throw KeyError("Unknown pass");
92 void Pipeline::add_renderable(const Renderable &r)
94 for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
101 renderables.push_back(&r);
104 void Pipeline::add_renderable_for_pass(const Renderable &r, const Tag &tag)
106 for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
107 if(i->renderable==&r)
109 i->passes.insert(tag);
113 renderables.push_back(&r);
114 renderables.back().passes.insert(tag);
117 void Pipeline::remove_renderable(const Renderable &r)
119 for(vector<Slot>::iterator i=renderables.begin(); i!=renderables.end(); ++i)
120 if(i->renderable==&r)
122 renderables.erase(i);
127 void Pipeline::add_effect(Effect &e)
129 effects.push_back(&e);
132 void Pipeline::add_postprocessor(PostProcessor &pp)
134 postproc.push_back(&pp);
141 void Pipeline::render(Renderer &renderer, const Tag &tag) const
143 const PipelinePass &pass = get_pass(tag);
145 Bind bind_depth_test(pass.depth_test);
146 Bind bind_blend(pass.blend);
147 Bind bind_lighting(pass.lighting);
149 for(vector<Effect *>::const_iterator i=pass.effects.begin(); i!=pass.effects.end(); ++i)
152 for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
153 if(i->passes.empty() || i->passes.count(tag))
154 i->renderable->render(renderer, tag);
156 for(vector<Effect *>::const_iterator i=pass.effects.end(); i!=pass.effects.begin();)
160 void Pipeline::render_all() const
167 Framebuffer *f = (fbo_ms ? fbo_ms : fbo);
169 f->clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
172 for(vector<Effect *>::const_iterator i=effects.begin(); i!=effects.end(); ++i)
175 Renderer renderer(camera);
176 for(vector<Tag>::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i)
177 render(renderer, *i);
179 for(vector<Effect *>::const_iterator i=effects.end(); i!=effects.begin();)
185 fbo->blit_from(*fbo_ms, COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT, false);
186 Framebuffer::unbind();
189 // XXX Need two color buffer textures to handle multiple post-processors correctly
190 for(vector<PostProcessor *>::const_iterator i=postproc.begin(); i!=postproc.end(); ++i)
191 (*i)->render(*color_buf, *depth_buf);
194 void Pipeline::create_fbos()
207 fbo = new Framebuffer;
209 color_buf = new Texture2D;
210 color_buf->set_min_filter(NEAREST);
211 color_buf->set_mag_filter(NEAREST);
212 color_buf->set_wrap(CLAMP_TO_EDGE);
213 color_buf->storage((hdr ? RGB16F : RGB), width, height);
214 fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0);
216 depth_buf = new Texture2D;
217 depth_buf->set_min_filter(NEAREST);
218 depth_buf->set_mag_filter(NEAREST);
219 depth_buf->set_wrap(CLAMP_TO_EDGE);
220 depth_buf->storage(DEPTH_COMPONENT, width, height);
221 fbo->attach(DEPTH_ATTACHMENT, *depth_buf, 0);
225 fbo_ms = new Framebuffer;
227 color_buf_ms = new Renderbuffer;
228 color_buf_ms->storage_multisample(samples, (hdr ? RGB16F : RGB), width, height);
229 fbo_ms->attach(COLOR_ATTACHMENT0, *color_buf_ms);
231 depth_buf_ms = new Renderbuffer;
232 depth_buf_ms->storage_multisample(samples, DEPTH_COMPONENT, width, height);
233 fbo_ms->attach(DEPTH_ATTACHMENT, *depth_buf_ms);
238 Pipeline::Slot::Slot(const Renderable *r):