+ }
+
+ if(!was_in_frame)
+ finish_frame();
+}
+
+void Pipeline::create_targets(bool recreate)
+{
+ if(recreate)
+ {
+ delete target[0];
+ delete target[1];
+ delete target_ms;
+ target[0] = 0;
+ target[1] = 0;
+ target_ms = 0;
+ }
+
+ PixelFormat fmt = (hdr ? RGB16F : RGB);
+ if(!target[0])
+ target[0] = new RenderTarget(width, height, fmt);
+ if(!target[1] && postproc.size()>1)
+ target[1] = new RenderTarget(width, height, fmt);
+
+ if(!target_ms && samples)
+ target_ms = new MultisampleTarget(width, height, samples, fmt);
+}
+
+
+Pipeline::Pass::Pass(const Tag &t):
+ tag(t),
+ lighting(0),
+ depth_test(0),
+ blend(0)
+{ }
+
+void Pipeline::Pass::set_lighting(const Lighting *l)
+{
+ lighting = l;
+}
+
+void Pipeline::Pass::set_depth_test(const DepthTest *d)
+{
+ depth_test = d;
+}
+
+void Pipeline::Pass::set_blend(const Blend *b)
+{
+ blend = b;
+}
+
+
+Pipeline::Slot::Slot(const Renderable *r):
+ renderable(r)
+{ }
+
+
+Pipeline::RenderTarget::RenderTarget(unsigned w, unsigned h, PixelFormat f)
+{
+ color.set_min_filter(NEAREST);
+ color.set_mag_filter(NEAREST);
+ color.set_wrap(CLAMP_TO_EDGE);
+ color.storage(f, w, h);
+ fbo.attach(COLOR_ATTACHMENT0, color, 0);
+
+ depth.set_min_filter(NEAREST);
+ depth.set_mag_filter(NEAREST);
+ depth.set_wrap(CLAMP_TO_EDGE);
+ depth.storage(DEPTH_COMPONENT, w, h);
+ fbo.attach(DEPTH_ATTACHMENT, depth, 0);
+}
+
+
+Pipeline::MultisampleTarget::MultisampleTarget(unsigned w, unsigned h, unsigned s, PixelFormat f)
+{
+ color.storage_multisample(s, f, w, h);
+ fbo.attach(COLOR_ATTACHMENT0, color);