if scene.background_set:
content = resources[scene.name+".wrapper.scene"]
- seq_res.statements.append(Statement("clear"))
+ ss = Statement("clear")
+ ss.sub.append(Statement("color", 0.0, 0.0, 0.0, 0.0))
+ ss.sub.append(Statement("depth", 1.0))
+ seq_res.statements.append(ss)
ss = Statement("step", "", "content")
ss.sub.append(Statement("depth_test", Token("LEQUAL")))
--- /dev/null
+extension MSP_clear_buffer
</require>
</extension>
+ <!-- The targeted clear commands were introduced directly to OpenGL 3.0
+ without an extension. -->
+ <extension name="GL_MSP_clear_buffer" supported="gl">
+ <require>
+ <command name="glClearBufferfi" />
+ <command name="glClearBufferfv" />
+ <command name="glClearBufferiv" />
+ <command name="glClearBufferuiv" />
+ </require>
+ </extension>
+
<extension name="GL_MSP_luminance_formats" supported="gl">
<require>
<enum name="GL_LUMINANCE" />
#endif
sequence.set_clear_enabled(tmpl.is_clear_enabled());
+ if(tmpl.is_clear_enabled())
+ {
+ sequence.set_clear_colors(tmpl.get_clear_colors());
+ sequence.set_clear_depth(tmpl.get_clear_depth());
+ sequence.set_clear_stencil(tmpl.get_clear_stencil());
+ }
for(const SequenceTemplate::Step &s: tmpl.get_steps())
{
alpha(false),
required_multisample(0),
max_multisample(0),
- clear_enabled(false)
+ clear_enabled(false),
+ clear_depth(1.0f),
+ clear_stencil(0)
{ }
SequenceTemplate::~SequenceTemplate()
void SequenceTemplate::Loader::clear()
{
+ ClearLoader ldr(obj);
+ load_sub_with(ldr);
obj.clear_enabled = true;
}
}
+SequenceTemplate::ClearLoader::ClearLoader(SequenceTemplate &t):
+ ObjectLoader<SequenceTemplate>(t)
+{
+ add("color", &ClearLoader::color);
+ add("depth", &ClearLoader::depth);
+ add("stencil", &ClearLoader::stencil);
+}
+
+void SequenceTemplate::ClearLoader::color(float r, float g, float b, float a)
+{
+ obj.clear_colors.push_back(Color(r, g, b, a));
+}
+
+void SequenceTemplate::ClearLoader::depth(float d)
+{
+ obj.clear_depth = d;
+}
+
+void SequenceTemplate::ClearLoader::stencil(int s)
+{
+ obj.clear_stencil = s;
+}
+
+
SequenceTemplate::Step::Loader::Loader(Step &p):
DataFile::CollectionObjectLoader<Step>(p, 0)
{
};
private:
+ class ClearLoader: public DataFile::ObjectLoader<SequenceTemplate>
+ {
+ public:
+ ClearLoader(SequenceTemplate &);
+
+ private:
+ void color(float, float, float, float);
+ void depth(float);
+ void stencil(int);
+ };
+
typedef TypeRegistry<PostProcLoader::AddPostProc, PostProcLoader &> PostProcessorRegistry;
bool hdr;
std::vector<Step> steps;
std::vector<PostProcessor> postprocessors;
bool clear_enabled;
+ std::vector<Color> clear_colors;
+ float clear_depth;
+ int clear_stencil;
public:
SequenceTemplate();
const std::vector<Step> &get_steps() const { return steps; }
const std::vector<PostProcessor> &get_postprocessors() const { return postprocessors; }
bool is_clear_enabled() const { return clear_enabled; }
+ const std::vector<Color> &get_clear_colors() const { return clear_colors; }
+ float get_clear_depth() const { return clear_depth; }
+ int get_clear_stencil() const { return clear_stencil; }
template<typename T>
static void register_postprocessor(const std::string &);
#include <msp/gl/extensions/arb_draw_instanced.h>
#include <msp/gl/extensions/ext_framebuffer_blit.h>
#include <msp/gl/extensions/ext_framebuffer_object.h>
+#include <msp/gl/extensions/msp_clear_buffer.h>
#include "batch.h"
#include "commands.h"
+#include "error.h"
#include "gl.h"
#include "pipelinestate.h"
pipeline_state = &ps;
}
-void Commands::clear(BufferBits buffers)
+void Commands::clear(const ClearValue *values)
{
- pipeline_state->apply();
- glClear(buffers);
+ const Framebuffer *target = pipeline_state->get_framebuffer();
+ if(!target)
+ throw invalid_operation("OpenGLCommands::clear");
+
+ if(!ARB_direct_state_access)
+ {
+ static Require _req(MSP_clear_buffer);
+ pipeline_state->apply();
+ }
+
+ unsigned i = 0;
+ for(FrameAttachment a: target->get_format())
+ {
+ if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferfv(target->id, GL_DEPTH, 0, &values->depth_stencil.depth);
+ else
+ glClearBufferfv(GL_DEPTH, 0, &values->depth_stencil.depth);
+ }
+ else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferiv(target->id, GL_STENCIL, 0, &values->depth_stencil.stencil);
+ else
+ glClearBufferiv(GL_STENCIL, 0, &values->depth_stencil.stencil);
+ }
+ else
+ {
+ if(ARB_direct_state_access)
+ glClearNamedFramebufferfv(target->id, GL_COLOR, i++, &values->color.r);
+ else
+ glClearBufferfv(GL_COLOR, i++, &values->color.r);
+ }
+ ++values;
+ }
}
void Commands::draw(const Batch &batch)
Commands();
void use_pipeline(const PipelineState &);
- void clear(BufferBits);
+ void clear(const ClearValue *);
void draw(const Batch &);
void draw_instanced(const Batch &, unsigned);
void resolve_multisample(Framebuffer &, BufferBits);
#define MSP_GL_FRAMEBUFFER_H_
#include <vector>
+#include "color.h"
#include "frameformat.h"
#include "gl.h"
#include "texturecube.h"
static Framebuffer &system();
};
+
+union ClearValue
+{
+ Color color;
+ struct
+ {
+ float depth;
+ int stencil;
+ } depth_stencil;
+
+ ClearValue(): color(0.0f, 0.0f, 0.0f, 0.0f) { }
+};
+
inline BufferBits operator|(BufferBits a, BufferBits b)
{ return static_cast<BufferBits>(static_cast<int>(a)|static_cast<int>(b)); }
renderable.render(*this, tag);
}
-void Renderer::clear()
-{
- clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT|STENCIL_BUFFER_BIT);
-}
-
-void Renderer::clear(BufferBits buffers)
+void Renderer::clear(const ClearValue *values)
{
pipeline_state.set_framebuffer(state->framebuffer);
- commands.clear(buffers);
+ commands.clear(values);
}
void Renderer::draw(const Batch &batch)
void exclude(const Renderable &);
void include(const Renderable &);
- void clear();
- void clear(BufferBits);
+ void clear(const ClearValue *);
void render(const Renderable &, Tag = Tag());
void draw(const Batch &);
height(0),
target{0, 0},
target_ms(0),
- clear_enabled(false)
+ clear_enabled(false),
+ clear_depth(1.0f),
+ clear_stencil(0)
{ }
Sequence::Sequence(unsigned w, unsigned h, const FrameFormat &f):
height(h),
target_format(f),
target_ms(0),
- clear_enabled(false)
+ clear_enabled(false),
+ clear_depth(1.0f),
+ clear_stencil(0)
{
if(target_format.empty())
throw invalid_argument("Sequence::Sequence");
clear_enabled = c;
}
+void Sequence::set_clear_colors(const vector<Color> &c)
+{
+ clear_enabled = true;
+ clear_colors = c;
+}
+
+void Sequence::set_clear_depth(float d)
+{
+ clear_enabled = true;
+ clear_depth = d;
+}
+
+void Sequence::set_clear_stencil(int s)
+{
+ clear_enabled = true;
+ clear_stencil = s;
+}
+
Sequence::Step &Sequence::add_step(Tag tag, Renderable &r)
{
steps.push_back(Step(tag, &r));
renderer.set_framebuffer(&(target_ms ? target_ms : target[0])->get_framebuffer());
if(clear_enabled)
- renderer.clear();
+ {
+ const Framebuffer *target_fbo = renderer.get_framebuffer();
+ if(!target_fbo)
+ throw invalid_operation("Sequence::render");
+
+ const FrameFormat &format = target_fbo->get_format();
+ ClearValue clear_values[7];
+ unsigned i = 0;
+ Color default_color = (clear_colors.empty() ? Color(0.0f, 0.0f, 0.0f, 0.0f) : clear_colors.front());
+ ClearValue *cv = clear_values;
+ for(FrameAttachment a: format)
+ {
+ if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
+ cv->depth_stencil.depth = clear_depth;
+ else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
+ cv->depth_stencil.stencil = clear_stencil;
+ else
+ cv->color = (i<clear_colors.size() ? clear_colors[i++] : default_color);
+ ++cv;
+ }
+
+ renderer.clear(clear_values);
+ }
for(const Step &s: steps)
{
RenderTarget *target[2];
RenderTarget *target_ms;
bool clear_enabled;
+ std::vector<Color> clear_colors;
+ float clear_depth;
+ int clear_stencil;
public:
Sequence();
const FrameFormat &get_target_format() { return target_format; }
void set_clear_enabled(bool);
+ void set_clear_colors(const std::vector<Color> &);
+ void set_clear_depth(float);
+ void set_clear_stencil(int);
/** Adds a step to the sequence. It's permissible to add the same
Renderable multiple times. */