sequence.set_debug_name(debug_name);
#endif
- sequence.set_hdr(tmpl.get_hdr());
- sequence.set_alpha(tmpl.get_alpha());
- unsigned samples = min(tmpl.get_maximum_multisample(), Limits::get_global().max_samples);
- if(samples<tmpl.get_required_multisample())
- throw invalid_operation("SequenceBuilder::build");
-
- sequence.set_multisample(samples);
-
const vector<SequenceTemplate::Step> &steps = tmpl.get_steps();
for(vector<SequenceTemplate::Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
{
Sequence *SequenceBuilder::build(unsigned w, unsigned h) const
{
- RefPtr<Sequence> sequence = new Sequence(w, h);
+ RefPtr<Sequence> sequence = new Sequence(w, h, create_frame_format());
build(*sequence);
return sequence.release();
}
Sequence *SequenceBuilder::build(const View &view) const
{
- RefPtr<Sequence> sequence = new Sequence(view);
+ RefPtr<Sequence> sequence = new Sequence(view, create_frame_format());
build(*sequence);
return sequence.release();
}
Sequence *SequenceBuilder::build(const Framebuffer &fbo) const
{
- RefPtr<Sequence> sequence = new Sequence(fbo);
+ RefPtr<Sequence> sequence = new Sequence(fbo, create_frame_format());
build(*sequence);
return sequence.release();
}
+FrameFormat SequenceBuilder::create_frame_format() const
+{
+ unsigned samples = min(tmpl.get_maximum_multisample(), Limits::get_global().max_samples);
+ if(samples<tmpl.get_required_multisample())
+ throw invalid_operation("SequenceBuilder::create_frame_format");
+
+ PixelComponents color_comp = (tmpl.get_alpha() ? RGBA : RGB);
+ DataType color_type = (tmpl.get_hdr() ? HALF_FLOAT : UNSIGNED_BYTE);
+ PixelFormat color_pf = make_pixelformat(color_comp, color_type);
+
+ return (COLOR_ATTACHMENT,color_pf, DEPTH_ATTACHMENT).set_samples(samples);
+}
+
} // namespace GL
} // namespace Msp
#include <msp/core/maputils.h>
#include "blend.h"
+#include "error.h"
#include "framebuffer.h"
#include "lighting.h"
#include "postprocessor.h"
namespace Msp {
namespace GL {
-Sequence::Sequence(unsigned w, unsigned h, bool d)
+Sequence::Sequence(unsigned w, unsigned h, const FrameFormat &f)
{
- init(w, h);
- hdr = d;
+ init(w, h, f);
}
-Sequence::Sequence(const View &view)
+Sequence::Sequence(const View &view, const FrameFormat &f)
{
- init(view.get_width(), view.get_height());
+ init(view.get_width(), view.get_height(), f);
}
-Sequence::Sequence(const Framebuffer &fbo)
+Sequence::Sequence(const Framebuffer &fbo, const FrameFormat &f)
{
- init(fbo.get_width(), fbo.get_height());
+ init(fbo.get_width(), fbo.get_height(), f);
}
-void Sequence::init(unsigned w, unsigned h)
+void Sequence::init(unsigned w, unsigned h, const FrameFormat &f)
{
width = w;
height = h;
- hdr = false;
- alpha = false;
- samples = 0;
- target_ms = 0;
- target[0] = 0;
- target[1] = 0;
+ target_format = f;
+
+ if(!target_format.empty())
+ {
+ FrameFormat postproc_fmt = target_format;
+ postproc_fmt.set_samples(1);
+ target[0] = new RenderTarget(width, height, postproc_fmt);
+ target[1] = new RenderTarget(width, height, postproc_fmt);
+
+ if(target_format.get_samples()>1)
+ target_ms = new RenderTarget(width, height, target_format);
+ else
+ target_ms = 0;
+ }
+ else
+ {
+ target_ms = 0;
+ target[0] = 0;
+ target[1] = 0;
+ }
}
Sequence::~Sequence()
delete target_ms;
}
-void Sequence::set_hdr(bool h)
-{
- if(h==hdr)
- return;
-
- bool old_hdr = hdr;
- hdr = h;
- try
- {
- create_targets(2);
- }
- catch(...)
- {
- hdr = old_hdr;
- throw;
- }
-}
-
-void Sequence::set_alpha(bool a)
-{
- if(a==alpha)
- return;
-
- bool old_alpha = alpha;
- alpha = a;
- try
- {
- create_targets(2);
- }
- catch(...)
- {
- alpha = old_alpha;
- throw;
- }
-}
-
-void Sequence::set_multisample(unsigned s)
-{
- if(s==samples)
- return;
-
- unsigned old_samples = samples;
- samples = s;
- try
- {
- create_targets(1);
- }
- catch(...)
- {
- samples = old_samples;
- throw;
- }
-}
-
Sequence::Step &Sequence::add_step(Tag tag, Renderable &r)
{
steps.push_back(Step(tag, &r));
void Sequence::add_postprocessor(PostProcessor *pp, bool owned)
{
- postproc.push_back(PostProcStep(pp, owned));
- try
- {
- create_targets(0);
- }
- catch(...)
+ if(target_format.empty())
{
if(owned)
delete pp;
- postproc.pop_back();
- throw;
+ throw invalid_operation("Sequence::add_postprocessor");
}
+ postproc.push_back(PostProcStep(pp, owned));
}
void Sequence::setup_frame(Renderer &renderer)
if(target[0])
{
- renderer.set_framebuffer(&(samples ? target_ms : target[0])->get_framebuffer());
+ renderer.set_framebuffer(&(target_ms ? target_ms : target[0])->get_framebuffer());
renderer.clear();
}
if(target[0])
{
- if(samples)
+ if(target_ms)
renderer.resolve_multisample(target[0]->get_framebuffer(), COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
renderer.set_depth_test(0);
}
}
-void Sequence::create_targets(unsigned recreate)
-{
- if(recreate>=2)
- {
- delete target[0];
- delete target[1];
- target[0] = 0;
- target[1] = 0;
- }
- if(recreate>=1)
- {
- delete target_ms;
- target_ms = 0;
- }
-
- PixelFormat color_pf = (hdr ? (alpha ? RGBA16F : RGB16F) : (alpha ? RGBA8 : RGB8));
- FrameFormat fmt = (COLOR_ATTACHMENT,color_pf, DEPTH_ATTACHMENT);
- if(!postproc.empty() || samples)
- {
- 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 RenderTarget(width, height, fmt.set_samples(samples));
-
-#ifdef DEBUG
- if(!debug_name.empty())
- set_target_debug_names();
-#endif
-}
-
void Sequence::set_debug_name(const string &name)
{
-#ifdef DEBUG
- debug_name = name;
- if(!name.empty())
- set_target_debug_names();
-#else
- (void)name;
-#endif
-}
-
-void Sequence::set_target_debug_names()
-{
#ifdef DEBUG
for(unsigned i=0; i<2; ++i)
if(target[i])
- target[i]->set_debug_name(format("%s [RT:%d]", debug_name, i));
+ target[i]->set_debug_name(format("%s [RT:%d]", name, i));
if(target_ms)
- target_ms->set_debug_name(debug_name+" [RT:ms]");
+ target_ms->set_debug_name(name+" [RT:ms]");
+#else
+ (void)name;
#endif
}
std::vector<PostProcStep> postproc;
unsigned width;
unsigned height;
- bool hdr;
- bool alpha;
- unsigned samples;
+ FrameFormat target_format;
RenderTarget *target[2];
RenderTarget *target_ms;
- std::string debug_name;
public:
- Sequence(unsigned, unsigned, bool = false);
- Sequence(const View &);
- Sequence(const Framebuffer &);
+ Sequence(unsigned, unsigned, const FrameFormat & = FrameFormat());
+ Sequence(const View &, const FrameFormat & = FrameFormat());
+ Sequence(const Framebuffer &, const FrameFormat & = FrameFormat());
private:
- void init(unsigned, unsigned);
+ void init(unsigned, unsigned, const FrameFormat &);
public:
~Sequence();
- /* Sets high dynamic range mode. Requires floating-point texture support.
- A ColorCurve postprocessor is recommended for full benefit. */
- void set_hdr(bool);
-
- /* Enable or disable alpha channel. When enabled, all render targets are
- created with an RGBA pixel format instead of RGB. */
- void set_alpha(bool);
-
- void set_multisample(unsigned);
+ const FrameFormat &get_target_format() { return target_format; }
unsigned get_width() const { return width; }
unsigned get_height() const { return height; }
- bool get_hdr() const { return hdr; }
- unsigned get_multisample() const { return samples; }
/** Adds a step to the sequence. It's permissible to add the same
Renderable multiple times. */
virtual void render(Renderer &, Tag tag = Tag()) const;
-private:
- void create_targets(unsigned);
-
-public:
void set_debug_name(const std::string &);
-private:
- void set_target_debug_names();
};
} // namespace GL