Make it possible to specify explicit clear values
authorMikko Rasa <tdb@tdb.fi>
Sat, 25 Sep 2021 11:06:53 +0000 (14:06 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 25 Sep 2021 11:22:45 +0000 (14:22 +0300)
13 files changed:
blender/io_mspgl/export_scene.py
extensions/msp_clear_buffer.glext [new file with mode: 0644]
gl.msp.xml
source/builders/sequencebuilder.cpp
source/builders/sequencetemplate.cpp
source/builders/sequencetemplate.h
source/core/commands.cpp
source/core/commands.h
source/core/framebuffer.h
source/render/renderer.cpp
source/render/renderer.h
source/render/sequence.cpp
source/render/sequence.h

index 0f1d1935601504fd7bbd59b372754579b064482e..0ad6769f1dedb0daa1230aa131d0fed229f11db2 100644 (file)
@@ -118,7 +118,10 @@ class SceneExporter:
                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")))
diff --git a/extensions/msp_clear_buffer.glext b/extensions/msp_clear_buffer.glext
new file mode 100644 (file)
index 0000000..fc4f110
--- /dev/null
@@ -0,0 +1 @@
+extension MSP_clear_buffer
index 7895a806ae486559e873c77885a57f7b3f591045..f406bc77b54a44a45a315fbf6dd00b0cfdc8a608 100644 (file)
             </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" />
index 6e87081d4ab5805d8173240eba3ca0b800331045..a614a836a5c4d15ee52770f4861e7063ed7fe1e1 100644 (file)
@@ -50,6 +50,12 @@ void SequenceBuilder::build(Sequence &sequence) const
 #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())
        {
index 83c4b7671f75234b42125b30509dff9e1bde2371..6e50c24838aafeebd751008a10e7e36d40022ec9 100644 (file)
@@ -20,7 +20,9 @@ SequenceTemplate::SequenceTemplate():
        alpha(false),
        required_multisample(0),
        max_multisample(0),
-       clear_enabled(false)
+       clear_enabled(false),
+       clear_depth(1.0f),
+       clear_stencil(0)
 { }
 
 SequenceTemplate::~SequenceTemplate()
@@ -83,6 +85,8 @@ void SequenceTemplate::Loader::postprocessor_loaded()
 
 void SequenceTemplate::Loader::clear()
 {
+       ClearLoader ldr(obj);
+       load_sub_with(ldr);
        obj.clear_enabled = true;
 }
 
@@ -131,6 +135,30 @@ void SequenceTemplate::Loader::step_with_slot(const string &tag, const string &r
 }
 
 
+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)
 {
index 660a043297bb2f8046c283bf6954ae538d620f09..81a130ef40a04947ceeb1c4e22b143671878890c 100644 (file)
@@ -110,6 +110,17 @@ public:
        };
 
 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;
@@ -119,6 +130,9 @@ private:
        std::vector<Step> steps;
        std::vector<PostProcessor> postprocessors;
        bool clear_enabled;
+       std::vector<Color> clear_colors;
+       float clear_depth;
+       int clear_stencil;
 
 public:
        SequenceTemplate();
@@ -131,6 +145,9 @@ public:
        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 &);
index 529cd3921fa5ef0243a6a78a6ffe2be6c1f6654d..2eb4659ad8e6ae0f62ecb2ec2e9aed362dc6afc3 100644 (file)
@@ -3,8 +3,10 @@
 #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"
 
@@ -22,10 +24,44 @@ void Commands::use_pipeline(const PipelineState &ps)
        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)
index ec3281a09ae656d9cb610a80c121e72545ab90cc..08fdbffd89223a7cda3648a18f2e8a97c85138cf 100644 (file)
@@ -18,7 +18,7 @@ public:
        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);
index acb0d3ee918b5fa946549fc12484027fc9a26505..48888459da363f7b24be4e7edd25aecbc0d00a8f 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_GL_FRAMEBUFFER_H_
 
 #include <vector>
+#include "color.h"
 #include "frameformat.h"
 #include "gl.h"
 #include "texturecube.h"
@@ -128,6 +129,19 @@ public:
        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)); }
 
index 6f7e9cba34d3c156a50e255372d0c59d078e8da9..aa6c9b55a4d4206ef458012e280efdacb3e9aba5 100644 (file)
@@ -243,15 +243,10 @@ void Renderer::render(const Renderable &renderable, Tag tag)
                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)
index ff2c2a2fb49207de2dc7c236563d5365d4eb3d79..8026f5ab8770429981c399b5f2482656756717fe 100644 (file)
@@ -195,8 +195,7 @@ public:
        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 &);
index 254a6c462abcbdc01aa232a104c05cf5380db269..7a964c870d39e2bbe40a9cbf4a2571d1e1f40843 100644 (file)
@@ -18,7 +18,9 @@ Sequence::Sequence():
        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):
@@ -26,7 +28,9 @@ 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");
@@ -55,6 +59,24 @@ void Sequence::set_clear_enabled(bool c)
        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));
@@ -109,7 +131,29 @@ void Sequence::render(Renderer &renderer, Tag tag) const
                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)
        {
index 061b04de3406a60b78c883f11a7b9ad2e2740666..cfd14942e9de044bd5e33af8dc99e43470caf96d 100644 (file)
@@ -83,6 +83,9 @@ private:
        RenderTarget *target[2];
        RenderTarget *target_ms;
        bool clear_enabled;
+       std::vector<Color> clear_colors;
+       float clear_depth;
+       int clear_stencil;
 
 public:
        Sequence();
@@ -94,6 +97,9 @@ public:
        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. */