From 5ffb45d7c8cbb108f59cbc912bd9cc1a5d5565f1 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 13 Jun 2017 19:19:33 +0200 Subject: [PATCH 01/33] Intermediate commit to establish rendertarget interfaces in favor of framebuffer interfaces --- .../stages/MultiFrameAggregationStage.h | 32 ++--- .../stages/MultiFrameAggregationStage.cpp | 102 +++------------- source/gloperate/CMakeLists.txt | 2 - .../gloperate/rendering/RenderTarget.h | 69 +++++++++++ .../include/gloperate/stages/base/BlitStage.h | 19 ++- .../gloperate/stages/base/FramebufferStage.h | 94 --------------- .../source/rendering/RenderTarget.cpp | 53 +++++---- .../source/stages/base/BlitStage.cpp | 48 +++++--- .../source/stages/base/FramebufferStage.cpp | 109 ------------------ 9 files changed, 175 insertions(+), 353 deletions(-) delete mode 100644 source/gloperate/include/gloperate/stages/base/FramebufferStage.h delete mode 100644 source/gloperate/source/stages/base/FramebufferStage.cpp diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h index b705843b..e12d172c 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h @@ -6,16 +6,12 @@ #include -#include -#include -#include -#include #include -#include #include #include #include +#include #include @@ -36,7 +32,7 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag , "" , "" , "" - , "Stage that aggregates multiple subsequent frames into a single framebuffer" + , "Stage that aggregates multiple subsequent frames into a single texture" , GLOPERATE_AUTHOR_ORGANIZATION , "v0.1.0" ) @@ -44,14 +40,13 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag public: // Inputs - Input aggregationFBO; ///< FBO to aggregate into - Input texture; ///< New frame to add to aggregation - Input textureRerendered; ///< Add texture to aggregation? - Input viewport; ///< Target viewport - Input aggregationFactor; ///< Weight of new frame in current aggregation + Input sourceTexture; ///< Current frame texture + Input targetTexture; ///< Aggregation target texture + Input viewport; ///< Target viewport + Input aggregationFactor; ///< Weight of new frame in current aggregation // Outputs - Output aggregatedFBO; ///< Framebuffer containing aggregation + Output aggregatedTexture; ///< Aggregation target texture (passed for stage chaining) public: @@ -76,20 +71,13 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag protected: // Virtual Stage interface virtual void onContextInit(gloperate::AbstractGLContext * context) override; + virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; virtual void onProcess() override; - // Helper functions - void setupGeometry(); - void setupProgram(); - - protected: // Data - std::unique_ptr m_vao; ///< VAO for screen aligned quad - std::unique_ptr m_vertexBuffer; ///< VBO for screen aligned quad - std::unique_ptr m_vertexShader; ///< Vertex shader - std::unique_ptr m_fragmentShader; ///< Fragment shader - std::unique_ptr m_program; ///< Shader program used for aggregation + std::unique_ptr m_triangle; ///< Screen-aligned Triangle for 'blitting' + std::unique_ptr m_fbo; ///< Framebuffer for render targets }; diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp index abc2b00c..bc55d969 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp @@ -12,43 +12,6 @@ #include -static const std::array s_vertices { { - glm::vec2( +1.f, -1.f ), - glm::vec2( +1.f, +1.f ), - glm::vec2( -1.f, -1.f ), - glm::vec2( -1.f, +1.f ) } }; - -static const char * s_vertexShader = R"( - #version 140 - #extension GL_ARB_explicit_attrib_location : require - - layout (location = 0) in vec2 a_vertex; - out vec2 v_uv; - - void main() - { - v_uv = a_vertex * 0.5 + 0.5; - gl_Position = vec4(a_vertex, 0.0, 1.0); - } -)"; - -static const char * s_fragmentShader = R"( - #version 140 - #extension GL_ARB_explicit_attrib_location : require - - uniform sampler2D tex; - - layout (location = 0) out vec4 fragColor; - - in vec2 v_uv; - - void main() - { - fragColor = texture(tex, v_uv); - } -)"; - - namespace gloperate_glkernel { @@ -58,12 +21,11 @@ CPPEXPOSE_COMPONENT(MultiFrameAggregationStage, gloperate::Stage) MultiFrameAggregationStage::MultiFrameAggregationStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, name) -, aggregationFBO("aggregationFBO", this) -, texture("texture", this) -, textureRerendered("textureRerendered", this) +, sourceTexture("sourceTexture", this) +, targetTexture("targetTexture", this) , viewport("viewport", this) , aggregationFactor("aggregationFactor", this) -, aggregatedFBO("aggregatedFBO", this) +, aggregatedTexture("aggregatedTexture", this) { } @@ -73,15 +35,18 @@ MultiFrameAggregationStage::~MultiFrameAggregationStage() void MultiFrameAggregationStage::onContextInit(gloperate::AbstractGLContext * /*context*/) { - setupGeometry(); - setupProgram(); + m_triangle = cppassist::make_unique(); + m_fbo = cppassist::make_unique(); } -void MultiFrameAggregationStage::onProcess() +void MultiFrameAggregationStage::onContextDeinit(gloperate::AbstractGLContext * /*context*/) { - if (!(*texture)) - return; + m_triangle = nullptr; + m_fbo = nullptr; +} +void MultiFrameAggregationStage::onProcess() +{ gl::glViewport( 0, // Origin (0,0) because content was already shifted in main render pass 0, // Applying the origin again would shift the result again @@ -89,56 +54,19 @@ void MultiFrameAggregationStage::onProcess() (*viewport).w ); - globjects::Framebuffer * fbo = *aggregationFBO; - fbo->bind(gl::GL_FRAMEBUFFER); + m_fbo->bind(gl::GL_FRAMEBUFFER); - (*texture)->bindActive(0); gl::glBlendColor(0.0f, 0.0f, 0.0f, *aggregationFactor); gl::glBlendFunc(gl::GL_CONSTANT_ALPHA, gl::GL_ONE_MINUS_CONSTANT_ALPHA); gl::glBlendEquation(gl::GL_FUNC_ADD); gl::glEnable(gl::GL_BLEND); - gl::glDisable(gl::GL_DEPTH_TEST); - m_program->use(); - m_vao->drawArrays(gl::GL_TRIANGLE_STRIP, 0, 4); - m_program->release(); + m_triangle->setTexture(*sourceTexture); + m_triangle->draw(); gl::glDisable(gl::GL_BLEND); - gl::glEnable(gl::GL_DEPTH_TEST); - - aggregatedFBO.setValue(*aggregationFBO); -} - -void MultiFrameAggregationStage::setupGeometry() -{ - m_vao = cppassist::make_unique(); - m_vertexBuffer = cppassist::make_unique(); - m_vertexBuffer->setData(s_vertices, gl::GL_STATIC_DRAW); - - auto binding = m_vao->binding(0); - binding->setAttribute(0); - binding->setBuffer(m_vertexBuffer.get(), 0, sizeof(glm::vec2)); - binding->setFormat(2, gl::GL_FLOAT, gl::GL_FALSE, 0); - m_vao->enable(0); -} - -void MultiFrameAggregationStage::setupProgram() -{ - //TODO this is a memory leak! Use resource loader? - globjects::StringTemplate * vertexShaderSource = new globjects::StringTemplate(new globjects::StaticStringSource(s_vertexShader )); - globjects::StringTemplate * fragmentShaderSource = new globjects::StringTemplate(new globjects::StaticStringSource(s_fragmentShader)); - -#ifdef __APPLE__ - vertexShaderSource ->replace("#version 140", "#version 150"); - fragmentShaderSource->replace("#version 140", "#version 150"); -#endif - - m_vertexShader = cppassist::make_unique(gl::GL_VERTEX_SHADER, vertexShaderSource); - m_fragmentShader = cppassist::make_unique(gl::GL_FRAGMENT_SHADER, fragmentShaderSource); - m_program = cppassist::make_unique(); - m_program->attach(m_vertexShader.get(), m_fragmentShader.get()); - m_program->setUniform("tex", 0); + aggregatedTexture.setValue(*targetTexture); } diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 9bd17ce3..93fcafbc 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -116,7 +116,6 @@ set(headers ${include_path}/stages/interfaces/RenderInterface.h ${include_path}/stages/base/BasicFramebufferStage.h - ${include_path}/stages/base/FramebufferStage.h ${include_path}/stages/base/TextureStage.h ${include_path}/stages/base/TextureLoadStage.h ${include_path}/stages/base/BlitStage.h @@ -214,7 +213,6 @@ set(sources ${source_path}/stages/base/RasterizationStage.cpp ${source_path}/stages/base/ClearStage.cpp ${source_path}/stages/base/ProgramStage.cpp - ${source_path}/stages/base/FramebufferStage.cpp ${source_path}/stages/base/TextureStage.cpp ${source_path}/stages/base/TextureLoadStage.cpp ${source_path}/stages/base/BlitStage.cpp diff --git a/source/gloperate/include/gloperate/rendering/RenderTarget.h b/source/gloperate/include/gloperate/rendering/RenderTarget.h index c1891a74..80344953 100644 --- a/source/gloperate/include/gloperate/rendering/RenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/RenderTarget.h @@ -99,6 +99,75 @@ class GLOPERATE_API RenderTarget */ void bind(gl::GLenum bindingPoint, globjects::Framebuffer * fbo); + /** + * @brief + * Get current attachment type + * + * @return + * The current attachment type + */ + RenderTargetType type() const; + + /** + * @brief + * Get default framebuffer attachment + * + * @return + * The default framebuffer attachment + * + * @remarks + * The result is only defined if type() == DefaultFBOAttachment + */ + gl::GLenum defaultFramebufferAttachment() const; + + /** + * @brief + * Get texture attachment + * + * @return + * The texture attachment + * + * @remarks + * The result is only defined if type() == Texture + */ + globjects::Texture * textureAttachment() const; + + /** + * @brief + * Get renderbuffer attachment + * + * @return + * The renderbuffer attachment + * + * @remarks + * The result is only defined if type() == Renderbuffer + */ + globjects::Renderbuffer * renderbufferAttachment() const; + + /** + * @brief + * Get framebuffer attachment + * + * @return + * The framebuffer attachment + * + * @remarks + * The result is only defined if type() == UserDefinedFBOAttachment + */ + globjects::FramebufferAttachment * framebufferAttachment() const; + + /** + * @brief + * Query requirement for user-defined framebuffer to use this attachment + * + * @return + * 'true', if a user-defined framebuffer is required to use this attachment + * + * @remarks + * A user-defined framebuffer is required if the attachment is neither invalid + * nor an attachment of the default framebuffer + */ + bool attachmentRequiresUserDefinedFramebuffer() const; protected: RenderTargetType m_type; ///< Target type diff --git a/source/gloperate/include/gloperate/stages/base/BlitStage.h b/source/gloperate/include/gloperate/stages/base/BlitStage.h index c8fffcc4..dda7a027 100644 --- a/source/gloperate/include/gloperate/stages/base/BlitStage.h +++ b/source/gloperate/include/gloperate/stages/base/BlitStage.h @@ -13,6 +13,8 @@ #include #include +#include + namespace gloperate { @@ -38,14 +40,15 @@ class GLOPERATE_API BlitStage : public Stage public: // Inputs - Input sourceFBO; ///< FBO containing the source attachments + Input source; ///< FBO containing the source attachments Input sourceViewport; ///< Viewport for reading from source FBO - Input targetFBO; ///< FBO with destination attachments + Input target; ///< FBO with destination attachments Input targetViewport; ///< Viewport for writing into destination FBO + Input minFilter; ///< Interpolation mode used when target size is lower than source size (default: linear interpolation) + Input magFilter; ///< Interpolation mode used when target size is greater than source size (default: nearest filtering) // Outputs - Output fboOut; ///< Pass through framebuffer - Output rendered; ///< 'true' if output has been rendered + Output targetOut; ///< Pass-through render target public: @@ -64,6 +67,14 @@ class GLOPERATE_API BlitStage : public Stage protected: // Virtual Stage interface virtual void onProcess() override; + virtual void onContextInit(AbstractGLContext * context) override; + virtual void onContextDeinit(AbstractGLContext * context) override; + + +protected: + std::unique_ptr m_defaultFBO; ///< Intermediate default FBO + std::unique_ptr m_sourceFBO; ///< Intermediate source FBO + std::unique_ptr m_targetFBO; ///< Intermediate target FBO }; diff --git a/source/gloperate/include/gloperate/stages/base/FramebufferStage.h b/source/gloperate/include/gloperate/stages/base/FramebufferStage.h deleted file mode 100644 index 8026c644..00000000 --- a/source/gloperate/include/gloperate/stages/base/FramebufferStage.h +++ /dev/null @@ -1,94 +0,0 @@ - -#pragma once - - -#include - -#include - -#include - -#include -#include -#include -#include -#include - - -namespace gloperate -{ - - -class RenderTarget; -class Texture; - - -/** -* @brief -* Stage that maintains a framebuffer attached with all input textures -* -* By default it only has one color texture and one depth texture input. -* Additional attachments (of type RenderTarget *) can be added as inputs dynamically. -* These will be added as color attachments in order of addition. -*/ -class GLOPERATE_API FramebufferStage : public Stage -{ -public: - CPPEXPOSE_DECLARE_COMPONENT( - FramebufferStage, gloperate::Stage - , "" // Tags - , "" // Icon - , "" // Annotations - , "Stage that maintains a framebuffer attached with all input textures" - , GLOPERATE_AUTHOR_ORGANIZATION - , "v1.0.0" - ) - - -public: - // Inputs - Input colorTexture; ///< Color attachment (#0) - Input depthTexture; ///< Depth attachment - - // Additional attachments (of type RenderTarget *) can be added as inputs dynamically - - // Outputs - Output fbo; ///< Framebuffer - - -public: - /** - * @brief - * Constructor - * - * @param[in] environment - * Environment to which the stage belongs (must NOT be null!) - * @param[in] name - * Stage name - */ - FramebufferStage(Environment * environment, const std::string & name = ""); - - /** - * @brief - * Destructor - */ - virtual ~FramebufferStage(); - - -protected: - // Virtual Stage interface - virtual void onContextInit(AbstractGLContext * context) override; - virtual void onContextDeinit(AbstractGLContext * context) override; - virtual void onProcess() override; - - // Helper functions - void rebuildFBO(); - bool isNameOfDepthRenderTarget(const std::string & name); - - -protected: - std::unique_ptr m_fbo; ///< The created framebuffer -}; - - -} // namespace gloperate diff --git a/source/gloperate/source/rendering/RenderTarget.cpp b/source/gloperate/source/rendering/RenderTarget.cpp index b8ce91b0..e1bbc48c 100644 --- a/source/gloperate/source/rendering/RenderTarget.cpp +++ b/source/gloperate/source/rendering/RenderTarget.cpp @@ -14,6 +14,9 @@ namespace gloperate RenderTarget::RenderTarget() : m_type(RenderTargetType::Invalid) , m_attachment(gl::GL_NONE) +, m_texture(nullptr) +, m_renderbuffer(nullptr) +, m_userDefined(nullptr) { } @@ -82,30 +85,36 @@ void RenderTarget::setTarget(globjects::FramebufferAttachment * fboAttachment) m_userDefined = fboAttachment; } -void RenderTarget::bind(gl::GLenum bindingPoint, globjects::Framebuffer * fbo) +RenderTargetType RenderTarget::type() const { - assert(fbo != nullptr); - assert(!fbo->isDefault()); + return m_type; +} - switch (m_type) - { - case RenderTargetType::Texture: - fbo->attachTexture(bindingPoint, m_texture); - break; - case RenderTargetType::Renderbuffer: - fbo->attachRenderBuffer(bindingPoint, m_renderbuffer); - break; - case RenderTargetType::DefaultFBOAttachment: - // [TODO] - break; - case RenderTargetType::UserDefinedFBOAttachment: - // [TODO] - break; - case RenderTargetType::Invalid: - default: - // [TODO] show error/warning? - break; - } +gl::GLenum RenderTarget::defaultFramebufferAttachment() const +{ + return m_attachment; +} + +globjects::Texture * RenderTarget::textureAttachment() const +{ + return m_texture; +} + +globjects::Renderbuffer * RenderTarget::renderbufferAttachment() const +{ + return m_renderbuffer; +} + +globjects::FramebufferAttachment * RenderTarget::framebufferAttachment() const +{ + return m_userDefined; +} + +bool RenderTarget::attachmentRequiresUserDefinedFramebuffer() const +{ + return m_type == RenderTargetType::Texture + || m_type == RenderTargetType::Renderbuffer + || m_type == RenderTargetType::UserDefinedFBOAttachment; } diff --git a/source/gloperate/source/stages/base/BlitStage.cpp b/source/gloperate/source/stages/base/BlitStage.cpp index 284ab92a..ce3e614c 100644 --- a/source/gloperate/source/stages/base/BlitStage.cpp +++ b/source/gloperate/source/stages/base/BlitStage.cpp @@ -4,7 +4,6 @@ #include #include -#include namespace gloperate { @@ -12,38 +11,61 @@ namespace gloperate BlitStage::BlitStage(Environment * environment, const std::string & name) :Stage(environment, name) -, sourceFBO("sourceFBO", this) +, source("source", this) , sourceViewport("sourceViewport", this) -, targetFBO("targetFBO", this) +, target("target", this) , targetViewport("targetViewport", this) -, fboOut("fboOut", this) -, rendered("rendered", this) +, minFilter("minFilter", this, gl::GL_LINEAR) +, magFilter("magFilter", this, gl::GL_NEAREST) +, targetOut("targetOut", this) { + setAlwaysProcessed(true); } -void BlitStage::onProcess() +void BlitStage::onContextInit(AbstractGLContext * /*context*/) { - globjects::Framebuffer * srcFBO = *sourceFBO; + m_defaultFBO = globjects::Framebuffer::defaultFBO(); + m_sourceFBO = cppassist::make_unique(); + m_targetFBO = cppassist::make_unique(); +} - globjects::Framebuffer * destFBO = *targetFBO; +void BlitStage::onContextDeinit(AbstractGLContext * /*context*/) +{ + m_defaultFBO = nullptr; + m_sourceFBO = nullptr; + m_targetFBO = nullptr; +} - std::array srcRect = {{ +void BlitStage::onProcess() +{ + std::array sourceRect = {{ static_cast((*sourceViewport).x), static_cast((*sourceViewport).y), static_cast((*sourceViewport).z), static_cast((*sourceViewport).w) }}; - std::array destRect = {{ + std::array targetRect = {{ static_cast((*targetViewport).x), static_cast((*targetViewport).y), static_cast((*targetViewport).z), static_cast((*targetViewport).w) }}; - srcFBO->blit(gl::GL_COLOR_ATTACHMENT0, srcRect, destFBO, destFBO->id() == 0 ? gl::GL_BACK_LEFT : gl::GL_COLOR_ATTACHMENT0, destRect, gl::GL_COLOR_BUFFER_BIT, gl::GL_LINEAR); + globjects::Framebuffer * sourceFBO = source->attachmentRequiresUserDefinedFramebuffer() ? m_sourceFBO.get() : m_defaultFBO.get(); + globjects::Framebuffer * targetFBO = target->attachmentRequiresUserDefinedFramebuffer() ? m_targetFBO.get() : m_defaultFBO.get(); + auto sourceAttachment = source->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : source->defaultFramebufferAttachment(); + auto targetAttachment = target->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : target->defaultFramebufferAttachment(); + + if (sourceRect[2] <= targetRect[2] && sourceRect[3] <= targetRect[3]) + { + sourceFBO->blit(sourceAttachment, sourceRect, targetFBO, targetAttachment, targetRect, gl::GL_COLOR_BUFFER_BIT, *magFilter); + } + else + { + sourceFBO->blit(sourceAttachment, sourceRect, targetFBO, targetAttachment, targetRect, gl::GL_COLOR_BUFFER_BIT, *minFilter); + } - fboOut.setValue(*targetFBO); - rendered.setValue(true); + targetOut.setValue(*target); } diff --git a/source/gloperate/source/stages/base/FramebufferStage.cpp b/source/gloperate/source/stages/base/FramebufferStage.cpp deleted file mode 100644 index 176d47b1..00000000 --- a/source/gloperate/source/stages/base/FramebufferStage.cpp +++ /dev/null @@ -1,109 +0,0 @@ - -#include - -#include - -#include - -#include - - -namespace gloperate -{ - - -CPPEXPOSE_COMPONENT(FramebufferStage, gloperate::Stage) - - -FramebufferStage::FramebufferStage(Environment * environment, const std::string & name) -: Stage(environment, "FramebufferStage", name) -, colorTexture("colorTexture", this) -, depthTexture("depthTexture", this) -, fbo ("fbo", this) -{ -} - -FramebufferStage::~FramebufferStage() -{ -} - -void FramebufferStage::onContextInit(AbstractGLContext *) -{ -} - -void FramebufferStage::onContextDeinit(AbstractGLContext *) -{ - // Clean up OpenGL objects - m_fbo = nullptr; -} - -void FramebufferStage::onProcess() -{ - // Check if FBO needs to be rebuilt - if (!fbo.isValid()) - { - // Rebuild FBO (and textures) - rebuildFBO(); - - // Update outputs - this->fbo.setValue(m_fbo.get()); - } -} - -void FramebufferStage::rebuildFBO() -{ - // Create FBO - m_fbo = cppassist::make_unique(); - - // Attach textures to FBO - std::vector colorAttachments; - for (int i = 0; i <= 1; i++) - { - // First round: Count number of color attachments - // Second round: Actually attach the textures - gl::GLenum index = gl::GL_COLOR_ATTACHMENT0; - if (i == 1) { - m_fbo->setDrawBuffers(colorAttachments); - } - - for (auto input : this->inputs()) - { - auto slot = dynamic_cast *>(input); - if (!slot) { - continue; - } - - RenderTarget * texture = **slot; - if (!texture) - { - continue; - } - - if (i == 0) { - if (!isNameOfDepthRenderTarget(slot->name())) { - // Add color attachment - colorAttachments.push_back(index); - index = index + 1; - } - } else { - if (isNameOfDepthRenderTarget(slot->name())) { - // Add depth attachment - texture->bind(gl::GL_DEPTH_ATTACHMENT, m_fbo.get()); - } else { - // Add color attachment - texture->bind(index, m_fbo.get()); - index = index + 1; - } - } - } - } -} - -bool FramebufferStage::isNameOfDepthRenderTarget(const std::string & name) -{ - return name.find("Depth") != std::string::npos || name.find("depth") != std::string::npos; -} - - - -} // namespace gloperate From 5b4cbef0a0f1b077970f405dd5994631f7013e77 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 14 Jun 2017 11:29:14 +0200 Subject: [PATCH 02/33] Adjust RenderInterface and start ClearStage rewrite --- .../stages/MultiFrameAggregationPipeline.cpp | 7 +- .../gloperate/stages/base/ClearStage.h | 57 +++- .../stages/interfaces/RenderInterface.h | 23 +- .../source/stages/base/ClearStage.cpp | 296 ++++++++++++++++-- .../stages/interfaces/RenderInterface.cpp | 8 +- 5 files changed, 337 insertions(+), 54 deletions(-) diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index 0138f85d..a0afafef 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -64,12 +63,12 @@ MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environm m_aggregationStage->aggregationFactor << m_controlStage->aggregationFactor; addStage(m_blitStage.get()); - m_blitStage->sourceFBO << m_aggregationStage->aggregatedFBO; - m_blitStage->targetFBO << renderInterface.targetFBO; + m_blitStage->source << m_aggregationStage->aggregatedFBO; + m_blitStage->target << renderInterface.renderTarget; m_blitStage->sourceViewport << renderInterface.deviceViewport; m_blitStage->targetViewport << renderInterface.deviceViewport; - renderInterface.rendered << m_blitStage->rendered; + renderInterface.renderTargetOut << m_blitStage->targetOut; } MultiFrameAggregationPipeline::~MultiFrameAggregationPipeline() diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index 7f9aa8d4..4edd6b92 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -14,7 +14,7 @@ namespace globjects { class Framebuffer; - class Texture; + class FramebufferAttachment; } @@ -22,9 +22,6 @@ namespace gloperate { -class AbstractDrawable; - - /** * @brief * Stage that clears the screen with a background color @@ -44,15 +41,45 @@ class GLOPERATE_API ClearStage : public Stage public: - // Interfaces - RenderInterface renderInterface; ///< Interface for rendering into a viewer - // Inputs - Input colorTexture; ///< Pass in of texture input/output + + Input clear; ///< Flag if buffers should get cleared + + Input viewport; ///< Region for clearing + + Input colorAttachment0; ///< Color attachment 0 to clear + Input clearColor0; ///< Clear color for attachment 0 + + Input colorAttachment1; ///< Color attachment 1 to clear + Input clearColor1; ///< Clear color for attachment 1 + + Input colorAttachment2; ///< Color attachment 2 to clear + Input clearColor2; ///< Clear color for attachment 2 + + Input colorAttachment3; ///< Color attachment 3 to clear + Input clearColor3; ///< Clear color for attachment 3 + + Input colorAttachment4; ///< Color attachment 4 to clear + Input clearColor4; ///< Clear color for attachment 4 + + // [TODO]: add until index 15 + + Input depthAttachment; ///< Depth only attachment to clear + Input depthValue; ///< Clear depth for both depth attachments + + Input depthStencilAttachment; ///< Combined depth stencil attachment to clear + Input stencilValue; ///< Clear stencil for combined depth stencil attachment // Outputs - Output fboOut; ///< Pass through framebuffer - Output colorTextureOut; ///< Pass through color texture + + Output colorAttachment0Out; ///< Pass-through color attachment 0 + Output colorAttachment1Out; ///< Pass-through color attachment 1 + Output colorAttachment2Out; ///< Pass-through color attachment 2 + Output colorAttachment3Out; ///< Pass-through color attachment 3 + Output colorAttachment4Out; ///< Pass-through color attachment 4 + // [TODO]: add until index 15 + Output depthAttachmentOut; ///< Pass-through depth only attachment + Output depthStencilAttachmentOut; ///< Pass-through depth stencil attachment public: @@ -78,6 +105,16 @@ class GLOPERATE_API ClearStage : public Stage // Virtual Stage interface virtual void onProcess() override; virtual void onContextInit(AbstractGLContext * content) override; + virtual void onContextDeinit(AbstractGLContext * content) override; + + void clearColorAttachment(unsigned char index, gloperate::RenderTarget * target, const glm::vec4 & clearColor); + void clearDepthAttachment(gloperate::RenderTarget * target, float clearDepth); + void clearDepthStencilAttachment(gloperate::RenderTarget * target, float clearDepth, int clearStencil); + + +protected: + std::unique_ptr m_defaultFBO; ///< Default FBO for clearing + std::unique_ptr m_fbo; ///< Intermediate FBO for clearing }; diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 80f5d5ec..36833c01 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -9,17 +9,12 @@ #include -namespace globjects -{ - class Framebuffer; -} - - namespace gloperate { class Stage; +class RenderTarget; /** @@ -39,15 +34,17 @@ class GLOPERATE_API RenderInterface { public: // Inputs - Input deviceViewport; ///< Viewport (in real device coordinates) - Input virtualViewport; ///< Viewport (in virtual coordinates) - Input backgroundColor; ///< Background color (RGB) - Input frameCounter; ///< Frame counter (number of frames) - Input timeDelta; ///< Time delta since last frame (in seconds) - Input targetFBO; ///< Target FBO (must not be null) + Input deviceViewport; ///< Viewport (in real device coordinates) + Input virtualViewport; ///< Viewport (in virtual coordinates) + Input backgroundColor; ///< Background color (RGB) + Input frameCounter; ///< Frame counter (number of frames) + Input timeDelta; ///< Time delta since last frame (in seconds) + Input colorRenderTarget; ///< Target color attachment (must not be null) + Input depthRenderTarget; ///< Target color attachment (may be null, depends on created OpenGL context) // Outputs - Output rendered; ///< 'true' if output has been rendered + Output colorRenderTargetOut; ///< Output color target of pipeline (must be set by owning stage/pipeline) + Output depthRenderTargetOut; ///< Output depth target of pipeline (may be set by owning stage/pipeline) public: diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index a5b43727..1b639eac 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -4,8 +4,11 @@ #include #include +#include +#include +#include -#include +#include namespace gloperate @@ -17,10 +20,29 @@ CPPEXPOSE_COMPONENT(ClearStage, gloperate::Stage) ClearStage::ClearStage(Environment * environment, const std::string & name) : Stage(environment, "ClearStage", name) -, renderInterface(this) -, colorTexture ("colorTexture", this) -, fboOut ("fboOut", this) -, colorTextureOut("colorTextureOut", this) +, clear ("clear", this) +, viewport ("viewport", this) +, colorAttachment0 ("colorAttachment0", this) +, clearColor0 ("clearColor0", this) +, colorAttachment1 ("colorAttachment1", this) +, clearColor1 ("clearColor1", this) +, colorAttachment2 ("colorAttachment2", this) +, clearColor2 ("clearColor2", this) +, colorAttachment3 ("colorAttachment3", this) +, clearColor3 ("clearColor3", this) +, colorAttachment4 ("colorAttachment4", this) +, clearColor4 ("clearColor4", this) +, depthAttachment ("depthAttachment", this) +, depthValue ("depthValue", this) +, depthStencilAttachment ("depthStencilAttachment", this) +, stencilValue ("stencilValue", this) +, colorAttachment0Out ("colorAttachment0Out", this) +, colorAttachment1Out ("colorAttachment1Out", this) +, colorAttachment2Out ("colorAttachment2Out", this) +, colorAttachment3Out ("colorAttachment3Out", this) +, colorAttachment4Out ("colorAttachment4Out", this) +, depthAttachmentOut ("depthAttachmentOut", this) +, depthStencilAttachmentOut("depthStencilAttachmentOut", this) { } @@ -30,32 +52,260 @@ ClearStage::~ClearStage() void ClearStage::onContextInit(AbstractGLContext *) { + m_defaultFBO = globjects::Framebuffer::defaultFBO(); + m_fbo = cppassist::make_unique(); } -void ClearStage::onProcess() +void ClearStage::onContextDeinit(AbstractGLContext *) { - // Set viewport - const glm::vec4 & viewport = *renderInterface.deviceViewport; - gl::glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + m_defaultFBO = nullptr; + m_fbo = nullptr; +} - // Bind FBO - globjects::Framebuffer * fbo = *renderInterface.targetFBO; - fbo->bind(gl::GL_FRAMEBUFFER); +void ClearStage::onProcess() +{ + if (!*clear) + { + // Setup OpenGL state + gl::glScissor(viewport->x, viewport->y, viewport->z, viewport->w); + gl::glEnable(gl::GL_SCISSOR_TEST); - // Clear background - auto & color = *renderInterface.backgroundColor; - gl::glClearColor(color.redf(), color.greenf(), color.bluef(), 1.0f); - gl::glScissor(viewport.x, viewport.y, viewport.z, viewport.w); - gl::glEnable(gl::GL_SCISSOR_TEST); - gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT); - gl::glDisable(gl::GL_SCISSOR_TEST); + // Clear individual buffers + clearColorAttachment (0, *colorAttachment0, *clearColor0 ); + clearColorAttachment (1, *colorAttachment1, *clearColor1 ); + clearColorAttachment (2, *colorAttachment2, *clearColor2 ); + clearColorAttachment (3, *colorAttachment3, *clearColor3 ); + clearColorAttachment (4, *colorAttachment4, *clearColor4 ); + clearDepthAttachment ( *depthAttachment, *depthValue ); + clearDepthStencilAttachment( *depthStencilAttachment, *depthValue, *stencilValue); - // Unbind FBO - globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); + // Reset OpenGL state + gl::glDisable(gl::GL_SCISSOR_TEST); + } // Update outputs - fboOut.setValue(fbo); - colorTextureOut.setValue(*colorTexture); + colorAttachment0Out.setValue(&colorAttachment0); + colorAttachment1Out.setValue(&colorAttachment1); + colorAttachment2Out.setValue(&colorAttachment2); + colorAttachment3Out.setValue(&colorAttachment3); + colorAttachment4Out.setValue(&colorAttachment4); + depthAttachmentOut.setValue(&depthAttachmentOut); + depthStencilAttachmentOut.setValue(&depthStencilAttachmentOut); +} + +void ClearStage::clearColorAttachment(unsigned char index, gloperate::RenderTarget * target, const glm::vec4 & clearColor) +{ + if (!target) + { + return; + } + + const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + + switch (target->type()) + { + case RenderTargetType::DefaultFBOAttachment: + m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), 0, clearColor); + break; + + case RenderTargetType::UserDefinedFBOAttachment: + { + const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); + const auto targetAttachment = target->framebufferAttachment(); + + const auto targetAttachedTexture = static_cast(targetAttachment); + const auto targetAttachedRenderbuffer = static_cast(targetAttachment); + const auto fboAttachedTexture = static_cast(fboAttachment); + const auto fboAttachedRenderbuffer = static_cast(fboAttachment); + + if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); + } + else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); + } + + m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); + } + break; + + case RenderTargetType::Texture: + { + const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedTexture = static_cast(attachment); + if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) + { + m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); + } + + m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); + } + break; + + case RenderTargetType::Renderbuffer: + { + const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedRenderbuffer = static_cast(attachment); + if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) + { + m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); + } + + m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); + } + break; + + default: + return false; + } +} + +void ClearStage::clearDepthAttachment(gloperate::RenderTarget * target, float clearDepth) +{ + if (!target) + { + return; + } + + const auto attachmentIndex = gl::GL_DEPTH_ATTACHMENT; + + switch (target->type()) + { + case RenderTargetType::DefaultFBOAttachment: + m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), clearDepth, 0); + break; + + case RenderTargetType::UserDefinedFBOAttachment: + { + const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); + const auto targetAttachment = target->framebufferAttachment(); + + const auto targetAttachedTexture = static_cast(targetAttachment); + const auto targetAttachedRenderbuffer = static_cast(targetAttachment); + const auto fboAttachedTexture = static_cast(fboAttachment); + const auto fboAttachedRenderbuffer = static_cast(fboAttachment); + + if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); + } + else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); + } + + m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); + } + break; + + case RenderTargetType::Texture: + { + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedTexture = static_cast(attachment); + if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) + { + m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); + } + + m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); + } + break; + + case RenderTargetType::Renderbuffer: + { + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedRenderbuffer = static_cast(attachment); + if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) + { + m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); + } + + m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); + } + break; + + default: + return false; + } +} + +void ClearStage::clearDepthStencilAttachment(gloperate::RenderTarget * target, float clearDepth, int clearStencil) +{ + if (!target) + { + return; + } + + const auto attachmentIndex = gl::GL_DEPTH_STENCIL_ATTACHMENT; + + switch (target->type()) + { + case RenderTargetType::DefaultFBOAttachment: + m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), 0, clearDepth, clearStencil); + break; + + case RenderTargetType::UserDefinedFBOAttachment: + { + const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); + const auto targetAttachment = target->framebufferAttachment(); + + const auto targetAttachedTexture = static_cast(targetAttachment); + const auto targetAttachedRenderbuffer = static_cast(targetAttachment); + const auto fboAttachedTexture = static_cast(fboAttachment); + const auto fboAttachedRenderbuffer = static_cast(fboAttachment); + + if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); + } + else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) + { + m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); + } + + m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); + } + break; + + case RenderTargetType::Texture: + { + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedTexture = static_cast(attachment); + if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) + { + m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); + } + + m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); + } + break; + + case RenderTargetType::Renderbuffer: + { + const auto attachment = m_fbo->getAttachment(attachmentIndex); + + const auto attachedRenderbuffer = static_cast(attachment); + if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) + { + m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); + } + + m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); + } + break; + + default: + return false; + } } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 0e4e4c30..36701ba5 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -12,8 +12,8 @@ RenderInterface::RenderInterface(Stage * stage) , backgroundColor("backgroundColor", stage) , frameCounter ("frameCounter", stage) , timeDelta ("timeDelta", stage) -, targetFBO ("targetFBO", stage) -, rendered ("rendered", stage) +, renderTarget ("renderTarget", stage) +, renderTargetOut("renderTargetOut", stage) { // Hide inputs in property editor deviceViewport .setOption("hidden", true); @@ -21,8 +21,8 @@ RenderInterface::RenderInterface(Stage * stage) backgroundColor.setOption("hidden", true); frameCounter .setOption("hidden", true); timeDelta .setOption("hidden", true); - targetFBO .setOption("hidden", true); - rendered .setOption("hidden", true); + renderTarget .setOption("hidden", true); + renderTargetOut.setOption("hidden", true); } RenderInterface::~RenderInterface() From 951dd6d4ec2f6241d42f08a435c87bdc100cc7ff Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 14 Jun 2017 19:03:43 +0200 Subject: [PATCH 03/33] Intermediate commit * Add CanvasInterface * Rewrite RenderInterface * Rewrite ClearStage and RasterizationStage * Remove semantics of virtual viewport in Canvas --- source/gloperate-glfw/source/RenderWindow.cpp | 6 - .../gloperate-qt/source/base/RenderWindow.cpp | 3 +- .../source/RenderItemRenderer.cpp | 1 - source/gloperate/CMakeLists.txt | 3 + .../gloperate/include/gloperate/base/Canvas.h | 29 +- .../gloperate/rendering/AttachmentType.h | 74 ++++ .../gloperate/rendering/RenderTarget.h | 48 ++- .../gloperate/stages/base/ClearStage.h | 43 +-- .../stages/base/RasterizationStage.h | 11 +- .../stages/interfaces/CanvasInterface.h | 63 ++++ .../stages/interfaces/RenderInterface.h | 74 +++- source/gloperate/source/base/Canvas.cpp | 198 ++++++++-- .../source/rendering/RenderTarget.cpp | 38 ++ .../source/stages/base/ClearStage.cpp | 348 +++++------------- .../source/stages/base/RasterizationStage.cpp | 47 ++- .../stages/interfaces/CanvasInterface.cpp | 27 ++ .../stages/interfaces/RenderInterface.cpp | 207 ++++++++++- .../FFMPEGVideoExporter.cpp | 5 +- .../FFMPEGVideoExporter.h | 3 +- 19 files changed, 826 insertions(+), 402 deletions(-) create mode 100644 source/gloperate/include/gloperate/rendering/AttachmentType.h create mode 100644 source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h create mode 100644 source/gloperate/source/stages/interfaces/CanvasInterface.cpp diff --git a/source/gloperate-glfw/source/RenderWindow.cpp b/source/gloperate-glfw/source/RenderWindow.cpp index d30ae534..0542ca01 100644 --- a/source/gloperate-glfw/source/RenderWindow.cpp +++ b/source/gloperate-glfw/source/RenderWindow.cpp @@ -63,11 +63,6 @@ void RenderWindow::onContextDeinit() void RenderWindow::onResize(ResizeEvent & event) { m_virtualSize = event.size(); - - m_canvas->setViewport( - glm::vec4(0, 0, m_deviceSize.x, m_deviceSize.y) - , glm::vec4(0, 0, m_virtualSize.x, m_virtualSize.y) - ); } void RenderWindow::onFramebufferResize(ResizeEvent & event) @@ -76,7 +71,6 @@ void RenderWindow::onFramebufferResize(ResizeEvent & event) m_canvas->setViewport( glm::vec4(0, 0, m_deviceSize.x, m_deviceSize.y) - , glm::vec4(0, 0, m_virtualSize.x, m_virtualSize.y) ); } diff --git a/source/gloperate-qt/source/base/RenderWindow.cpp b/source/gloperate-qt/source/base/RenderWindow.cpp index 0a6cf3d0..08c56cf9 100644 --- a/source/gloperate-qt/source/base/RenderWindow.cpp +++ b/source/gloperate-qt/source/base/RenderWindow.cpp @@ -51,11 +51,10 @@ void RenderWindow::onContextDeinit() m_canvas->setOpenGLContext(nullptr); } -void RenderWindow::onResize(const QSize & deviceSize, const QSize & virtualSize) +void RenderWindow::onResize(const QSize & deviceSize, const QSize & /*virtualSize*/) { m_canvas->setViewport( glm::vec4(0, 0, deviceSize.width(), deviceSize.height()) - , glm::vec4(0, 0, virtualSize.width(), virtualSize.height()) ); } diff --git a/source/gloperate-qtquick/source/RenderItemRenderer.cpp b/source/gloperate-qtquick/source/RenderItemRenderer.cpp index 9728b668..c2dd3d81 100644 --- a/source/gloperate-qtquick/source/RenderItemRenderer.cpp +++ b/source/gloperate-qtquick/source/RenderItemRenderer.cpp @@ -93,7 +93,6 @@ QOpenGLFramebufferObject * RenderItemRenderer::createFramebufferObject(const QSi auto ratio = window->devicePixelRatio(); m_canvas->setViewport( glm::vec4(0, 0, m_renderItem->width() * ratio, m_renderItem->height() * ratio) - , glm::vec4(0, 0, m_renderItem->width(), m_renderItem->height()) ); // This function is called by Qt. We must not reset the context here because diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 93fcafbc..6b6a3544 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -83,6 +83,7 @@ set(headers ${include_path}/pipeline/Output.inl ${include_path}/rendering/AbstractDrawable.h + ${include_path}/rendering/AttachmentType.h ${include_path}/rendering/Camera.h ${include_path}/rendering/CameraUtils.h ${include_path}/rendering/Drawable.h @@ -115,6 +116,7 @@ set(headers ${include_path}/rendering/ColorGradientPreparation.h ${include_path}/stages/interfaces/RenderInterface.h + ${include_path}/stages/interfaces/CanvasInterface.h ${include_path}/stages/base/BasicFramebufferStage.h ${include_path}/stages/base/TextureStage.h ${include_path}/stages/base/TextureLoadStage.h @@ -205,6 +207,7 @@ set(sources ${source_path}/rendering/ColorGradientPreparation.cpp ${source_path}/stages/interfaces/RenderInterface.cpp + ${source_path}/stages/interfaces/CanvasInterface.cpp ${source_path}/stages/base/BasicFramebufferStage.cpp ${source_path}/stages/base/ColorGradientSelectionStage.cpp ${source_path}/stages/base/ColorGradientTextureStage.cpp diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 55ccc80e..07b34440 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -32,6 +32,7 @@ class Stage; class AbstractSlot; class MouseDevice; class KeyboardDevice; +class RenderTarget; /** @@ -169,30 +170,19 @@ class GLOPERATE_API Canvas : public cppexpose::Object * @brief * Set viewport (must be called from UI thread) * - * @param[in] deviceViewport + * @param[in] viewport * Viewport (in real device coordinates) - * @param[in] virtualViewport - * Viewport (in virtual coordinates) */ - void setViewport(const glm::vec4 & deviceViewport, const glm::vec4 & virtualViewport); + void setViewport(const glm::vec4 & viewport); /** * @brief - * Get device viewport + * Get viewport (in real device coordinates) * * @return - * The device viewport + * The viewport */ - const glm::vec4 & deviceViewport() const; - - /** - * @brief - * Get virtual viewport - * - * @return - * The virtual viewport - */ - const glm::vec4 & virtualViewport() const; + const glm::vec4 & viewport() const; /** * @brief @@ -319,8 +309,7 @@ class GLOPERATE_API Canvas : public cppexpose::Object AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' gloperate::ChronoTimer m_clock; ///< Time measurement - glm::vec4 m_deviceViewport; ///< Viewport (in real device coordinates) - glm::vec4 m_virtualViewport; ///< Viewport (in virtual coordinates) + glm::vec4 m_viewport; ///< Viewport (in real device coordinates) float m_timeDelta; ///< Time delta since the last update (in seconds) std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call @@ -332,6 +321,10 @@ class GLOPERATE_API Canvas : public cppexpose::Object cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) std::vector m_changedInputs; ///< List of changed input slots std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs + + std::unique_ptr m_colorTarget; ///< Input render target for color attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment + std::unique_ptr m_depthStencilTarget; ///< Input render target for depth stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/AttachmentType.h b/source/gloperate/include/gloperate/rendering/AttachmentType.h new file mode 100644 index 00000000..98a5f055 --- /dev/null +++ b/source/gloperate/include/gloperate/rendering/AttachmentType.h @@ -0,0 +1,74 @@ + +#pragma once + + +#include +#include + + +namespace gloperate +{ + + +/** +* @brief +* Type of a render target +*/ +enum class AttachmentType : unsigned int +{ + Color, ///< Color attachment + Depth, ///< Depth only attachment + DepthStencil ///< Depth stencil attachment +}; + + +} // namespace gloperate + + +namespace std +{ + + +/** +* @brief +* Hash specialization for RenderTargetType enum class. +* +* Enables the use of RenderTargetType as key type of the unordered collection types. +*/ +template<> +struct hash +{ + std::hash::result_type operator()(const gloperate::RenderTargetType & arg) const + { + std::hash hasher; + return hasher(static_cast(arg)); + } +}; + + +} // namespace std + + +namespace cppexpose +{ + + +/** +* @brief +* Template specialization of enum strings for RenderTargetType. +*/ +template<> +struct EnumDefaultStrings +{ + std::map operator()() + { + return { + { gloperate::AttachmentType::Color, "Color" }, + { gloperate::AttachmentType::Depth, "Depth" }, + { gloperate::AttachmentType::DepthStencil, "DepthStencil" } + }; + } +}; + + +} // namespace cppexpose diff --git a/source/gloperate/include/gloperate/rendering/RenderTarget.h b/source/gloperate/include/gloperate/rendering/RenderTarget.h index 80344953..a52eece5 100644 --- a/source/gloperate/include/gloperate/rendering/RenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/RenderTarget.h @@ -2,9 +2,11 @@ #pragma once +#include #include #include +#include #include @@ -51,6 +53,33 @@ class GLOPERATE_API RenderTarget */ void releaseTarget(); + /** + * @brief + * Get attachment type + * + * @return + * The attachment type + */ + AttachmentType attachmentType() const; + + /** + * @brief + * Get attachment type as GLenum + * + * @return + * The attachment type as GLenum + */ + gl::GLenum attachmentGLType() const; + + /** + * @brief + * Set attachment type + * + * @param[in] type + * The attachment type + */ + void setAttachmentType(AttachmentType attachmentType); + /** * @brief * Set desired target @@ -101,10 +130,10 @@ class GLOPERATE_API RenderTarget /** * @brief - * Get current attachment type + * Get current target type * * @return - * The current attachment type + * The current target type */ RenderTargetType type() const; @@ -169,12 +198,17 @@ class GLOPERATE_API RenderTarget */ bool attachmentRequiresUserDefinedFramebuffer() const; + gl::GLenum attachmentBuffer() const; + + gl::GLint attachmentDrawBuffer(gl::GLint index) const; + protected: - RenderTargetType m_type; ///< Target type - gl::GLenum m_attachment; ///< Default framebuffer attachment target - globjects::Texture * m_texture; ///< Texture target - globjects::Renderbuffer * m_renderbuffer; ///< Renderbuffer target - globjects::FramebufferAttachment * m_userDefined; ///< User defined framebuffer attachment target + RenderTargetType m_type; ///< Target type + AttachmentType m_attachmentType; ///< OpenGL attachment type + gl::GLenum m_attachment; ///< Default framebuffer attachment target + globjects::Texture * m_texture; ///< Texture target + globjects::Renderbuffer * m_renderbuffer; ///< Renderbuffer target + globjects::FramebufferAttachment * m_userDefined; ///< User defined framebuffer attachment target }; diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index 4edd6b92..b2370080 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -45,41 +45,7 @@ class GLOPERATE_API ClearStage : public Stage Input clear; ///< Flag if buffers should get cleared - Input viewport; ///< Region for clearing - - Input colorAttachment0; ///< Color attachment 0 to clear - Input clearColor0; ///< Clear color for attachment 0 - - Input colorAttachment1; ///< Color attachment 1 to clear - Input clearColor1; ///< Clear color for attachment 1 - - Input colorAttachment2; ///< Color attachment 2 to clear - Input clearColor2; ///< Clear color for attachment 2 - - Input colorAttachment3; ///< Color attachment 3 to clear - Input clearColor3; ///< Clear color for attachment 3 - - Input colorAttachment4; ///< Color attachment 4 to clear - Input clearColor4; ///< Clear color for attachment 4 - - // [TODO]: add until index 15 - - Input depthAttachment; ///< Depth only attachment to clear - Input depthValue; ///< Clear depth for both depth attachments - - Input depthStencilAttachment; ///< Combined depth stencil attachment to clear - Input stencilValue; ///< Clear stencil for combined depth stencil attachment - - // Outputs - - Output colorAttachment0Out; ///< Pass-through color attachment 0 - Output colorAttachment1Out; ///< Pass-through color attachment 1 - Output colorAttachment2Out; ///< Pass-through color attachment 2 - Output colorAttachment3Out; ///< Pass-through color attachment 3 - Output colorAttachment4Out; ///< Pass-through color attachment 4 - // [TODO]: add until index 15 - Output depthAttachmentOut; ///< Pass-through depth only attachment - Output depthStencilAttachmentOut; ///< Pass-through depth stencil attachment + RenderInterface renderInterface; ///< Renderinterface to manage render targets inputs and outputs public: @@ -107,12 +73,11 @@ class GLOPERATE_API ClearStage : public Stage virtual void onContextInit(AbstractGLContext * content) override; virtual void onContextDeinit(AbstractGLContext * content) override; - void clearColorAttachment(unsigned char index, gloperate::RenderTarget * target, const glm::vec4 & clearColor); - void clearDepthAttachment(gloperate::RenderTarget * target, float clearDepth); - void clearDepthStencilAttachment(gloperate::RenderTarget * target, float clearDepth, int clearStencil); - protected: + std::vector *> m_colorValueInputs; + std::vector *> m_depthValueInputs; + std::vector> *> m_depthStencilValueInputs; std::unique_ptr m_defaultFBO; ///< Default FBO for clearing std::unique_ptr m_fbo; ///< Intermediate FBO for clearing }; diff --git a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h index 6d31ba6f..543481f6 100644 --- a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h +++ b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h @@ -50,12 +50,6 @@ class GLOPERATE_API RasterizationStage : public Stage // Inputs Input rasterize; ///< If connected, it enables/disables rasterization Input drawable; ///< Drawable that is rendered - Input colorTexture; ///< Pass in of texture input/output - - // Outputs - Output fboOut; ///< Pass through framebuffer - Output colorTextureOut; ///< Pass through color texture - public: /** @@ -79,6 +73,11 @@ class GLOPERATE_API RasterizationStage : public Stage protected: // Virtual Stage interface virtual void onProcess() override; + + +protected: + std::unique_ptr m_defaultFBO; ///< Default FBO for clearing + std::unique_ptr m_fbo; ///< Intermediate FBO for clearing }; diff --git a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h new file mode 100644 index 00000000..4d440c39 --- /dev/null +++ b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h @@ -0,0 +1,63 @@ + +#pragma once + + +#include +#include +#include + +#include + + +namespace gloperate +{ + + +class Stage; +class RenderTarget; + + +/** +* @brief +* Interface that can be used for rendering stages and pipelines that +* are intended to get rendered by a Canvas. +* +* A render stage is a stage that renders into framebuffer targets +* and can therefore be assigned to a viewer. Therefore, it has to support +* interface via input and output slots which is accessed by the viewer. +* +* A Canvas should attach to the render targets +* +* This class can be used to instanciate the necessary inputs and outputs +* for rendering stages. It can just be instanciated on a stage or pipeline +* and it will add the inputs and outputs directly to the stage (the interface +* itself is not an object in the hierarchy). +*/ +class GLOPERATE_API CanvasInterface +{ +public: + // Inputs + Input viewport; ///< Viewport (in real device coordinates) + Input backgroundColor; ///< Background color (RGBA) + Input frameCounter; ///< Frame counter (number of frames) + Input timeDelta; ///< Time delta since last frame (in seconds) + +public: + /** + * @brief + * Constructor + * + * @param[in] stage + * Stage (must NOT be null) + */ + CanvasInterface(Stage * stage); + + /** + * @brief + * Destructor + */ + ~CanvasInterface(); +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 36833c01..7a97b88c 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -9,6 +9,16 @@ #include +namespace globjects +{ + + +class Framebuffer; + + +} // namespace globjects + + namespace gloperate { @@ -21,9 +31,8 @@ class RenderTarget; * @brief * Interface that can be used for rendering stages and pipelines * -* A render stage is a stage that renders into the current framebuffer -* and can therefore be assigned to a viewer. Therefore, it has to support -* interface via input and output slots which is accessed by the viewer. +* A render stage is a stage that renders into render targets, given +* a common viewport. * * This class can be used to instanciate the necessary inputs and outputs * for rendering stages. It can just be instanciated on a stage or pipeline @@ -34,17 +43,10 @@ class GLOPERATE_API RenderInterface { public: // Inputs - Input deviceViewport; ///< Viewport (in real device coordinates) - Input virtualViewport; ///< Viewport (in virtual coordinates) - Input backgroundColor; ///< Background color (RGB) - Input frameCounter; ///< Frame counter (number of frames) - Input timeDelta; ///< Time delta since last frame (in seconds) - Input colorRenderTarget; ///< Target color attachment (must not be null) - Input depthRenderTarget; ///< Target color attachment (may be null, depends on created OpenGL context) + Input viewport; ///< Viewport (in framebuffer coordinates) - // Outputs - Output colorRenderTargetOut; ///< Output color target of pipeline (must be set by owning stage/pipeline) - Output depthRenderTargetOut; ///< Output depth target of pipeline (may be set by owning stage/pipeline) + // Rendertarget Inputs -> subject to pipeline/stage designer + // Rendertarget Outputs -> subject to pipeline/stage designer public: @@ -62,6 +64,52 @@ class GLOPERATE_API RenderInterface * Destructor */ ~RenderInterface(); + + bool allRenderTargetsCompatible() const; + + size_t renderTargetInputSize() const; + + const std::vector *> & renderTargetInputs() const; + + Input * renderTargetInput(size_t index) const; + + RenderTarget * inputRenderTarget(size_t index) const; + + size_t renderTargetOutputSize() const; + + const std::vector *> & renderTargetOutputs() const; + + Output * renderTargetOutput(size_t index) const; + + RenderTarget * outputRenderTarget(size_t index) const; + + /** + * @brief + * Registers new render target input + * + * @param[in] input + * New render target input + */ + void addRenderTargetInput(Input * input); + + /** + * @brief + * Registers new render target input + * + * @param[in] input + * New render target input + */ + void addRenderTargetOutput(Output * input); + + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + + globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; + + static globjects::Framebuffer * configureFBO(size_t index, RenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + +protected: + std::vector *> m_renderTargetInputs; ///< List of input render targets + std::vector *> m_renderTargetOutputs; ///< List of output render targets (pass-through) }; diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index c0936c10..c96dbcfa 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -1,6 +1,9 @@ #include +#include +#include + #include #include @@ -17,6 +20,8 @@ #include #include #include +#include +#include using namespace cppassist; @@ -37,6 +42,87 @@ gloperate::Slot * getSlot(gloperate::Stage * stage, const std::string & name) } } +template +gloperate::Input * getInput(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return nullptr; + } + + const auto & inputs = stage->inputs(); + + const auto it = std::find_if(inputs.begin(), inputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto input = dynamic_cast *>(slot); + + if (!input) + { + return false; + } + + return callback(input); + }); + + if (it == inputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + +template +void forAllInputs(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return; + } + + const auto & inputs = stage->inputs(); + + for (const auto input : inputs) + { + const auto inputT = dynamic_cast *>(input); + + if (!inputT) + { + continue; + } + + callback(inputT); + } +} + +template +gloperate::Output * getOutput(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return nullptr; + } + + const auto & outputs = stage->outputs(); + + const auto it = std::find_if(outputs.begin(), outputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto output = dynamic_cast *>(slot); + + if (!output) + { + return false; + } + + return callback(output); + }); + + if (it == outputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + auto s_nextCanvasId = size_t(0); @@ -56,6 +142,9 @@ Canvas::Canvas(Environment * environment) , m_mouseDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_keyboardDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_replaceStage(false) +, m_colorTarget(cppassist::make_unique()) +, m_depthTarget(cppassist::make_unique()) +, m_depthStencilTarget(cppassist::make_unique()) { // Register functions addFunction("onStageInputChanged", this, &Canvas::scr_onStageInputChanged); @@ -73,6 +162,10 @@ Canvas::Canvas(Environment * environment) // Register canvas m_environment->registerCanvas(this); + + m_colorTarget->setAttachmentType(AttachmentType::Color); + m_depthTarget->setAttachmentType(AttachmentType::Depth); + m_depthStencilTarget->setAttachmentType(AttachmentType::DepthStencil); } Canvas::~Canvas() @@ -189,7 +282,7 @@ void Canvas::updateTime() m_timeDelta += timeDelta; // Update timing - auto slotTimeDelta = getSlot(m_renderStage.get(), "timeDelta"); + auto slotTimeDelta = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "timeDelta"; }); if (slotTimeDelta) slotTimeDelta->setValue(m_timeDelta); // Check if a redraw is required @@ -199,33 +292,25 @@ void Canvas::updateTime() promoteChangedInputs(); } -void Canvas::setViewport(const glm::vec4 & deviceViewport, const glm::vec4 & virtualViewport) +void Canvas::setViewport(const glm::vec4 & deviceViewport) { std::lock_guard lock(this->m_mutex); // Store viewport information - m_deviceViewport = deviceViewport; - m_virtualViewport = virtualViewport; + m_viewport = deviceViewport; m_initialized = true; // Promote new viewport - auto slotDeviceViewport = getSlot(m_renderStage.get(), "deviceViewport"); - if (slotDeviceViewport) slotDeviceViewport->setValue(m_deviceViewport); - auto slotVirtualViewport = getSlot(m_renderStage.get(), "virtualViewport"); - if (slotVirtualViewport) slotVirtualViewport->setValue(m_virtualViewport); + auto slotViewport = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "viewport"; }); + if (slotViewport) slotViewport->setValue(m_viewport); // Check if a redraw is required checkRedraw(); } -const glm::vec4 & Canvas::deviceViewport() const +const glm::vec4 & Canvas::viewport() const { - return m_deviceViewport; -} - -const glm::vec4 & Canvas::virtualViewport() const -{ - return m_virtualViewport; + return m_viewport; } void Canvas::render(globjects::Framebuffer * targetFBO) @@ -258,26 +343,87 @@ void Canvas::render(globjects::Framebuffer * targetFBO) m_renderStage->initContext(m_openGLContext); // Promote viewport information - auto slotdeviceViewport = getSlot(m_renderStage.get(), "deviceViewport"); - if (slotdeviceViewport) slotdeviceViewport->setValue(m_deviceViewport); - auto slotVirtualViewport = getSlot(m_renderStage.get(), "virtualViewport"); - if (slotVirtualViewport) slotVirtualViewport->setValue(m_virtualViewport); + auto slotViewport = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "viewport"; }); + if (slotViewport) slotViewport->setValue(m_viewport); // Mark output as required - auto slotRendered = getSlot(m_renderStage.get(), "rendered"); - if (slotRendered) slotRendered->setRequired(true); + auto slotColorRenderTarget = getOutput(m_renderStage.get(), [](Output * output) { + RenderTarget * target = **output; + + return target->attachmentType() == AttachmentType::Color; + }); + if (slotColorRenderTarget) slotColorRenderTarget->setRequired(true); // Replace finished m_replaceStage = false; } - // Render - auto slotTargetFBO = getSlot(m_renderStage.get(), "targetFBO"); - if (slotTargetFBO) + // Extract default color and depth buffer from FBO + if (targetFBO->isDefault()) { - slotTargetFBO->setValue(targetFBO); - m_renderStage->process(); + m_colorTarget->setTarget(gl::GL_BACK_LEFT); + m_depthTarget->setTarget(gl::GL_DEPTH_ATTACHMENT); + m_depthStencilTarget->setTarget(gl::GL_DEPTH_STENCIL_ATTACHMENT); } + else + { + unsigned int i = 0; + globjects::FramebufferAttachment * colorAttachment = nullptr; + while (i < 16 && colorAttachment == nullptr) + { + colorAttachment = targetFBO->getAttachment(gl::GL_COLOR_ATTACHMENT0+i); + } + const auto depthAttachment = targetFBO->getAttachment(gl::GL_DEPTH_ATTACHMENT); + const auto depthStencilAttachment = targetFBO->getAttachment(gl::GL_DEPTH_STENCIL_ATTACHMENT); + + if (colorAttachment) + { + m_colorTarget->setTarget(colorAttachment); + } + else + { + m_colorTarget->releaseTarget(); + } + + if (depthStencilAttachment) + { + m_depthTarget->setTarget(depthStencilAttachment); + m_depthStencilTarget->setTarget(depthStencilAttachment); + } + else if (depthAttachment) + { + m_depthTarget->setTarget(depthAttachment); + m_depthStencilTarget->setTarget(depthAttachment); + } + else + { + m_depthTarget->releaseTarget(); + m_depthStencilTarget->releaseTarget(); + } + } + + // Update render stage input render targets + forAllInputs(m_renderStage.get(), [this](Input * input) { + gloperate::RenderTarget * renderTarget = **input; + + switch (renderTarget->attachmentType()) + { + case AttachmentType::Color: + input->setValue(m_colorTarget.get()); + break; + case AttachmentType::Depth: + input->setValue(m_depthTarget.get()); + break; + case AttachmentType::DepthStencil: + input->setValue(m_depthStencilTarget.get()); + break; + default: + input->setValue(nullptr); + } + }); + + // Render + m_renderStage->process(); } void Canvas::promoteKeyPress(int key, int modifier) diff --git a/source/gloperate/source/rendering/RenderTarget.cpp b/source/gloperate/source/rendering/RenderTarget.cpp index e1bbc48c..7566318d 100644 --- a/source/gloperate/source/rendering/RenderTarget.cpp +++ b/source/gloperate/source/rendering/RenderTarget.cpp @@ -49,6 +49,30 @@ void RenderTarget::releaseTarget() m_type = RenderTargetType::Invalid; } +AttachmentType RenderTarget::attachmentType() const +{ + return m_attachmentType; +} + +gl::GLenum RenderTarget::attachmentGLType() const +{ + switch (m_attachmentType) + { + case AttachmentType::Depth: + return gl::GL_DEPTH; + case AttachmentType::DepthStencil: + return gl::GL_DEPTH_STENCIL; + case AttachmentType::Color: + default: + return gl::GL_COLOR; + } +} + +void RenderTarget::setAttachmentType(AttachmentType attachmentType) +{ + m_attachmentType = attachmentType; +} + void RenderTarget::setTarget(globjects::Texture * texture) { releaseTarget(); @@ -117,5 +141,19 @@ bool RenderTarget::attachmentRequiresUserDefinedFramebuffer() const || m_type == RenderTargetType::UserDefinedFBOAttachment; } +gl::GLenum RenderTarget::attachmentBuffer() const +{ + return attachmentRequiresUserDefinedFramebuffer() + ? attachmentGLType() + : m_attachment; +} + +gl::GLint RenderTarget::attachmentDrawBuffer(gl::GLint index) const +{ + return attachmentRequiresUserDefinedFramebuffer() + ? (m_attachmentType == AttachmentType::Color ? index : 0) + : 0; +} + } // namespace gloperate diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index 1b639eac..cec0169f 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -20,30 +20,44 @@ CPPEXPOSE_COMPONENT(ClearStage, gloperate::Stage) ClearStage::ClearStage(Environment * environment, const std::string & name) : Stage(environment, "ClearStage", name) -, clear ("clear", this) -, viewport ("viewport", this) -, colorAttachment0 ("colorAttachment0", this) -, clearColor0 ("clearColor0", this) -, colorAttachment1 ("colorAttachment1", this) -, clearColor1 ("clearColor1", this) -, colorAttachment2 ("colorAttachment2", this) -, clearColor2 ("clearColor2", this) -, colorAttachment3 ("colorAttachment3", this) -, clearColor3 ("clearColor3", this) -, colorAttachment4 ("colorAttachment4", this) -, clearColor4 ("clearColor4", this) -, depthAttachment ("depthAttachment", this) -, depthValue ("depthValue", this) -, depthStencilAttachment ("depthStencilAttachment", this) -, stencilValue ("stencilValue", this) -, colorAttachment0Out ("colorAttachment0Out", this) -, colorAttachment1Out ("colorAttachment1Out", this) -, colorAttachment2Out ("colorAttachment2Out", this) -, colorAttachment3Out ("colorAttachment3Out", this) -, colorAttachment4Out ("colorAttachment4Out", this) -, depthAttachmentOut ("depthAttachmentOut", this) -, depthStencilAttachmentOut("depthStencilAttachmentOut", this) +, clear("clear", this) +, renderInterface(this) { + inputAdded.connect( [this] (gloperate::AbstractSlot * connectedInput) { + auto renderTargetInput = dynamic_cast *>(connectedInput); + auto colorValueInput = dynamic_cast *>(connectedInput); + auto depthValueInput = dynamic_cast *>(connectedInput); + auto depthStencilValueInput = dynamic_cast> *>(connectedInput); + + if (renderTargetInput) + { + renderInterface.addRenderTargetInput(renderTargetInput); + } + + if (colorValueInput) + { + m_colorValueInputs.push_back(colorValueInput); + } + + if (depthValueInput) + { + m_depthValueInputs.push_back(depthValueInput); + } + + if (depthStencilValueInput) + { + m_depthStencilValueInputs.push_back(depthStencilValueInput); + } + }); + + outputAdded.connect( [this] (gloperate::AbstractSlot * connectedOutput) { + auto renderTargetOutput = dynamic_cast *>(connectedOutput); + + if (renderTargetOutput) + { + renderInterface.addRenderTargetOutput(renderTargetOutput); + } + }); } ClearStage::~ClearStage() @@ -67,246 +81,76 @@ void ClearStage::onProcess() if (!*clear) { // Setup OpenGL state - gl::glScissor(viewport->x, viewport->y, viewport->z, viewport->w); + gl::glScissor(renderInterface.viewport->x, renderInterface.viewport->y, renderInterface.viewport->z, renderInterface.viewport->w); gl::glEnable(gl::GL_SCISSOR_TEST); - // Clear individual buffers - clearColorAttachment (0, *colorAttachment0, *clearColor0 ); - clearColorAttachment (1, *colorAttachment1, *clearColor1 ); - clearColorAttachment (2, *colorAttachment2, *clearColor2 ); - clearColorAttachment (3, *colorAttachment3, *clearColor3 ); - clearColorAttachment (4, *colorAttachment4, *clearColor4 ); - clearDepthAttachment ( *depthAttachment, *depthValue ); - clearDepthStencilAttachment( *depthStencilAttachment, *depthValue, *stencilValue); - - // Reset OpenGL state - gl::glDisable(gl::GL_SCISSOR_TEST); - } - - // Update outputs - colorAttachment0Out.setValue(&colorAttachment0); - colorAttachment1Out.setValue(&colorAttachment1); - colorAttachment2Out.setValue(&colorAttachment2); - colorAttachment3Out.setValue(&colorAttachment3); - colorAttachment4Out.setValue(&colorAttachment4); - depthAttachmentOut.setValue(&depthAttachmentOut); - depthStencilAttachmentOut.setValue(&depthStencilAttachmentOut); -} - -void ClearStage::clearColorAttachment(unsigned char index, gloperate::RenderTarget * target, const glm::vec4 & clearColor) -{ - if (!target) - { - return; - } - - const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; - - switch (target->type()) - { - case RenderTargetType::DefaultFBOAttachment: - m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), 0, clearColor); - break; - - case RenderTargetType::UserDefinedFBOAttachment: - { - const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); - const auto targetAttachment = target->framebufferAttachment(); - - const auto targetAttachedTexture = static_cast(targetAttachment); - const auto targetAttachedRenderbuffer = static_cast(targetAttachment); - const auto fboAttachedTexture = static_cast(fboAttachment); - const auto fboAttachedRenderbuffer = static_cast(fboAttachment); + size_t colorAttachmentIndex = 0; + size_t depthAttachmentIndex = 0; + size_t depthStencilAttachmentIndex = 0; - if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) - { - m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); - } - else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) + renderInterface.pairwiseRenderTargetsDo([this, & colorAttachmentIndex, & depthAttachmentIndex, & depthStencilAttachmentIndex](Input * input, Output * output) { + if (!output->isRequired() || !**input) { - m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); + return; } - m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); - } - break; - - case RenderTargetType::Texture: - { - const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedTexture = static_cast(attachment); - if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) - { - m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); - } - - m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); - } - break; - - case RenderTargetType::Renderbuffer: - { - const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedRenderbuffer = static_cast(attachment); - if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) + switch ((**input)->attachmentType()) { - m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); + case AttachmentType::Color: + { + if (m_colorValueInputs.size() <= colorAttachmentIndex) + { + return; + } + + auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + + fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(colorAttachmentIndex), **m_colorValueInputs.at(colorAttachmentIndex)); + + ++colorAttachmentIndex; + } + break; + case AttachmentType::Depth: + { + if (m_depthValueInputs.size() <= depthAttachmentIndex) + { + return; + } + + auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + + fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex), 0); + + ++depthAttachmentIndex; + } + break; + case AttachmentType::DepthStencil: + { + if (m_depthStencilValueInputs.size() <= depthStencilAttachmentIndex) + { + return; + } + + auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + + fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(depthAttachmentIndex), (**m_depthStencilValueInputs.at(depthAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).second); + + ++depthStencilAttachmentIndex; + } + break; + default: + break; } + }); - m_fbo->clearBuffer(gl::GL_COLOR, index, clearColor); - } - break; - - default: - return false; - } -} - -void ClearStage::clearDepthAttachment(gloperate::RenderTarget * target, float clearDepth) -{ - if (!target) - { - return; - } - - const auto attachmentIndex = gl::GL_DEPTH_ATTACHMENT; - - switch (target->type()) - { - case RenderTargetType::DefaultFBOAttachment: - m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), clearDepth, 0); - break; - - case RenderTargetType::UserDefinedFBOAttachment: - { - const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); - const auto targetAttachment = target->framebufferAttachment(); - - const auto targetAttachedTexture = static_cast(targetAttachment); - const auto targetAttachedRenderbuffer = static_cast(targetAttachment); - const auto fboAttachedTexture = static_cast(fboAttachment); - const auto fboAttachedRenderbuffer = static_cast(fboAttachment); - - if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) - { - m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); - } - else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) - { - m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); - } - - m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); - } - break; - - case RenderTargetType::Texture: - { - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedTexture = static_cast(attachment); - if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) - { - m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); - } - - m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); - } - break; - - case RenderTargetType::Renderbuffer: - { - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedRenderbuffer = static_cast(attachment); - if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) - { - m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); - } - - m_fbo->clearBuffer(gl::GL_DEPTH, clearDepth, 0); - } - break; - - default: - return false; - } -} - -void ClearStage::clearDepthStencilAttachment(gloperate::RenderTarget * target, float clearDepth, int clearStencil) -{ - if (!target) - { - return; + // Reset OpenGL state + gl::glDisable(gl::GL_SCISSOR_TEST); } - const auto attachmentIndex = gl::GL_DEPTH_STENCIL_ATTACHMENT; - - switch (target->type()) - { - case RenderTargetType::DefaultFBOAttachment: - m_defaultFBO->clearBuffer(target->defaultFramebufferAttachment(), 0, clearDepth, clearStencil); - break; - - case RenderTargetType::UserDefinedFBOAttachment: - { - const auto fboAttachment = m_fbo->getAttachment(attachmentIndex); - const auto targetAttachment = target->framebufferAttachment(); - - const auto targetAttachedTexture = static_cast(targetAttachment); - const auto targetAttachedRenderbuffer = static_cast(targetAttachment); - const auto fboAttachedTexture = static_cast(fboAttachment); - const auto fboAttachedRenderbuffer = static_cast(fboAttachment); - - if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) - { - m_fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); - } - else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderbuffer() != targetAttachedRenderbuffer->renderbuffer())) - { - m_fbo->attachTexture(attachmentIndex, targetAttachedRenderbuffer->renderbuffer); - } - - m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); - } - break; - - case RenderTargetType::Texture: - { - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedTexture = static_cast(attachment); - if (!attachment->isTextureAttachment() || attachedTexture->texture() != target->textureAttachment()) - { - m_fbo->attachTexture(attachmentIndex, target->textureAttachment()); - } - - m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); - } - break; - - case RenderTargetType::Renderbuffer: - { - const auto attachment = m_fbo->getAttachment(attachmentIndex); - - const auto attachedRenderbuffer = static_cast(attachment); - if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != target->renderbufferAttachment()) - { - m_fbo->attachRenderBuffer(attachmentIndex, target->renderbufferAttachment()); - } - - m_fbo->clearBuffer(gl::GL_DEPTH_STENCIL, clearDepth, clearStencil); - } - break; - - default: - return false; - } + // Update outputs + renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); } - } // namespace gloperate diff --git a/source/gloperate/source/stages/base/RasterizationStage.cpp b/source/gloperate/source/stages/base/RasterizationStage.cpp index 25b8a760..9465f75a 100644 --- a/source/gloperate/source/stages/base/RasterizationStage.cpp +++ b/source/gloperate/source/stages/base/RasterizationStage.cpp @@ -17,13 +17,27 @@ CPPEXPOSE_COMPONENT(RasterizationStage, gloperate::Stage) RasterizationStage::RasterizationStage(Environment * environment, const std::string & name) : Stage(environment, "RasterizationStage", name) -, renderInterface(this) -, rasterize ("rasterize", this, true) -, drawable ("drawable", this) -, colorTexture ("colorTexture", this) -, fboOut ("fboOut", this) -, colorTextureOut("colorTextureOut", this) +, renderInterface( this) +, rasterize ("rasterize", this, true) +, drawable ("drawable", this) { + inputAdded.connect( [this] (gloperate::AbstractSlot * connectedInput) { + auto renderTargetInput = dynamic_cast *>(connectedInput); + + if (renderTargetInput) + { + renderInterface.addRenderTargetInput(renderTargetInput); + } + }); + + outputAdded.connect( [this] (gloperate::AbstractSlot * connectedOutput) { + auto renderTargetOutput = dynamic_cast *>(connectedOutput); + + if (renderTargetOutput) + { + renderInterface.addRenderTargetOutput(renderTargetOutput); + } + }); } RasterizationStage::~RasterizationStage() @@ -32,16 +46,23 @@ RasterizationStage::~RasterizationStage() void RasterizationStage::onProcess() { - // Get FBO - globjects::Framebuffer * fbo = *renderInterface.targetFBO; + if (!renderInterface.allRenderTargetsCompatible()) + { + cppassist::warning("gloperate") << "Framebuffer attachments not compatible"; + + return; + } // Check if rasterization is enabled if (*rasterize) { // Set viewport - const glm::vec4 & viewport = *renderInterface.deviceViewport; + const glm::vec4 & viewport = *renderInterface.viewport; gl::glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + // Configure FBO + auto fbo = renderInterface.configureFBO(m_fbo.get(), m_defaultFBO.get()); + // Bind FBO fbo->bind(gl::GL_FRAMEBUFFER); @@ -49,13 +70,13 @@ void RasterizationStage::onProcess() (*drawable)->draw(); // Unbind FBO - globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); + fbo->unbind(); } // Update outputs - fboOut.setValue(fbo); - colorTextureOut.setValue(*colorTexture); - renderInterface.rendered.setValue(true); + renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); } diff --git a/source/gloperate/source/stages/interfaces/CanvasInterface.cpp b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp new file mode 100644 index 00000000..92315665 --- /dev/null +++ b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp @@ -0,0 +1,27 @@ + +#include + + +namespace gloperate +{ + + +CanvasInterface::CanvasInterface(Stage * stage) +: viewport ("viewport", stage) +, backgroundColor("backgroundColor", stage) +, frameCounter ("frameCounter", stage) +, timeDelta ("timeDelta", stage) +{ + // Hide inputs in property editor + viewport .setOption("hidden", true); + backgroundColor.setOption("hidden", true); + frameCounter .setOption("hidden", true); + timeDelta .setOption("hidden", true); +} + +CanvasInterface::~CanvasInterface() +{ +} + + +} // namespace gloperate diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 36701ba5..acfe0bf3 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -1,33 +1,212 @@ #include +#include + +#include + +#include +#include +#include +#include + +#include +#include + namespace gloperate { RenderInterface::RenderInterface(Stage * stage) -: deviceViewport ("deviceViewport", stage) -, virtualViewport("virtualViewport", stage) -, backgroundColor("backgroundColor", stage) -, frameCounter ("frameCounter", stage) -, timeDelta ("timeDelta", stage) -, renderTarget ("renderTarget", stage) -, renderTargetOut("renderTargetOut", stage) +: viewport("viewport", stage) { // Hide inputs in property editor - deviceViewport .setOption("hidden", true); - virtualViewport.setOption("hidden", true); - backgroundColor.setOption("hidden", true); - frameCounter .setOption("hidden", true); - timeDelta .setOption("hidden", true); - renderTarget .setOption("hidden", true); - renderTargetOut.setOption("hidden", true); + viewport.setOption("hidden", true); } RenderInterface::~RenderInterface() { } +bool RenderInterface::allRenderTargetsCompatible() const +{ + if (renderTargetInputSize() == 0) + { + return true; + } + + auto numberOfDepthAttachments = std::count_if(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { + return input ? (**input)->attachmentType() == AttachmentType::Depth || (**input)->attachmentType() == AttachmentType::DepthStencil : false; + }); + + auto allDefaultFramebufferAttachments = std::all_of(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { + return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }); + + auto allUserDefinedFramebufferAttachments = std::all_of(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { + return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }); + + return allDefaultFramebufferAttachments != allUserDefinedFramebufferAttachments && numberOfDepthAttachments <= 1; +} + +size_t RenderInterface::renderTargetInputSize() const +{ + return m_renderTargetInputs.size(); +} + +const std::vector *> & RenderInterface::renderTargetInputs() const +{ + return m_renderTargetInputs; +} + +Input * RenderInterface::renderTargetInput(size_t index) const +{ + return m_renderTargetInputs.size() > index ? m_renderTargetInputs.at(index) : nullptr; +} + +RenderTarget * RenderInterface::inputRenderTarget(size_t index) const +{ + const auto input = renderTargetInput(index); + + return input ? **input : nullptr; +} + +size_t RenderInterface::renderTargetOutputSize() const +{ + return m_renderTargetOutputs.size(); +} + +const std::vector *> & RenderInterface::renderTargetOutputs() const +{ + return m_renderTargetOutputs; +} + +Output * RenderInterface::renderTargetOutput(size_t index) const +{ + return m_renderTargetOutputs.size() > index ? m_renderTargetOutputs.at(index) : nullptr; +} + +RenderTarget * RenderInterface::outputRenderTarget(size_t index) const +{ + const auto output = renderTargetOutput(index); + + return output ? **output : nullptr; +} + +void RenderInterface::addRenderTargetInput(Input * input) +{ + m_renderTargetInputs.push_back(input); +} + +void RenderInterface::addRenderTargetOutput(Output * input) +{ + m_renderTargetOutputs.push_back(input); +} + +void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) +{ + const auto end = includeIncompletePairs + ? std::min(m_renderTargetInputs.size(), m_renderTargetOutputs.size()) + : std::max(m_renderTargetInputs.size(), m_renderTargetOutputs.size()); + + for (auto i = size_t(0); i < end; ++i) + { + callback(renderTargetInput(i), renderTargetOutput(i)); + } +} + +globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const +{ + assert(allRenderTargetsCompatible()); + + globjects::Framebuffer * currentFBO = nullptr; + auto colorAttachmentIndex = size_t(0); + for (auto input : m_renderTargetInputs) + { + auto nextFBO = configureFBO(colorAttachmentIndex, **input, fbo, defaultFBO); + + if (!currentFBO) + { + currentFBO = nextFBO; + } + + assert(nextFBO == currentFBO); + + if ((**input)->attachmentType() == AttachmentType::Color) + { + ++colorAttachmentIndex; + } + } + + return currentFBO; +} + +globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) +{ + const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + + switch (renderTarget->type()) + { + case RenderTargetType::DefaultFBOAttachment: + return defaultFBO; + + case RenderTargetType::UserDefinedFBOAttachment: + { + const auto fboAttachment = fbo->getAttachment(attachmentIndex); + const auto targetAttachment = renderTarget->framebufferAttachment(); + + const auto targetAttachedTexture = static_cast(targetAttachment); + const auto targetAttachedRenderbuffer = static_cast(targetAttachment); + const auto fboAttachedTexture = static_cast(fboAttachment); + const auto fboAttachedRenderbuffer = static_cast(fboAttachment); + + if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) + { + fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); + } + else if (fboAttachment->isRenderBufferAttachment() && (!targetAttachment->isRenderBufferAttachment() || fboAttachedRenderbuffer->renderBuffer() != targetAttachedRenderbuffer->renderBuffer())) + { + fbo->attachRenderBuffer(attachmentIndex, targetAttachedRenderbuffer->renderBuffer()); + } + + return fbo; + } + break; + + case RenderTargetType::Texture: + { + const auto attachment = fbo->getAttachment(attachmentIndex); + + const auto attachedTexture = static_cast(attachment); + if (!attachment->isTextureAttachment() || attachedTexture->texture() != renderTarget->textureAttachment()) + { + fbo->attachTexture(attachmentIndex, renderTarget->textureAttachment()); + } + + return fbo; + } + break; + + case RenderTargetType::Renderbuffer: + { + const auto attachment = fbo->getAttachment(attachmentIndex); + + const auto attachedRenderbuffer = static_cast(attachment); + if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != renderTarget->renderbufferAttachment()) + { + fbo->attachRenderBuffer(attachmentIndex, renderTarget->renderbufferAttachment()); + } + + return fbo; + } + break; + + default: + return nullptr; + } +} + } // namespace gloperate diff --git a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp index 1109b3f1..ef862913 100644 --- a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp +++ b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp @@ -215,8 +215,7 @@ void FFMPEGVideoExporter::initialize(ContextHandling contextHandling) m_fbo->clearBuffer(gl::GL_COLOR, 0, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}); - m_savedDeviceViewport = m_canvas->deviceViewport(); - m_savedVirtualViewport = m_canvas->virtualViewport(); + m_savedViewport = m_canvas->viewport(); m_canvas->setViewport(viewport, viewport); @@ -243,7 +242,7 @@ void FFMPEGVideoExporter::finalize() m_canvas->openGLContext()->release(); } - m_canvas->setViewport(m_savedDeviceViewport, m_savedVirtualViewport); + m_canvas->setViewport(m_savedViewport); m_initialized = false; } diff --git a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.h b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.h index 886ffc40..1776faa3 100644 --- a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.h +++ b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.h @@ -94,6 +94,5 @@ class FFMPEGVideoExporter : public gloperate::AbstractVideoExporter bool m_initialized; AbstractVideoExporter::ContextHandling m_contextHandling; - glm::vec4 m_savedDeviceViewport; - glm::vec4 m_savedVirtualViewport; + glm::vec4 m_savedViewport; }; From ffd2406588efdc456bf96dd2daf13e1914c78909 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 15 Jun 2017 17:10:52 +0200 Subject: [PATCH 04/33] Refactor Multiframe Aggregation, adjust ShapeDemo --- .../demo-stages-plugins/CMakeLists.txt | 64 ++--- .../demo-stages-plugins/ShapeDemo.cpp | 38 +-- .../examples/demo-stages-plugins/ShapeDemo.h | 7 +- source/gloperate-glkernel/CMakeLists.txt | 2 + .../IntermediateFramePreparationStage.h | 83 ++++++ .../stages/MultiFrameAggregationPipeline.h | 41 +-- .../stages/MultiFrameAggregationStage.h | 13 +- .../IntermediateFramePreparationStage.cpp | 84 ++++++ .../stages/MultiFrameAggregationPipeline.cpp | 249 +++++++++++++----- .../stages/MultiFrameAggregationStage.cpp | 43 +-- .../stages/interfaces/CanvasInterface.h | 4 +- .../stages/base/BasicFramebufferStage.cpp | 2 + .../source/stages/base/ClearStage.cpp | 17 +- .../source/stages/base/RasterizationStage.cpp | 17 -- .../stages/interfaces/CanvasInterface.cpp | 3 +- .../stages/interfaces/RenderInterface.cpp | 18 ++ .../FFMPEGVideoExporter.cpp | 4 +- 17 files changed, 490 insertions(+), 199 deletions(-) create mode 100644 source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h create mode 100644 source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp diff --git a/source/examples/demo-stages-plugins/CMakeLists.txt b/source/examples/demo-stages-plugins/CMakeLists.txt index fa255a8e..8525a67c 100644 --- a/source/examples/demo-stages-plugins/CMakeLists.txt +++ b/source/examples/demo-stages-plugins/CMakeLists.txt @@ -40,44 +40,44 @@ set(source_path "${CMAKE_CURRENT_SOURCE_DIR}") set(headers ${include_path}/ShapeDemo.h - ${include_path}/ShaderDemoPipeline.h - ${include_path}/DemoAntialiasableTriangleStage.h - ${include_path}/DemoAntialiasingPipeline.h - ${include_path}/DemoDOFCubeStage.h - ${include_path}/DemoDOFPipeline.h - ${include_path}/DemoSSAORenderingStage.h - ${include_path}/DemoSSAOPostprocessingStage.h - ${include_path}/DemoSSAOPipeline.h - ${include_path}/DemoTransparencyStage.h - ${include_path}/DemoTransparencyPipeline.h - ${include_path}/DemoMultiFramePipeline.h - ${include_path}/DemoDrawableStage.h - ${include_path}/LightTestStage.h - ${include_path}/LightTestPipeline.h - ${include_path}/DemoTextRenderingPipeline.h - ${include_path}/GlyphSequenceDemoStage.h +# ${include_path}/ShaderDemoPipeline.h +# ${include_path}/DemoAntialiasableTriangleStage.h +# ${include_path}/DemoAntialiasingPipeline.h +# ${include_path}/DemoDOFCubeStage.h +# ${include_path}/DemoDOFPipeline.h +# ${include_path}/DemoSSAORenderingStage.h +# ${include_path}/DemoSSAOPostprocessingStage.h +# ${include_path}/DemoSSAOPipeline.h +# ${include_path}/DemoTransparencyStage.h +# ${include_path}/DemoTransparencyPipeline.h +# ${include_path}/DemoMultiFramePipeline.h +# ${include_path}/DemoDrawableStage.h +# ${include_path}/LightTestStage.h +# ${include_path}/LightTestPipeline.h +# ${include_path}/DemoTextRenderingPipeline.h +# ${include_path}/GlyphSequenceDemoStage.h ) set(sources ${source_path}/plugin.cpp ${source_path}/ShapeDemo.cpp - ${source_path}/ShaderDemoPipeline.cpp - ${source_path}/DemoAntialiasableTriangleStage.cpp - ${source_path}/DemoAntialiasingPipeline.cpp - ${source_path}/DemoDOFCubeStage.cpp - ${source_path}/DemoDOFPipeline.cpp - ${source_path}/DemoSSAORenderingStage.cpp - ${source_path}/DemoSSAOPostprocessingStage.cpp - ${source_path}/DemoSSAOPipeline.cpp - ${source_path}/DemoTransparencyStage.cpp - ${source_path}/DemoTransparencyPipeline.cpp - ${source_path}/DemoMultiFramePipeline.cpp - ${source_path}/DemoDrawableStage.cpp - ${source_path}/LightTestStage.cpp - ${source_path}/LightTestPipeline.cpp - ${source_path}/DemoTextRenderingPipeline.cpp - ${source_path}/GlyphSequenceDemoStage.cpp +# ${source_path}/ShaderDemoPipeline.cpp +# ${source_path}/DemoAntialiasableTriangleStage.cpp +# ${source_path}/DemoAntialiasingPipeline.cpp +# ${source_path}/DemoDOFCubeStage.cpp +# ${source_path}/DemoDOFPipeline.cpp +# ${source_path}/DemoSSAORenderingStage.cpp +# ${source_path}/DemoSSAOPostprocessingStage.cpp +# ${source_path}/DemoSSAOPipeline.cpp +# ${source_path}/DemoTransparencyStage.cpp +# ${source_path}/DemoTransparencyPipeline.cpp +# ${source_path}/DemoMultiFramePipeline.cpp +# ${source_path}/DemoDrawableStage.cpp +# ${source_path}/LightTestStage.cpp +# ${source_path}/LightTestPipeline.cpp +# ${source_path}/DemoTextRenderingPipeline.cpp +# ${source_path}/GlyphSequenceDemoStage.cpp ) # Group source files diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index f9c5a706..4c85150f 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include #include #include +#include CPPEXPOSE_COMPONENT(ShapeDemo, gloperate::Stage) @@ -30,12 +30,13 @@ using namespace gloperate; ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) : Pipeline(environment, "ShapeDemo", name) -, renderInterface(this) +, canvasInterface(this) , shape("shape", this, ShapeType::Box) , texture("texture", this) , angle("angle", this, 0.0f) , rotate("rotate", this, false) , color("color", this, Color(255, 255, 255, 255)) +, m_colorTarget(cppassist::make_unique()) , m_timer(cppassist::make_unique(environment, "Timer")) , m_trackball(cppassist::make_unique(environment, "Trackball")) , m_shape(cppassist::make_unique(environment, "Shape")) @@ -50,6 +51,8 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , m_colorizeRenderPass(cppassist::make_unique(environment, "ColorizeRenderPass")) , m_colorizeRasterization(cppassist::make_unique(environment, "ColorizeRasterization")) { + m_colorTarget->setAttachmentType(gloperate::AttachmentType::Color); + // Get data path std::string dataPath = gloperate::dataPath(); @@ -68,7 +71,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Trackball stage addStage(m_trackball.get()); - m_trackball->viewport << renderInterface.deviceViewport; + m_trackball->viewport << canvasInterface.viewport; // Shape stage addStage(m_shape.get()); @@ -81,18 +84,19 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Texture loader stage addStage(m_texture.get()); - m_texture->filename << texture; + m_texture->filename << this->texture; // Framebuffer stage addStage(m_framebuffer.get()); - m_framebuffer->viewport << renderInterface.deviceViewport; + m_framebuffer->viewport << canvasInterface.viewport; // Clear stage addStage(m_clear.get()); - m_clear->renderInterface.targetFBO << m_framebuffer->fbo; - m_clear->renderInterface.deviceViewport << renderInterface.deviceViewport; - m_clear->renderInterface.backgroundColor = Color(0.0f, 0.0f, 0.0f, 1.0f); - m_clear->colorTexture << m_framebuffer->colorTexture; + m_clear->createInput("ColorAttachment") << m_framebuffer->colorBuffer; + m_clear->createInput("DepthAttachment") << m_framebuffer->depthBuffer; + m_clear->renderInterface.viewport << canvasInterface.viewport; + + // Invalidation of Clear Stage if new rendering should take place m_clear->createInput("renderPass") << m_shapeRenderPass->renderPass; // Transform stage for shape @@ -116,10 +120,10 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Rasterization stage for shape addStage(m_shapeRasterization.get()); - m_shapeRasterization->renderInterface.targetFBO << m_clear->fboOut; - m_shapeRasterization->renderInterface.deviceViewport << renderInterface.deviceViewport; + m_shapeRasterization->createInput("ColorAttachment") << *m_clear->createOutput("ColorAttachmentOut"); + m_shapeRasterization->createInput("DepthAttachment") << *m_clear->createOutput("DepthAttachmentOut"); + m_shapeRasterization->renderInterface.viewport << canvasInterface.viewport; m_shapeRasterization->drawable << m_shapeRenderPass->renderPass; - m_shapeRasterization->colorTexture << m_clear->colorTextureOut; // Colorize program stage addStage(m_colorizeProgram.get()); @@ -132,16 +136,16 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRenderPass->program << m_colorizeProgram->program; m_colorizeRenderPass->culling = false; m_colorizeRenderPass->createInput("color") << this->color; - m_colorizeRenderPass->createInput("source") << m_shapeRasterization->colorTextureOut; + m_colorizeRenderPass->createInput("source") << m_framebuffer->colorTexture; // Colorize rasterization stage addStage(m_colorizeRasterization.get()); - m_colorizeRasterization->renderInterface.targetFBO << renderInterface.targetFBO; - m_colorizeRasterization->renderInterface.deviceViewport << renderInterface.deviceViewport; + m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color"); + m_colorizeRasterization->renderInterface.viewport << canvasInterface.viewport; m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; // Outputs - renderInterface.rendered << m_colorizeRasterization->renderInterface.rendered; + *createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); // Start rotation rotate = true; @@ -177,7 +181,7 @@ void ShapeDemo::onRotateChanged(const bool & rotate) // Connect angle to timer and resume timer angle << m_timer->virtualTime; - m_timer->timeDelta << renderInterface.timeDelta; + m_timer->timeDelta << canvasInterface.timeDelta; } // Switch rotation off diff --git a/source/examples/demo-stages-plugins/ShapeDemo.h b/source/examples/demo-stages-plugins/ShapeDemo.h index fbe6f477..2db67a56 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.h +++ b/source/examples/demo-stages-plugins/ShapeDemo.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include namespace gloperate @@ -51,7 +51,7 @@ class ShapeDemo : public gloperate::Pipeline public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs Input shape; ///< Shape type @@ -87,6 +87,9 @@ class ShapeDemo : public gloperate::Pipeline protected: + // Misc + std::unique_ptr m_colorTarget; + // Stages std::unique_ptr m_timer; ///< Timer for continuous rendering and animation diff --git a/source/gloperate-glkernel/CMakeLists.txt b/source/gloperate-glkernel/CMakeLists.txt index 94641a9b..ed66e6f7 100644 --- a/source/gloperate-glkernel/CMakeLists.txt +++ b/source/gloperate-glkernel/CMakeLists.txt @@ -38,6 +38,7 @@ set(headers ${include_path}/stages/MultiFrameAggregationPipeline.h ${include_path}/stages/MultiFrameAggregationStage.h ${include_path}/stages/MultiFrameControlStage.h + ${include_path}/stages/IntermediateFramePreparationStage.h ${include_path}/stages/DiscDistributionKernelStage.h ${include_path}/stages/HemisphereDistributionKernelStage.h @@ -49,6 +50,7 @@ set(sources ${source_path}/stages/MultiFrameAggregationPipeline.cpp ${source_path}/stages/MultiFrameAggregationStage.cpp ${source_path}/stages/MultiFrameControlStage.cpp + ${source_path}/stages/IntermediateFramePreparationStage.cpp ${source_path}/stages/DiscDistributionKernelStage.cpp ${source_path}/stages/HemisphereDistributionKernelStage.cpp diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h new file mode 100644 index 00000000..9fb41460 --- /dev/null +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h @@ -0,0 +1,83 @@ + +#pragma once + + +#include + +#include + +#include +#include +#include + +#include + + +namespace gloperate_glkernel +{ + + +/** +* @brief +* Stage that ensures the intermediate frame is stored in a texture for further aggregation +*/ +class GLOPERATE_GLKERNEL_API IntermediateFramePreparationStage : public gloperate::Stage +{ +public: + CPPEXPOSE_DECLARE_COMPONENT( + IntermediateFramePreparationStage, gloperate::Stage + , "" + , "" + , "" + , "Stage that ensures the intermediate frame is in the outer color attachment" + , GLOPERATE_AUTHOR_ORGANIZATION + , "v0.1.0" + ) + + +public: + // Render Interface + gloperate::RenderInterface renderInterface; ///< Render interface for aggregation target + + // Inputs + Input intermediateRenderTarget; ///< Intermediate frame render target + Input intermediateFrameTexture; ///< Designated intermediate frame texture + + // Outputs + Output intermediateFrameTextureOut; ///< Intermediate frame texture with same contents as intermediateRenderTarget + + +public: + /** + * @brief + * Constructor + * + * @param[in] environment + * Environment to which the stage belongs (must NOT be null!) + * @param[in] name + * Stage name + */ + IntermediateFramePreparationStage(gloperate::Environment * environment, const std::string & name = "IntermediateFramePreparationStage"); + + /** + * @brief + * Destructor + */ + virtual ~IntermediateFramePreparationStage(); + + +protected: + // Virtual Stage interface + virtual void onContextInit(gloperate::AbstractGLContext * context) override; + virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; + virtual void onProcess() override; + +protected: + // Data + std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets + std::unique_ptr m_fbo; ///< Framebuffer for render targets + std::unique_ptr m_targetFBO; ///< Framebuffer for blitting target +}; + + +} // namespace gloperate_glkernel diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h index 15be5276..6ad97906 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -26,6 +27,7 @@ namespace gloperate_glkernel class MultiFrameControlStage; class MultiFrameAggregationStage; +class IntermediateFramePreparationStage; /** @@ -48,11 +50,13 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs Input multiFrameCount; ///< Maximum number of frames to aggregate + // Additional Inputs + public: /** @@ -72,37 +76,34 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P */ virtual ~MultiFrameAggregationPipeline(); - /** - * @brief - * Set the frame generating stage/pipeline - * - * @param[in] interface - * Render interface of the frame generating stage - */ - void setFrameRenderer(gloperate::RenderInterface & interface); - protected: // Virtual Stage interface - virtual void onProcess() override; + //virtual void onProcess() override; // Helper functions - void connectBasicRenderInterface(gloperate::RenderInterface & interface); void disconnectRenderStage(); + /** + * @brief + * Set the intermediate frame generating stage/pipeline + * + * @param[in] stage + * The render stage + */ + void setRenderStage(gloperate::Stage * stage); + protected: // Aggregation stages - std::unique_ptr m_renderFramebufferStage; ///< FBO stage for frame generating stage - std::unique_ptr m_aggregationColorTextureStage; ///< Aggregation color texture - std::unique_ptr m_aggregationDepthTextureStage; ///< Aggregation depth texture - std::unique_ptr m_aggregationFramebufferStage; ///< Aggregation FBO - std::unique_ptr m_controlStage; ///< Multiframe control stage - std::unique_ptr m_aggregationStage; ///< Aggregation stage - std::unique_ptr m_blitStage; ///< Blit stage + std::unique_ptr m_colorRenderTargetStage; ///< Aggregation color render target + std::unique_ptr m_depthStencilRenderTargetStage; ///< Aggregation depth stencil render target + std::unique_ptr m_controlStage; ///< Multiframe control stage + std::unique_ptr m_framePreparationStage; ///< Intermediate frame preparation stage + std::unique_ptr m_aggregationStage; ///< Aggregation stage // Inserted Stage/Pipeline - Stage * m_frameRenderStage; ///< Frame generating stage + Stage * m_renderStage; ///< Actual rendering stage, providing intermediate frames }; diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h index e12d172c..25b3a6eb 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h @@ -39,14 +39,12 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag public: - // Inputs - Input sourceTexture; ///< Current frame texture - Input targetTexture; ///< Aggregation target texture - Input viewport; ///< Target viewport - Input aggregationFactor; ///< Weight of new frame in current aggregation + // Render Interface + gloperate::RenderInterface renderInterface; ///< Render interface for aggregation target - // Outputs - Output aggregatedTexture; ///< Aggregation target texture (passed for stage chaining) + // Inputs + Input intermediateFrame; ///< Current frame texture + Input aggregationFactor; ///< Weight of new frame in current aggregation public: @@ -77,6 +75,7 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag protected: // Data std::unique_ptr m_triangle; ///< Screen-aligned Triangle for 'blitting' + std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets std::unique_ptr m_fbo; ///< Framebuffer for render targets }; diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp new file mode 100644 index 00000000..a33aecbc --- /dev/null +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -0,0 +1,84 @@ + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + + +namespace gloperate_glkernel +{ + + +CPPEXPOSE_COMPONENT(IntermediateFramePreparationStage, gloperate::Stage) + + +IntermediateFramePreparationStage::IntermediateFramePreparationStage(gloperate::Environment * environment, const std::string & name) +: Stage(environment, name) +, renderInterface (this) +, intermediateRenderTarget("intermediateRenderTarget", this) +, intermediateFrameTexture("intermediateFrameTexture", this) +, intermediateFrameTextureOut("intermediateFrameTextureOut", this) +{ +} + +IntermediateFramePreparationStage::~IntermediateFramePreparationStage() +{ +} + +void IntermediateFramePreparationStage::onContextInit(gloperate::AbstractGLContext * /*context*/) +{ + m_defaultFBO = globjects::Framebuffer::defaultFBO(); + m_fbo = cppassist::make_unique(); + m_targetFBO = cppassist::make_unique(); +} + +void IntermediateFramePreparationStage::onContextDeinit(gloperate::AbstractGLContext * /*context*/) +{ + m_defaultFBO = nullptr; + m_fbo = nullptr; + m_targetFBO = nullptr; +} + +void IntermediateFramePreparationStage::onProcess() +{ + if (!renderInterface.allRenderTargetsCompatible()) + { + cppassist::warning("gloperate") << "Framebuffer configuration not compatible"; + + return; + } + + if (intermediateRenderTarget->type() != gloperate::RenderTargetType::Texture + || intermediateRenderTarget->textureAttachment() != *intermediateFrameTexture) + { + std::array rect = {{ + static_cast(renderInterface.viewport->x), + static_cast(renderInterface.viewport->y), + static_cast(renderInterface.viewport->z), + static_cast(renderInterface.viewport->w) + }}; + + auto sourceFBO = renderInterface.configureFBO(0, *intermediateRenderTarget, m_fbo.get(), m_defaultFBO.get()); + auto sourceAttachment = (*intermediateRenderTarget)->attachmentRequiresUserDefinedFramebuffer() ? (*intermediateRenderTarget)->attachmentBuffer() : gl::GL_COLOR_ATTACHMENT0; + + auto targetFBO = m_targetFBO.get(); + auto targetAttachment = gl::GL_COLOR_ATTACHMENT0; + + targetFBO->attachTexture(gl::GL_COLOR_ATTACHMENT0, *intermediateFrameTexture); + + sourceFBO->blit(sourceAttachment, rect, targetFBO, targetAttachment, rect, gl::GL_COLOR_BUFFER_BIT, gl::GL_NEAREST); + } + + intermediateFrameTextureOut.setValue(*intermediateFrameTexture); +} + + +} // namespace gloperate_glkernel diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index a0afafef..9807e34e 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -10,6 +10,106 @@ #include #include +#include + + +namespace +{ + + +template +gloperate::Slot * getSlot(gloperate::Stage * stage, const std::string & name) +{ + if (!stage) { + return nullptr; + } else { + return static_cast *>(stage->property(name)); + } +} + +template +gloperate::Input * getInput(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return nullptr; + } + + const auto & inputs = stage->inputs(); + + const auto it = std::find_if(inputs.begin(), inputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto input = dynamic_cast *>(slot); + + if (!input) + { + return false; + } + + return callback(input); + }); + + if (it == inputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + +template +void forAllInputs(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return; + } + + const auto & inputs = stage->inputs(); + + for (const auto input : inputs) + { + const auto inputT = dynamic_cast *>(input); + + if (!inputT) + { + continue; + } + + callback(inputT); + } +} + +template +gloperate::Output * getOutput(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return nullptr; + } + + const auto & outputs = stage->outputs(); + + const auto it = std::find_if(outputs.begin(), outputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto output = dynamic_cast *>(slot); + + if (!output) + { + return false; + } + + return callback(output); + }); + + if (it == outputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + + +} namespace gloperate_glkernel @@ -21,110 +121,127 @@ CPPEXPOSE_COMPONENT(MultiFrameAggregationPipeline, gloperate::Stage) MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environment * environment, const std::string & name) : Pipeline(environment, name) -, renderInterface(this) +// Inputs +, canvasInterface(this) , multiFrameCount("multiFrameCount", this, 64) -, m_renderFramebufferStage(cppassist::make_unique(environment, "RenderFramebufferStage")) -, m_aggregationColorTextureStage(cppassist::make_unique(environment, "ColorTextureStage")) -, m_aggregationDepthTextureStage(cppassist::make_unique(environment, "DepthTextureStage")) -, m_aggregationFramebufferStage(cppassist::make_unique(environment, "AccumulationFramebufferStage")) +// Stages +, m_colorRenderTargetStage(cppassist::make_unique(environment, "ColorStage")) +, m_depthStencilRenderTargetStage(cppassist::make_unique(environment, "DepthStencilStage")) , m_controlStage(cppassist::make_unique(environment, "MultiFrameControlStage")) +, m_framePreparationStage(cppassist::make_unique(environment, "IntermediateFramePreparationStage")) , m_aggregationStage(cppassist::make_unique(environment, "MultiFrameAggregationStage")) -, m_blitStage(cppassist::make_unique(environment, "BlitStage")) -, m_frameRenderStage(nullptr) +// Additional Stages +, m_renderStage(nullptr) { - addStage(m_renderFramebufferStage.get()); - m_renderFramebufferStage->viewport << renderInterface.deviceViewport; - - addStage(m_aggregationColorTextureStage.get()); - m_aggregationColorTextureStage->size << renderInterface.deviceViewport; - m_aggregationColorTextureStage->format.setValue(gl::GL_RGBA); - m_aggregationColorTextureStage->internalFormat.setValue(gl::GL_RGBA32F); - m_aggregationColorTextureStage->type.setValue(gl::GL_FLOAT); + canvasInterface.addRenderTargetInput(createInput("ColorTarget")); + canvasInterface.addRenderTargetOutput(createOutput("ColorTargetOut")); - addStage(m_aggregationDepthTextureStage.get()); - m_aggregationDepthTextureStage->size << renderInterface.deviceViewport; - m_aggregationDepthTextureStage->format.setValue(gl::GL_DEPTH_COMPONENT); - m_aggregationDepthTextureStage->internalFormat.setValue(gl::GL_DEPTH_COMPONENT); - m_aggregationDepthTextureStage->type.setValue(gl::GL_UNSIGNED_BYTE); + addStage(m_colorRenderTargetStage.get()); + m_colorRenderTargetStage->size << canvasInterface.viewport; + m_colorRenderTargetStage->format.setValue(gl::GL_RGBA); + m_colorRenderTargetStage->internalFormat.setValue(gl::GL_RGBA32F); + m_colorRenderTargetStage->type.setValue(gl::GL_FLOAT); - addStage(m_aggregationFramebufferStage.get()); - m_aggregationFramebufferStage->colorTexture << m_aggregationColorTextureStage->renderTarget; - m_aggregationFramebufferStage->depthTexture << m_aggregationDepthTextureStage->renderTarget; + addStage(m_depthStencilRenderTargetStage.get()); + m_depthStencilRenderTargetStage->size << canvasInterface.viewport; + m_depthStencilRenderTargetStage->format.setValue(gl::GL_DEPTH_STENCIL); + m_depthStencilRenderTargetStage->internalFormat.setValue(gl::GL_DEPTH24_STENCIL8); + m_depthStencilRenderTargetStage->type.setValue(gl::GL_UNSIGNED_INT_24_8); addStage(m_controlStage.get()); - m_controlStage->frameNumber << renderInterface.frameCounter; + m_controlStage->frameNumber << canvasInterface.frameCounter; m_controlStage->multiFrameCount << multiFrameCount; - m_controlStage->viewport << renderInterface.deviceViewport; + m_controlStage->viewport << canvasInterface.viewport; + + addStage(m_framePreparationStage.get()); + + // m_framePreparationStage->intermediateRenderTarget << ...; // later set by setRenderStage + m_framePreparationStage->intermediateFrameTexture << m_colorRenderTargetStage->texture; addStage(m_aggregationStage.get()); - m_aggregationStage->aggregationFBO << m_aggregationFramebufferStage->fbo; - m_aggregationStage->texture << m_renderFramebufferStage->colorTexture; - m_aggregationStage->viewport << renderInterface.deviceViewport; + (*m_aggregationStage->createInput("ColorTarget")) << (*canvasInterface.renderTargetInput(0)); + (*canvasInterface.renderTargetOutput(0)) << (*m_aggregationStage->createOutput("ColorTargetOut")); + m_aggregationStage->intermediateFrame << m_framePreparationStage->intermediateFrameTextureOut; // set by setRenderStage + m_aggregationStage->renderInterface.viewport << canvasInterface.viewport; m_aggregationStage->aggregationFactor << m_controlStage->aggregationFactor; - addStage(m_blitStage.get()); - m_blitStage->source << m_aggregationStage->aggregatedFBO; - m_blitStage->target << renderInterface.renderTarget; - m_blitStage->sourceViewport << renderInterface.deviceViewport; - m_blitStage->targetViewport << renderInterface.deviceViewport; + stageAdded.connect([this](Stage * stage) { + setRenderStage(stage); + }); - renderInterface.renderTargetOut << m_blitStage->targetOut; + stageRemoved.connect([this](Stage * stage) { + if (m_renderStage == stage) + { + disconnectRenderStage(); + } + }); } MultiFrameAggregationPipeline::~MultiFrameAggregationPipeline() { } -void MultiFrameAggregationPipeline::onProcess() +/*void MultiFrameAggregationPipeline::onProcess() { - if (!m_frameRenderStage) + if (!m_renderStage) { return; } Pipeline::onProcess(); -} +}*/ -void MultiFrameAggregationPipeline::setFrameRenderer(gloperate::RenderInterface & interface) +void MultiFrameAggregationPipeline::setRenderStage(gloperate::Stage * stage) { disconnectRenderStage(); - m_frameRenderStage = interface.rendered.parentStage(); - addStage(m_frameRenderStage); - - connectBasicRenderInterface(interface); -} - -void MultiFrameAggregationPipeline::connectBasicRenderInterface(gloperate::RenderInterface & interface) -{ - interface.deviceViewport << renderInterface.deviceViewport; - interface.virtualViewport << renderInterface.virtualViewport; - interface.backgroundColor << renderInterface.backgroundColor; - interface.frameCounter << renderInterface.frameCounter; - interface.timeDelta << renderInterface.timeDelta; - interface.targetFBO << m_renderFramebufferStage->fbo; - - m_aggregationStage->textureRerendered << interface.rendered; + m_renderStage = stage; + + // Promote viewport information + auto slotViewport = getInput(m_renderStage, [](Input* input) { return input->name() == "viewport"; }); + (*slotViewport) << canvasInterface.viewport; + + // Update render stage input render targets + forAllInputs(m_renderStage, [this](Input * input) { + gloperate::RenderTarget * renderTarget = **input; + + switch (renderTarget->attachmentType()) + { + case gloperate::AttachmentType::Color: + (*input) << m_colorRenderTargetStage->renderTarget; + break; + case gloperate::AttachmentType::Depth: + (*input) << m_depthStencilRenderTargetStage->renderTarget; + break; + case gloperate::AttachmentType::DepthStencil: + (*input) << m_depthStencilRenderTargetStage->renderTarget; + break; + default: + input->setValue(nullptr); + } + }); + + // Connect Color Output + auto slotColorRenderTarget = getOutput(m_renderStage, [](Output * output) { + gloperate::RenderTarget * target = **output; + + return target->attachmentType() == gloperate::AttachmentType::Color; + }); + + if (slotColorRenderTarget) + { + m_framePreparationStage->intermediateRenderTarget << (*slotColorRenderTarget); + } } void MultiFrameAggregationPipeline::disconnectRenderStage() { - if (!m_frameRenderStage) + if (!m_renderStage) { return; } - // disconnect inputs - for (auto input : m_frameRenderStage->inputs()) - { - input->disconnect(); - } - - // disconnect outputs by disconnecting their receivers - m_aggregationStage->textureRerendered.disconnect(); - - // remove stage from pipeline - removeStage(m_frameRenderStage); + m_renderStage = nullptr; } diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp index bc55d969..afe17909 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp @@ -4,12 +4,12 @@ #include #include -#include -#include -#include -#include #include -#include +#include +#include + +#include +#include namespace gloperate_glkernel @@ -21,11 +21,9 @@ CPPEXPOSE_COMPONENT(MultiFrameAggregationStage, gloperate::Stage) MultiFrameAggregationStage::MultiFrameAggregationStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, name) -, sourceTexture("sourceTexture", this) -, targetTexture("targetTexture", this) -, viewport("viewport", this) +, renderInterface (this) +, intermediateFrame("intermediateFrame", this) , aggregationFactor("aggregationFactor", this) -, aggregatedTexture("aggregatedTexture", this) { } @@ -36,37 +34,50 @@ MultiFrameAggregationStage::~MultiFrameAggregationStage() void MultiFrameAggregationStage::onContextInit(gloperate::AbstractGLContext * /*context*/) { m_triangle = cppassist::make_unique(); + m_defaultFBO = globjects::Framebuffer::defaultFBO(); m_fbo = cppassist::make_unique(); } void MultiFrameAggregationStage::onContextDeinit(gloperate::AbstractGLContext * /*context*/) { m_triangle = nullptr; + m_defaultFBO = nullptr; m_fbo = nullptr; } void MultiFrameAggregationStage::onProcess() { + if (!renderInterface.allRenderTargetsCompatible()) + { + cppassist::warning("gloperate") << "Framebuffer configuration not compatible"; + + return; + } + + auto fbo = renderInterface.configureFBO(m_fbo.get(), m_defaultFBO.get()); + gl::glViewport( - 0, // Origin (0,0) because content was already shifted in main render pass - 0, // Applying the origin again would shift the result again - (*viewport).z, - (*viewport).w + renderInterface.viewport->x, + renderInterface.viewport->y, + renderInterface.viewport->z, + renderInterface.viewport->w ); - m_fbo->bind(gl::GL_FRAMEBUFFER); + fbo->bind(gl::GL_FRAMEBUFFER); gl::glBlendColor(0.0f, 0.0f, 0.0f, *aggregationFactor); gl::glBlendFunc(gl::GL_CONSTANT_ALPHA, gl::GL_ONE_MINUS_CONSTANT_ALPHA); gl::glBlendEquation(gl::GL_FUNC_ADD); gl::glEnable(gl::GL_BLEND); - m_triangle->setTexture(*sourceTexture); + m_triangle->setTexture(*intermediateFrame); m_triangle->draw(); gl::glDisable(gl::GL_BLEND); - aggregatedTexture.setValue(*targetTexture); + renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); } diff --git a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h index 4d440c39..9b079ca0 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -33,11 +34,10 @@ class RenderTarget; * and it will add the inputs and outputs directly to the stage (the interface * itself is not an object in the hierarchy). */ -class GLOPERATE_API CanvasInterface +class GLOPERATE_API CanvasInterface : public RenderInterface { public: // Inputs - Input viewport; ///< Viewport (in real device coordinates) Input backgroundColor; ///< Background color (RGBA) Input frameCounter; ///< Frame counter (number of frames) Input timeDelta; ///< Time delta since last frame (in seconds) diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 1bbe8b43..86398357 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -72,6 +72,7 @@ void BasicFramebufferStage::rebuildFBO() m_colorBuffer = cppassist::make_unique(); m_colorBuffer->setTarget(m_colorTexture.get()); + m_colorBuffer->setAttachmentType(AttachmentType::Color); // Create depth texture m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); @@ -79,6 +80,7 @@ void BasicFramebufferStage::rebuildFBO() m_depthBuffer = cppassist::make_unique(); m_depthBuffer->setTarget(m_depthTexture.get()); + m_depthBuffer->setAttachmentType(AttachmentType::Depth); // Create FBO m_fbo = cppassist::make_unique(); diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index cec0169f..27698150 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -23,17 +23,11 @@ ClearStage::ClearStage(Environment * environment, const std::string & name) , clear("clear", this) , renderInterface(this) { - inputAdded.connect( [this] (gloperate::AbstractSlot * connectedInput) { - auto renderTargetInput = dynamic_cast *>(connectedInput); + inputAdded.connect( [this] (AbstractSlot * connectedInput) { auto colorValueInput = dynamic_cast *>(connectedInput); auto depthValueInput = dynamic_cast *>(connectedInput); auto depthStencilValueInput = dynamic_cast> *>(connectedInput); - if (renderTargetInput) - { - renderInterface.addRenderTargetInput(renderTargetInput); - } - if (colorValueInput) { m_colorValueInputs.push_back(colorValueInput); @@ -49,15 +43,6 @@ ClearStage::ClearStage(Environment * environment, const std::string & name) m_depthStencilValueInputs.push_back(depthStencilValueInput); } }); - - outputAdded.connect( [this] (gloperate::AbstractSlot * connectedOutput) { - auto renderTargetOutput = dynamic_cast *>(connectedOutput); - - if (renderTargetOutput) - { - renderInterface.addRenderTargetOutput(renderTargetOutput); - } - }); } ClearStage::~ClearStage() diff --git a/source/gloperate/source/stages/base/RasterizationStage.cpp b/source/gloperate/source/stages/base/RasterizationStage.cpp index 9465f75a..18e158dc 100644 --- a/source/gloperate/source/stages/base/RasterizationStage.cpp +++ b/source/gloperate/source/stages/base/RasterizationStage.cpp @@ -21,23 +21,6 @@ RasterizationStage::RasterizationStage(Environment * environment, const std::str , rasterize ("rasterize", this, true) , drawable ("drawable", this) { - inputAdded.connect( [this] (gloperate::AbstractSlot * connectedInput) { - auto renderTargetInput = dynamic_cast *>(connectedInput); - - if (renderTargetInput) - { - renderInterface.addRenderTargetInput(renderTargetInput); - } - }); - - outputAdded.connect( [this] (gloperate::AbstractSlot * connectedOutput) { - auto renderTargetOutput = dynamic_cast *>(connectedOutput); - - if (renderTargetOutput) - { - renderInterface.addRenderTargetOutput(renderTargetOutput); - } - }); } RasterizationStage::~RasterizationStage() diff --git a/source/gloperate/source/stages/interfaces/CanvasInterface.cpp b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp index 92315665..e3ab1949 100644 --- a/source/gloperate/source/stages/interfaces/CanvasInterface.cpp +++ b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp @@ -7,13 +7,12 @@ namespace gloperate CanvasInterface::CanvasInterface(Stage * stage) -: viewport ("viewport", stage) +: RenderInterface(stage) , backgroundColor("backgroundColor", stage) , frameCounter ("frameCounter", stage) , timeDelta ("timeDelta", stage) { // Hide inputs in property editor - viewport .setOption("hidden", true); backgroundColor.setOption("hidden", true); frameCounter .setOption("hidden", true); timeDelta .setOption("hidden", true); diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index acfe0bf3..58ac30b5 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -23,6 +23,24 @@ RenderInterface::RenderInterface(Stage * stage) { // Hide inputs in property editor viewport.setOption("hidden", true); + + stage->inputAdded.connect( [this] (AbstractSlot * connectedInput) { + auto renderTargetInput = dynamic_cast *>(connectedInput); + + if (renderTargetInput) + { + addRenderTargetInput(renderTargetInput); + } + }); + + stage->outputAdded.connect( [this] (AbstractSlot * connectedOutput) { + auto renderTargetOutput = dynamic_cast *>(connectedOutput); + + if (renderTargetOutput) + { + addRenderTargetOutput(renderTargetOutput); + } + }); } RenderInterface::~RenderInterface() diff --git a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp index ef862913..4ca10fa6 100644 --- a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp +++ b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp @@ -156,7 +156,7 @@ void FFMPEGVideoExporter::onRender(ContextHandling contextHandling, globjects::F m_canvas->render(m_fbo.get()); - auto destVP = m_savedDeviceViewport; + auto destVP = m_savedViewport; std::array srcRect = {{int(viewport.x), int(viewport.y), int(viewport.z), int(viewport.w)}}; std::array destRect = {{int(destVP.x), int(destVP.y), int(destVP.z), int(destVP.w)}}; @@ -217,7 +217,7 @@ void FFMPEGVideoExporter::initialize(ContextHandling contextHandling) m_savedViewport = m_canvas->viewport(); - m_canvas->setViewport(viewport, viewport); + m_canvas->setViewport(viewport); if (m_contextHandling == AbstractVideoExporter::ActivateContext) { From 329106d2163c110180b67cff560069c46cf19d22 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 15 Jun 2017 18:43:56 +0200 Subject: [PATCH 05/33] Fixes towards functioning ShapeDemo --- .../demo-stages-plugins/ShapeDemo.cpp | 8 +++- .../stages/base/RasterizationStage.h | 2 + source/gloperate/source/base/Canvas.cpp | 42 +++++++++++++++---- .../stages/base/BasicFramebufferStage.cpp | 25 +++++------ .../source/stages/base/RasterizationStage.cpp | 14 +++++++ .../stages/interfaces/RenderInterface.cpp | 35 +++++++++++++--- 6 files changed, 101 insertions(+), 25 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 4c85150f..aa30b694 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -138,9 +138,13 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRenderPass->createInput("color") << this->color; m_colorizeRenderPass->createInput("source") << m_framebuffer->colorTexture; + auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); + shapeColorOutput->setRequired(true); + shapeColorOutput->valueInvalidated.connect([this]() { m_colorizeRasterization->drawable.invalidate(); }); + // Colorize rasterization stage addStage(m_colorizeRasterization.get()); - m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color"); + m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color", m_colorTarget.get()); m_colorizeRasterization->renderInterface.viewport << canvasInterface.viewport; m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; @@ -178,6 +182,7 @@ void ShapeDemo::onRotateChanged(const bool & rotate) { // Set timer to current rotation value m_timer->virtualTime = *angle; + m_timer->virtualTime.setRequired(true); // Connect angle to timer and resume timer angle << m_timer->virtualTime; @@ -193,5 +198,6 @@ void ShapeDemo::onRotateChanged(const bool & rotate) // Stop time m_timer->timeDelta.disconnect(); + m_timer->virtualTime.setRequired(false); } } diff --git a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h index 543481f6..bb98d98a 100644 --- a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h +++ b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h @@ -73,6 +73,8 @@ class GLOPERATE_API RasterizationStage : public Stage protected: // Virtual Stage interface virtual void onProcess() override; + virtual void onContextInit(AbstractGLContext * content) override; + virtual void onContextDeinit(AbstractGLContext * content) override; protected: diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index c96dbcfa..1c7a436c 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -123,6 +123,29 @@ gloperate::Output * getOutput(gloperate::Stage * stage, std::function *>(*it); } +template +void forAllOutputs(gloperate::Stage * stage, std::function *)> callback) +{ + if (!stage) + { + return; + } + + const auto & outputs = stage->outputs(); + + for (const auto output : outputs) + { + const auto outputT = dynamic_cast *>(output); + + if (!outputT) + { + continue; + } + + callback(outputT); + } +} + auto s_nextCanvasId = size_t(0); @@ -283,7 +306,10 @@ void Canvas::updateTime() // Update timing auto slotTimeDelta = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "timeDelta"; }); - if (slotTimeDelta) slotTimeDelta->setValue(m_timeDelta); + if (slotTimeDelta) + { + slotTimeDelta->setValue(m_timeDelta); + } // Check if a redraw is required checkRedraw(); @@ -324,7 +350,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) debug(2, "gloperate") << "render(); " << "targetFBO: " << fboName; // Abort if not initialized - if (!m_initialized) return; + if (!m_initialized || !m_renderStage) return; // Check if the render stage is to be replaced if (m_replaceStage) @@ -347,12 +373,9 @@ void Canvas::render(globjects::Framebuffer * targetFBO) if (slotViewport) slotViewport->setValue(m_viewport); // Mark output as required - auto slotColorRenderTarget = getOutput(m_renderStage.get(), [](Output * output) { - RenderTarget * target = **output; - - return target->attachmentType() == AttachmentType::Color; + forAllOutputs(m_renderStage.get(), [](Output * output) { + output->setRequired(true); }); - if (slotColorRenderTarget) slotColorRenderTarget->setRequired(true); // Replace finished m_replaceStage = false; @@ -406,6 +429,11 @@ void Canvas::render(globjects::Framebuffer * targetFBO) forAllInputs(m_renderStage.get(), [this](Input * input) { gloperate::RenderTarget * renderTarget = **input; + if (renderTarget == nullptr) + { + return; + } + switch (renderTarget->attachmentType()) { case AttachmentType::Color: diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 86398357..1e7b357d 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -51,24 +51,26 @@ void BasicFramebufferStage::onProcess() { // Rebuild FBO (and textures) rebuildFBO(); - - // Update outputs - this->fbo.setValue(m_fbo.get()); - this->colorTexture.setValue(m_colorTexture.get()); - this->depthTexture.setValue(m_depthTexture.get()); - this->colorBuffer.setValue(m_colorBuffer.get()); - this->depthBuffer.setValue(m_depthBuffer.get()); } -} -void BasicFramebufferStage::rebuildFBO() -{ // Get texture size glm::ivec2 size = glm::ivec2((*this->viewport).z, (*this->viewport).w); + m_colorTexture->image2D(0, gl::GL_RGBA, size.x, size.y, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, nullptr); + m_depthTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_UNSIGNED_BYTE, nullptr); + + // Update outputs + this->fbo.setValue(m_fbo.get()); + this->colorTexture.setValue(m_colorTexture.get()); + this->depthTexture.setValue(m_depthTexture.get()); + this->colorBuffer.setValue(m_colorBuffer.get()); + this->depthBuffer.setValue(m_depthBuffer.get()); +} + +void BasicFramebufferStage::rebuildFBO() +{ // Create color texture m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - m_colorTexture->image2D(0, gl::GL_RGBA, size.x, size.y, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, nullptr); m_colorBuffer = cppassist::make_unique(); m_colorBuffer->setTarget(m_colorTexture.get()); @@ -76,7 +78,6 @@ void BasicFramebufferStage::rebuildFBO() // Create depth texture m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - m_depthTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_UNSIGNED_BYTE, nullptr); m_depthBuffer = cppassist::make_unique(); m_depthBuffer->setTarget(m_depthTexture.get()); diff --git a/source/gloperate/source/stages/base/RasterizationStage.cpp b/source/gloperate/source/stages/base/RasterizationStage.cpp index 18e158dc..242dce84 100644 --- a/source/gloperate/source/stages/base/RasterizationStage.cpp +++ b/source/gloperate/source/stages/base/RasterizationStage.cpp @@ -27,6 +27,18 @@ RasterizationStage::~RasterizationStage() { } +void RasterizationStage::onContextInit(AbstractGLContext *) +{ + m_defaultFBO = globjects::Framebuffer::defaultFBO(); + m_fbo = cppassist::make_unique(); +} + +void RasterizationStage::onContextDeinit(AbstractGLContext *) +{ + m_defaultFBO = nullptr; + m_fbo = nullptr; +} + void RasterizationStage::onProcess() { if (!renderInterface.allRenderTargetsCompatible()) @@ -49,6 +61,8 @@ void RasterizationStage::onProcess() // Bind FBO fbo->bind(gl::GL_FRAMEBUFFER); + fbo->printStatus(true); + // Render the drawable (*drawable)->draw(); diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 58ac30b5..1830b878 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -126,8 +126,8 @@ void RenderInterface::addRenderTargetOutput(Output * input) void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) { const auto end = includeIncompletePairs - ? std::min(m_renderTargetInputs.size(), m_renderTargetOutputs.size()) - : std::max(m_renderTargetInputs.size(), m_renderTargetOutputs.size()); + ? std::max(m_renderTargetInputs.size(), m_renderTargetOutputs.size()) + : std::min(m_renderTargetInputs.size(), m_renderTargetOutputs.size()); for (auto i = size_t(0); i < end; ++i) { @@ -139,6 +139,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * { assert(allRenderTargetsCompatible()); + std::vector drawBuffers; globjects::Framebuffer * currentFBO = nullptr; auto colorAttachmentIndex = size_t(0); for (auto input : m_renderTargetInputs) @@ -154,16 +155,29 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * if ((**input)->attachmentType() == AttachmentType::Color) { + drawBuffers.push_back(gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); ++colorAttachmentIndex; } } + currentFBO->setDrawBuffers(drawBuffers); + return currentFBO; } globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) { - const auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; + + if (renderTarget->attachmentType() == AttachmentType::Depth) + { + attachmentIndex = gl::GL_DEPTH_ATTACHMENT; + } + + if (renderTarget->attachmentType() == AttachmentType::DepthStencil) + { + attachmentIndex = gl::GL_DEPTH_STENCIL_ATTACHMENT; + } switch (renderTarget->type()) { @@ -180,7 +194,18 @@ globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarge const auto fboAttachedTexture = static_cast(fboAttachment); const auto fboAttachedRenderbuffer = static_cast(fboAttachment); - if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) + if (!fboAttachment) + { + if (targetAttachment->isTextureAttachment()) + { + fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); + } + else + { + fbo->attachRenderBuffer(attachmentIndex, targetAttachedRenderbuffer->renderBuffer()); + } + } + else if (fboAttachment->isTextureAttachment() && (!targetAttachment->isTextureAttachment() || fboAttachedTexture->texture() != targetAttachedTexture->texture())) { fbo->attachTexture(attachmentIndex, targetAttachedTexture->texture()); } @@ -198,7 +223,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarge const auto attachment = fbo->getAttachment(attachmentIndex); const auto attachedTexture = static_cast(attachment); - if (!attachment->isTextureAttachment() || attachedTexture->texture() != renderTarget->textureAttachment()) + if (!attachment || !attachment->isTextureAttachment() || attachedTexture->texture() != renderTarget->textureAttachment()) { fbo->attachTexture(attachmentIndex, renderTarget->textureAttachment()); } From efe27087995bae60720de0e29a496ffbca7cb2ba Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 16 Jun 2017 13:24:44 +0200 Subject: [PATCH 06/33] Fix erroneous usage of glGetInteger using non-defined enum values in Core profile (closes #351) --- .../gloperate/source/base/GLContextUtils.cpp | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/source/gloperate/source/base/GLContextUtils.cpp b/source/gloperate/source/base/GLContextUtils.cpp index eff71c0b..6476208d 100644 --- a/source/gloperate/source/base/GLContextUtils.cpp +++ b/source/gloperate/source/base/GLContextUtils.cpp @@ -51,30 +51,33 @@ gloperate::GLContextFormat GLContextUtils::retrieveFormat() format.setProfile(retrieveProfile()); - i = -1; glGetIntegerv(GLenum::GL_RED_BITS, &i); - format.setRedBufferSize(i); + if (format.profile() != GLContextFormat::Profile::Core) + { + i = -1; glGetIntegerv(GLenum::GL_RED_BITS, &i); + format.setRedBufferSize(i); + + i = -1; glGetIntegerv(GLenum::GL_GREEN_BITS, &i); + format.setGreenBufferSize(i); - i = -1; glGetIntegerv(GLenum::GL_GREEN_BITS, &i); - format.setGreenBufferSize(i); + i = -1; glGetIntegerv(GLenum::GL_BLUE_BITS, &i); + format.setBlueBufferSize(i); - i = -1; glGetIntegerv(GLenum::GL_BLUE_BITS, &i); - format.setBlueBufferSize(i); + i = -1; glGetIntegerv(GLenum::GL_ALPHA_BITS, &i); + format.setAlphaBufferSize(i); - i = -1; glGetIntegerv(GLenum::GL_ALPHA_BITS, &i); - format.setAlphaBufferSize(i); + i = -1; glGetIntegerv(GLenum::GL_DEPTH_BITS, &i); + format.setDepthBufferSize(i); - i = -1; glGetIntegerv(GLenum::GL_DEPTH_BITS, &i); - format.setDepthBufferSize(i); + i = -1; glGetIntegerv(GLenum::GL_STENCIL_BITS, &i); + format.setStencilBufferSize(i); - i = -1; glGetIntegerv(GLenum::GL_STENCIL_BITS, &i); - format.setStencilBufferSize(i); + b = GL_FALSE; glGetBooleanv(GLenum::GL_STEREO, &b); + format.setStereo(b == GL_TRUE); + } i = -1; glGetIntegerv(GLenum::GL_SAMPLES, &i); format.setSamples(i); - b = GL_FALSE; glGetBooleanv(GLenum::GL_STEREO, &b); - format.setStereo(b == GL_TRUE); - return format; } From ed19ec42826ea49b3e9b880c7ccfbd866b7016a9 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 16 Jun 2017 13:25:03 +0200 Subject: [PATCH 07/33] Fix default FBO rendering for ShapeDemo --- source/examples/gloperate-glfw-example/main.cpp | 3 +++ source/examples/gloperate-qt-example/main.cpp | 3 +++ source/gloperate-glfw/source/GLContextFactory.cpp | 1 + source/gloperate-qtquick/source/Application.cpp | 4 ++++ .../include/gloperate/rendering/RenderTarget.h | 12 ------------ source/gloperate/source/base/GLContextFormat.cpp | 7 +++---- .../source/stages/interfaces/RenderInterface.cpp | 2 +- 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/source/examples/gloperate-glfw-example/main.cpp b/source/examples/gloperate-glfw-example/main.cpp index 35fc0e43..8822746e 100644 --- a/source/examples/gloperate-glfw-example/main.cpp +++ b/source/examples/gloperate-glfw-example/main.cpp @@ -42,6 +42,9 @@ int main(int argc, char * argv[]) // Specify desired context format gloperate::GLContextFormat format; + format.setVersion(3, 2); + format.setProfile(gloperate::GLContextFormat::Profile::Core); + format.setForwardCompatible(true); if (!contextString.empty()) { diff --git a/source/examples/gloperate-qt-example/main.cpp b/source/examples/gloperate-qt-example/main.cpp index 5e69d1b3..555dd265 100644 --- a/source/examples/gloperate-qt-example/main.cpp +++ b/source/examples/gloperate-qt-example/main.cpp @@ -48,6 +48,9 @@ int main(int argc, char * argv[]) // Specify desired context format gloperate::GLContextFormat format; + format.setVersion(3, 2); + format.setProfile(gloperate::GLContextFormat::Profile::Core); + format.setForwardCompatible(true); if (!contextString.empty()) { diff --git a/source/gloperate-glfw/source/GLContextFactory.cpp b/source/gloperate-glfw/source/GLContextFactory.cpp index a737c27f..8004e3b1 100644 --- a/source/gloperate-glfw/source/GLContextFactory.cpp +++ b/source/gloperate-glfw/source/GLContextFactory.cpp @@ -70,6 +70,7 @@ void GLContextFactory::initializeGLFWState(const gloperate::GLContextFormat & fo // Set OpenGL version glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, format.majorVersion()); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, format.minorVersion()); + glfwWindowHint(GLFW_DOUBLEBUFFER, int(true)); // Set OpenGL context flags if (format.version() >= glbinding::Version(3, 0)) diff --git a/source/gloperate-qtquick/source/Application.cpp b/source/gloperate-qtquick/source/Application.cpp index c6daf8fa..fbc49ba0 100644 --- a/source/gloperate-qtquick/source/Application.cpp +++ b/source/gloperate-qtquick/source/Application.cpp @@ -55,6 +55,10 @@ Application::Application(int & argc, char ** argv) // Specify desired context format gloperate::GLContextFormat format; + format.setVersion(3, 2); + format.setProfile(gloperate::GLContextFormat::Profile::Core); + format.setForwardCompatible(true); + if (!contextFormat.empty()) { if (!format.initializeFromString(contextFormat)) diff --git a/source/gloperate/include/gloperate/rendering/RenderTarget.h b/source/gloperate/include/gloperate/rendering/RenderTarget.h index a52eece5..8fad5e6d 100644 --- a/source/gloperate/include/gloperate/rendering/RenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/RenderTarget.h @@ -116,18 +116,6 @@ class GLOPERATE_API RenderTarget */ void setTarget(globjects::FramebufferAttachment * fboAttachment); - /** - * @brief - * Bind render target to a framebuffer - * - * @param[in] renderbuffer - * Target framebuffer - * @param[in] bindingPoint - * Target binding point, e.g. gl::GL_DEPTH_ATTACHMENT - * Will be ignored if not applicable - */ - void bind(gl::GLenum bindingPoint, globjects::Framebuffer * fbo); - /** * @brief * Get current target type diff --git a/source/gloperate/source/base/GLContextFormat.cpp b/source/gloperate/source/base/GLContextFormat.cpp index 12812a10..24484edd 100644 --- a/source/gloperate/source/base/GLContextFormat.cpp +++ b/source/gloperate/source/base/GLContextFormat.cpp @@ -91,10 +91,9 @@ GLContextFormat::GLContextFormat() , m_samples(-1) , m_swapBehavior(SwapBehavior::DoubleBuffering) { -#ifdef __APPLE__ m_version = glbinding::Version(3,2); m_profile = Profile::Core; -#endif + m_forwardCompatibility = true; } GLContextFormat::~GLContextFormat() @@ -431,9 +430,9 @@ bool GLContextFormat::verifyPixelFormat(const GLContextFormat & requested) const issues.push_back("- Stereo Buffering requested, but not initialized."); } - if (requested.samples()) + if (requested.samples() > 0) { - if (!samples()) + if (samples() <= 0) { issues.push_back("- Sample Buffers requested, but none initialized."); } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 1830b878..b6499870 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -155,7 +155,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * if ((**input)->attachmentType() == AttachmentType::Color) { - drawBuffers.push_back(gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); + drawBuffers.push_back((**input)->type() == RenderTargetType::DefaultFBOAttachment ? (**input)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); ++colorAttachmentIndex; } } From ce40fd1eee624794ec33e96dcfae68e3b9d8df54 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 16 Jun 2017 16:41:49 +0200 Subject: [PATCH 08/33] Working ShapeDemo again --- .../demo-stages-plugins/ShapeDemo.cpp | 63 ++++++++++------ .../examples/demo-stages-plugins/ShapeDemo.h | 3 + .../IntermediateFramePreparationStage.cpp | 2 +- source/gloperate/CMakeLists.txt | 2 + .../include/gloperate/pipeline/Output.inl | 2 +- .../include/gloperate/pipeline/Stage.h | 3 + .../include/gloperate/pipeline/Stage.inl | 8 +++ .../stages/base/FloatSelectionStage.h | 71 +++++++++++++++++++ source/gloperate/source/base/Canvas.cpp | 23 +++--- .../source/pipeline/AbstractSlot.cpp | 12 ++-- source/gloperate/source/pipeline/Stage.cpp | 2 - .../source/stages/base/ClearStage.cpp | 8 +-- .../stages/base/FloatSelectionStage.cpp | 57 +++++++++++++++ 13 files changed, 209 insertions(+), 47 deletions(-) create mode 100644 source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h create mode 100644 source/gloperate/source/stages/base/FloatSelectionStage.cpp diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index aa30b694..33b3c481 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , color("color", this, Color(255, 255, 255, 255)) , m_colorTarget(cppassist::make_unique()) , m_timer(cppassist::make_unique(environment, "Timer")) +, m_floatSelection(cppassist::make_unique(environment, "FloatSelection")) , m_trackball(cppassist::make_unique(environment, "Trackball")) , m_shape(cppassist::make_unique(environment, "Shape")) , m_texture(cppassist::make_unique(environment, "Texture")) @@ -64,11 +66,20 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) angle.setOption("updateOnDrag", true); rotate.valueChanged.connect(this, &ShapeDemo::onRotateChanged); + m_timer->virtualTime.valueChanged.connect([this](const float & angle) { + // Set angle to current timer value + this->angle = angle; + }); // Timer stage addStage(m_timer.get()); m_timer->interval = 2.0f * glm::pi(); + addStage(m_floatSelection.get()); + m_floatSelection->createInput("timerValue") << m_timer->virtualTime; + m_floatSelection->createInput("angle") << angle; + m_floatSelection->index = 1u; + // Trackball stage addStage(m_trackball.get()); m_trackball->viewport << canvasInterface.viewport; @@ -90,18 +101,9 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) addStage(m_framebuffer.get()); m_framebuffer->viewport << canvasInterface.viewport; - // Clear stage - addStage(m_clear.get()); - m_clear->createInput("ColorAttachment") << m_framebuffer->colorBuffer; - m_clear->createInput("DepthAttachment") << m_framebuffer->depthBuffer; - m_clear->renderInterface.viewport << canvasInterface.viewport; - - // Invalidation of Clear Stage if new rendering should take place - m_clear->createInput("renderPass") << m_shapeRenderPass->renderPass; - // Transform stage for shape addStage(m_shapeTransform.get()); - m_shapeTransform->rotationAngle << angle; + m_shapeTransform->rotationAngle << m_floatSelection->value; // Program stage for shape addStage(m_shapeProgram.get()); @@ -118,6 +120,17 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_shapeRenderPass->createInput("color") << this->color; m_shapeRenderPass->createInput("tex0") << m_texture->texture; + // Clear stage + addStage(m_clear.get()); + m_clear->createInput("ColorAttachment") << m_framebuffer->colorBuffer; + m_clear->createInput("DepthAttachment") << m_framebuffer->depthBuffer; + m_clear->createInput("ColorValue") = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + m_clear->createInput("DepthValue") = 1.0f; + m_clear->renderInterface.viewport << canvasInterface.viewport; + + // Invalidation of Clear Stage if new rendering should take place + m_clear->createInput("renderPass") << m_shapeRenderPass->renderPass; + // Rasterization stage for shape addStage(m_shapeRasterization.get()); m_shapeRasterization->createInput("ColorAttachment") << *m_clear->createOutput("ColorAttachmentOut"); @@ -125,6 +138,10 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_shapeRasterization->renderInterface.viewport << canvasInterface.viewport; m_shapeRasterization->drawable << m_shapeRenderPass->renderPass; + auto colorTextureInput = m_shapeRasterization->createInput("ColorTexture"); + auto colorTextureOutput = m_shapeRasterization->createOutput("ColorTextureOut"); + *colorTextureInput << m_framebuffer->colorTexture; + // Colorize program stage addStage(m_colorizeProgram.get()); *m_colorizeProgram->createInput("shader1") = dataPath + "/gloperate/shaders/geometry/screenaligned.vert"; @@ -136,11 +153,18 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRenderPass->program << m_colorizeProgram->program; m_colorizeRenderPass->culling = false; m_colorizeRenderPass->createInput("color") << this->color; - m_colorizeRenderPass->createInput("source") << m_framebuffer->colorTexture; + m_colorizeRenderPass->createInput("source") << *colorTextureOutput; + /* Hack Start */ auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); - shapeColorOutput->setRequired(true); - shapeColorOutput->valueInvalidated.connect([this]() { m_colorizeRasterization->drawable.invalidate(); }); + shapeColorOutput->valueChanged.onFire([=]() { + colorTextureOutput->setValue(**colorTextureInput); + }); + shapeColorOutput->valueInvalidated.onFire([=]() { + m_clear->renderInterface.renderTargetOutput(0)->invalidate(); + m_clear->renderInterface.renderTargetOutput(1)->invalidate(); + }); + /* Hack End */ // Colorize rasterization stage addStage(m_colorizeRasterization.get()); @@ -182,22 +206,19 @@ void ShapeDemo::onRotateChanged(const bool & rotate) { // Set timer to current rotation value m_timer->virtualTime = *angle; - m_timer->virtualTime.setRequired(true); - // Connect angle to timer and resume timer - angle << m_timer->virtualTime; + // Switch angle to timer and resume timer m_timer->timeDelta << canvasInterface.timeDelta; + m_floatSelection->index = 0u; } // Switch rotation off else { - // Set angle to current timer value - angle.disconnect(); - angle = *m_timer->virtualTime; - // Stop time m_timer->timeDelta.disconnect(); - m_timer->virtualTime.setRequired(false); + + // Switch timer to angle + m_floatSelection->index = 1u; } } diff --git a/source/examples/demo-stages-plugins/ShapeDemo.h b/source/examples/demo-stages-plugins/ShapeDemo.h index 2db67a56..5e854439 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.h +++ b/source/examples/demo-stages-plugins/ShapeDemo.h @@ -28,6 +28,7 @@ namespace gloperate class TrackballStage; class TimerStage; class TransformStage; + class FloatSelectionStage; } @@ -93,6 +94,8 @@ class ShapeDemo : public gloperate::Pipeline // Stages std::unique_ptr m_timer; ///< Timer for continuous rendering and animation + std::unique_ptr m_floatSelection; ///< Selection between user-defined angle and timer-updated angle + std::unique_ptr m_trackball; ///< Trackball camera navigation stage std::unique_ptr m_shape; ///< Stage that generates a basic shape diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index a33aecbc..a06d3a60 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -67,7 +67,7 @@ void IntermediateFramePreparationStage::onProcess() }}; auto sourceFBO = renderInterface.configureFBO(0, *intermediateRenderTarget, m_fbo.get(), m_defaultFBO.get()); - auto sourceAttachment = (*intermediateRenderTarget)->attachmentRequiresUserDefinedFramebuffer() ? (*intermediateRenderTarget)->attachmentBuffer() : gl::GL_COLOR_ATTACHMENT0; + auto sourceAttachment = (*intermediateRenderTarget)->attachmentRequiresUserDefinedFramebuffer() ? (*intermediateRenderTarget)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0; auto targetFBO = m_targetFBO.get(); auto targetAttachment = gl::GL_COLOR_ATTACHMENT0; diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 6b6a3544..df7558a9 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -117,6 +117,7 @@ set(headers ${include_path}/stages/interfaces/RenderInterface.h ${include_path}/stages/interfaces/CanvasInterface.h + ${include_path}/stages/base/FloatSelectionStage.h ${include_path}/stages/base/BasicFramebufferStage.h ${include_path}/stages/base/TextureStage.h ${include_path}/stages/base/TextureLoadStage.h @@ -208,6 +209,7 @@ set(sources ${source_path}/stages/interfaces/RenderInterface.cpp ${source_path}/stages/interfaces/CanvasInterface.cpp + ${source_path}/stages/base/FloatSelectionStage.cpp ${source_path}/stages/base/BasicFramebufferStage.cpp ${source_path}/stages/base/ColorGradientSelectionStage.cpp ${source_path}/stages/base/ColorGradientTextureStage.cpp diff --git a/source/gloperate/include/gloperate/pipeline/Output.inl b/source/gloperate/include/gloperate/pipeline/Output.inl index d4f8ad03..7cef5c02 100644 --- a/source/gloperate/include/gloperate/pipeline/Output.inl +++ b/source/gloperate/include/gloperate/pipeline/Output.inl @@ -37,7 +37,7 @@ void Output::onRequiredChanged() } else { - // Inform parent stage + // Inform parent stage to propagate required state to inputs if (Stage * stage = this->parentStage()) { stage->outputRequiredChanged(this); diff --git a/source/gloperate/include/gloperate/pipeline/Stage.h b/source/gloperate/include/gloperate/pipeline/Stage.h index f3c162cc..b3e6c093 100644 --- a/source/gloperate/include/gloperate/pipeline/Stage.h +++ b/source/gloperate/include/gloperate/pipeline/Stage.h @@ -71,6 +71,9 @@ class GLOPERATE_API Stage : public cppexpose::Object template Input * operator<<(Slot & source); + template + Input * operator=(const T & value); + private: std::string m_name; Stage * m_stage; diff --git a/source/gloperate/include/gloperate/pipeline/Stage.inl b/source/gloperate/include/gloperate/pipeline/Stage.inl index aa6ebd2d..d0fa55c6 100644 --- a/source/gloperate/include/gloperate/pipeline/Stage.inl +++ b/source/gloperate/include/gloperate/pipeline/Stage.inl @@ -19,6 +19,14 @@ Input * Stage::CreateConnectedInputProxy::operator<<(Slot & source) return m_stage->createConnectedInput(m_name, source); } +template +Input * Stage::CreateConnectedInputProxy::operator=(const T & value) +{ + ++m_createdCount; + return m_stage->createInput(m_name, value); +} + + template std::vector *> Stage::inputs() const { diff --git a/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h b/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h new file mode 100644 index 00000000..349ccef7 --- /dev/null +++ b/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h @@ -0,0 +1,71 @@ + +#pragma once + + +#include + +#include +#include +#include +#include + + +namespace gloperate +{ + + + +/** +* @brief +* Stage that selects a float from a given index +*/ +class GLOPERATE_API FloatSelectionStage : public gloperate::Stage +{ +public: + CPPEXPOSE_DECLARE_COMPONENT( + FloatSelectionStage, gloperate::Stage + , "" // Tags + , "" // Icon + , "" // Annotations + , "Stage that selects a float from a given index" + , GLOPERATE_AUTHOR_ORGANIZATION + , "v1.0.0" + ) + + +public: + Input index; ///< Index of float to select + + Output value; ///< Resulting float + + +public: + /** + * @brief + * Constructor + * + * @param[in] environment + * Environment to which the stage belongs (must NOT be null!) + * @param[in] name + * Stage name + */ + FloatSelectionStage(gloperate::Environment * environment, const std::string & name = "FloatSelectionStage"); + + /** + * @brief + * Destructor + */ + ~FloatSelectionStage(); + + +protected: + // Virtual Stage interface + virtual void onProcess() override; + + +protected: + std::vector *> m_floatInputs; +}; + + +} // namespace gloperate diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 1c7a436c..ac5186cf 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -32,16 +32,6 @@ namespace { -template -gloperate::Slot * getSlot(gloperate::Stage * stage, const std::string & name) -{ - if (!stage) { - return nullptr; - } else { - return static_cast *>(stage->property(name)); - } -} - template gloperate::Input * getInput(gloperate::Stage * stage, std::function *)> callback) { @@ -534,10 +524,17 @@ void Canvas::promoteMouseWheel(const glm::vec2 & delta, const glm::ivec2 & pos) void Canvas::checkRedraw() { - auto slotRendered = getSlot(m_renderStage.get(), "rendered"); - if (slotRendered && !slotRendered->isValid()) + bool redraw = false; + forAllOutputs(m_renderStage.get(), [& redraw](Output * output) { + if (**output && !output->isValid()) + { + redraw = true; + } + }); + + if (redraw) { - redraw(); + this->redraw(); } } diff --git a/source/gloperate/source/pipeline/AbstractSlot.cpp b/source/gloperate/source/pipeline/AbstractSlot.cpp index 3912f777..629b4ca4 100644 --- a/source/gloperate/source/pipeline/AbstractSlot.cpp +++ b/source/gloperate/source/pipeline/AbstractSlot.cpp @@ -69,14 +69,16 @@ bool AbstractSlot::isRequired() const void AbstractSlot::setRequired(bool required) { - if (m_required != required) + if (m_required == required) { - m_required = required; + return; + } - cppassist::debug(3, "gloperate") << this->qualifiedName() << ": required changed to " << required; + m_required = required; - onRequiredChanged(); - } + cppassist::debug(3, "gloperate") << this->qualifiedName() << ": required changed to " << required; + + onRequiredChanged(); } bool AbstractSlot::isFeedback() const diff --git a/source/gloperate/source/pipeline/Stage.cpp b/source/gloperate/source/pipeline/Stage.cpp index 0603987b..d20153d8 100644 --- a/source/gloperate/source/pipeline/Stage.cpp +++ b/source/gloperate/source/pipeline/Stage.cpp @@ -47,8 +47,6 @@ Stage::Stage(Environment * environment, const std::string & className, const std Stage::~Stage() { - info() << m_name << " destroyed."; - if (Pipeline * parent = parentPipeline()) { parent->removeStage(this); diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index 27698150..da6a91b5 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -20,7 +20,7 @@ CPPEXPOSE_COMPONENT(ClearStage, gloperate::Stage) ClearStage::ClearStage(Environment * environment, const std::string & name) : Stage(environment, "ClearStage", name) -, clear("clear", this) +, clear("clear", this, true) , renderInterface(this) { inputAdded.connect( [this] (AbstractSlot * connectedInput) { @@ -63,7 +63,7 @@ void ClearStage::onContextDeinit(AbstractGLContext *) void ClearStage::onProcess() { - if (!*clear) + if (*clear) { // Setup OpenGL state gl::glScissor(renderInterface.viewport->x, renderInterface.viewport->y, renderInterface.viewport->z, renderInterface.viewport->w); @@ -104,7 +104,7 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex), 0); + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, **m_depthValueInputs.at(depthAttachmentIndex), 0, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); ++depthAttachmentIndex; } @@ -118,7 +118,7 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(depthAttachmentIndex), (**m_depthStencilValueInputs.at(depthAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).second); + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); ++depthStencilAttachmentIndex; } diff --git a/source/gloperate/source/stages/base/FloatSelectionStage.cpp b/source/gloperate/source/stages/base/FloatSelectionStage.cpp new file mode 100644 index 00000000..0a39e089 --- /dev/null +++ b/source/gloperate/source/stages/base/FloatSelectionStage.cpp @@ -0,0 +1,57 @@ + +#include + +#include + + +namespace gloperate +{ + + +CPPEXPOSE_COMPONENT(FloatSelectionStage, gloperate::Stage) + + +FloatSelectionStage::FloatSelectionStage(gloperate::Environment * environment, const std::string & name) +: Stage(environment, "FloatSelectionStage", name) +, index("index", this, 0) +, value("value", this, 0.0f) +{ + inputAdded.connect([this](AbstractSlot * slot) { + auto floatInput = dynamic_cast *>(slot); + + if (floatInput) + { + m_floatInputs.push_back(floatInput); + } + }); + + inputRemoved.connect([this](AbstractSlot * slot) { + const auto it = std::find(m_floatInputs.begin(), m_floatInputs.end(), static_cast *>(slot)); + + if (it == m_floatInputs.end()) + { + return; + } + + m_floatInputs.erase(it); + }); +} + +FloatSelectionStage::~FloatSelectionStage() +{ +} + +void FloatSelectionStage::onProcess() +{ + if (m_floatInputs.size() <= *index) + { + value.setValue(0.0f); + + return; + } + + value.setValue(**m_floatInputs.at(*index)); +} + + +} // namespace gloperate From 9d3a024792b6d0ac34da3770321ac7f022b0dbbe Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 16 Jun 2017 23:42:19 +0200 Subject: [PATCH 09/33] Introduce RenderbufferRenderTargetStage --- .../demo-stages-plugins/ShapeDemo.cpp | 2 +- .../stages/MultiFrameAggregationPipeline.h | 13 +-- .../stages/MultiFrameAggregationPipeline.cpp | 9 +- source/gloperate/CMakeLists.txt | 6 +- .../base/RenderbufferRenderTargetStage.h | 90 +++++++++++++++++++ ...tureStage.h => TextureRenderTargetStage.h} | 10 +-- .../base/RenderbufferRenderTargetStage.cpp | 74 +++++++++++++++ ...Stage.cpp => TextureRenderTargetStage.cpp} | 16 ++-- 8 files changed, 193 insertions(+), 27 deletions(-) create mode 100644 source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h rename source/gloperate/include/gloperate/stages/base/{TextureStage.h => TextureRenderTargetStage.h} (83%) create mode 100644 source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp rename source/gloperate/source/stages/base/{TextureStage.cpp => TextureRenderTargetStage.cpp} (68%) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 6d9f9a32..9e066aec 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h index 6ad97906..51e5c29f 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h @@ -15,7 +15,8 @@ namespace gloperate { class BasicFramebufferStage; - class TextureStage; + class TextureRenderTargetStage; + class RenderbufferRenderTargetStage; class FramebufferStage; class BlitStage; } @@ -96,11 +97,11 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P protected: // Aggregation stages - std::unique_ptr m_colorRenderTargetStage; ///< Aggregation color render target - std::unique_ptr m_depthStencilRenderTargetStage; ///< Aggregation depth stencil render target - std::unique_ptr m_controlStage; ///< Multiframe control stage - std::unique_ptr m_framePreparationStage; ///< Intermediate frame preparation stage - std::unique_ptr m_aggregationStage; ///< Aggregation stage + std::unique_ptr m_colorRenderTargetStage; ///< Aggregation color render target + std::unique_ptr m_depthStencilRenderTargetStage; ///< Aggregation depth stencil render target + std::unique_ptr m_controlStage; ///< Multiframe control stage + std::unique_ptr m_framePreparationStage; ///< Intermediate frame preparation stage + std::unique_ptr m_aggregationStage; ///< Aggregation stage // Inserted Stage/Pipeline Stage * m_renderStage; ///< Actual rendering stage, providing intermediate frames diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index 9807e34e..840037d3 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -5,7 +5,8 @@ #include #include -#include +#include +#include #include #include @@ -125,8 +126,8 @@ MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environm , canvasInterface(this) , multiFrameCount("multiFrameCount", this, 64) // Stages -, m_colorRenderTargetStage(cppassist::make_unique(environment, "ColorStage")) -, m_depthStencilRenderTargetStage(cppassist::make_unique(environment, "DepthStencilStage")) +, m_colorRenderTargetStage(cppassist::make_unique(environment, "ColorStage")) +, m_depthStencilRenderTargetStage(cppassist::make_unique(environment, "DepthStencilStage")) , m_controlStage(cppassist::make_unique(environment, "MultiFrameControlStage")) , m_framePreparationStage(cppassist::make_unique(environment, "IntermediateFramePreparationStage")) , m_aggregationStage(cppassist::make_unique(environment, "MultiFrameAggregationStage")) @@ -144,9 +145,7 @@ MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environm addStage(m_depthStencilRenderTargetStage.get()); m_depthStencilRenderTargetStage->size << canvasInterface.viewport; - m_depthStencilRenderTargetStage->format.setValue(gl::GL_DEPTH_STENCIL); m_depthStencilRenderTargetStage->internalFormat.setValue(gl::GL_DEPTH24_STENCIL8); - m_depthStencilRenderTargetStage->type.setValue(gl::GL_UNSIGNED_INT_24_8); addStage(m_controlStage.get()); m_controlStage->frameNumber << canvasInterface.frameCounter; diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index f7b26a70..67905e8b 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -120,7 +120,8 @@ set(headers ${include_path}/stages/interfaces/CanvasInterface.h ${include_path}/stages/base/FloatSelectionStage.h ${include_path}/stages/base/BasicFramebufferStage.h - ${include_path}/stages/base/TextureStage.h + ${include_path}/stages/base/TextureRenderTargetStage.h + ${include_path}/stages/base/RenderbufferRenderTargetStage.h ${include_path}/stages/base/TextureLoadStage.h ${include_path}/stages/base/BlitStage.h ${include_path}/stages/base/ColorGradientSelectionStage.h @@ -220,7 +221,8 @@ set(sources ${source_path}/stages/base/RasterizationStage.cpp ${source_path}/stages/base/ClearStage.cpp ${source_path}/stages/base/ProgramStage.cpp - ${source_path}/stages/base/TextureStage.cpp + ${source_path}/stages/base/TextureRenderTargetStage.cpp + ${source_path}/stages/base/RenderbufferRenderTargetStage.cpp ${source_path}/stages/base/TextureLoadStage.cpp ${source_path}/stages/base/BlitStage.cpp ${source_path}/stages/base/ShapeStage.cpp diff --git a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h new file mode 100644 index 00000000..478b861e --- /dev/null +++ b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h @@ -0,0 +1,90 @@ + +#pragma once + + +#include + +#include + +#include + +#include +#include +#include +#include + + +namespace globjects +{ + class Renderbuffer; +} + + +namespace gloperate +{ + + +class RenderTarget; + + +/** +* @brief +* Stage that creates an empty texture with a specified size and format +*/ +class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage +{ +public: + CPPEXPOSE_DECLARE_COMPONENT( + RenderbufferRenderTargetStage, gloperate::Stage + , "" // Tags + , "" // Icon + , "" // Annotations + , "Stage that creates an empty renderbuffer as render target with a specified size and format" + , GLOPERATE_AUTHOR_ORGANIZATION + , "v1.0.0" + ) + + +public: + // Inputs + Input internalFormat; ///< OpenGL internal image format + Input size; ///< Viewport size + + // Outputs + Output renderbuffer; ///< Texture + Output renderTarget; ///< RenderTarget + + +public: + /** + * @brief + * Constructor + * + * @param[in] environment + * Environment to which the stage belongs (must NOT be null!) + * @param[in] name + * Stage name + */ + RenderbufferRenderTargetStage(Environment * environment, const std::string & name = ""); + + /** + * @brief + * Destructor + */ + virtual ~RenderbufferRenderTargetStage(); + + +protected: + // Virtual Stage interface + virtual void onContextInit(gloperate::AbstractGLContext * context) override; + virtual void onContextDeinit(AbstractGLContext * context) override; + virtual void onProcess() override; + + +protected: + std::unique_ptr m_renderbuffer; ///< The created renderbuffer + std::unique_ptr m_renderTarget; ///< The passed render target +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/stages/base/TextureStage.h b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h similarity index 83% rename from source/gloperate/include/gloperate/stages/base/TextureStage.h rename to source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h index e8205e6a..8e3d4531 100644 --- a/source/gloperate/include/gloperate/stages/base/TextureStage.h +++ b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h @@ -31,15 +31,15 @@ class RenderTarget; * @brief * Stage that creates an empty texture with a specified size and format */ -class GLOPERATE_API TextureStage : public gloperate::Stage +class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage { public: CPPEXPOSE_DECLARE_COMPONENT( - TextureStage, gloperate::Stage + TextureRenderTargetStage, gloperate::Stage , "" // Tags , "" // Icon , "" // Annotations - , "Stage that creates an empty texture with a specified size and format" + , "Stage that creates an empty texture as render target with a specified size and format" , GLOPERATE_AUTHOR_ORGANIZATION , "v1.0.0" ) @@ -67,13 +67,13 @@ class GLOPERATE_API TextureStage : public gloperate::Stage * @param[in] name * Stage name */ - TextureStage(Environment * environment, const std::string & name = ""); + TextureRenderTargetStage(Environment * environment, const std::string & name = ""); /** * @brief * Destructor */ - virtual ~TextureStage(); + virtual ~TextureRenderTargetStage(); protected: diff --git a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp new file mode 100644 index 00000000..b0261eab --- /dev/null +++ b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp @@ -0,0 +1,74 @@ + +#include + +#include +#include + +#include + +#include + +#include + + +using namespace gl; +using namespace globjects; + + +namespace gloperate +{ + + +CPPEXPOSE_COMPONENT(RenderbufferRenderTargetStage, gloperate::Stage) + + +RenderbufferRenderTargetStage::RenderbufferRenderTargetStage(gloperate::Environment * environment, const std::string & name) +: Stage(environment, "RenderbufferRenderTargetStage", name) +, internalFormat("internalFormat", this) +, size("size", this) +, renderbuffer("renderbuffer", this) +, renderTarget("renderTarget", this) +{ +} + +RenderbufferRenderTargetStage::~RenderbufferRenderTargetStage() +{ +} + +void RenderbufferRenderTargetStage::onContextInit(gloperate::AbstractGLContext *) +{ + // Create new texture + m_renderbuffer = cppassist::make_unique(); + + // Create wrapping render target + m_renderTarget = cppassist::make_unique(); + m_renderTarget->setTarget(m_renderbuffer.get()); +} + +void RenderbufferRenderTargetStage::onContextDeinit(AbstractGLContext *) +{ + // Clean up OpenGL objects + m_renderbuffer = nullptr; + m_renderTarget = nullptr; +} + +void RenderbufferRenderTargetStage::onProcess() +{ + // Check if texture has been created successfully + if (!m_renderbuffer.get()) + { + return; + } + + // Create texture image + const auto width = (*size)[2]; + const auto height = (*size)[3]; + m_renderbuffer->storage(*internalFormat, width, height); + + // Update outputs + renderbuffer.setValue(m_renderbuffer.get()); + renderTarget.setValue(m_renderTarget.get()); +} + + +} // namespace gloperate diff --git a/source/gloperate/source/stages/base/TextureStage.cpp b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp similarity index 68% rename from source/gloperate/source/stages/base/TextureStage.cpp rename to source/gloperate/source/stages/base/TextureRenderTargetStage.cpp index fc70f018..4a71f795 100644 --- a/source/gloperate/source/stages/base/TextureStage.cpp +++ b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp @@ -1,5 +1,5 @@ -#include +#include #include #include @@ -19,11 +19,11 @@ namespace gloperate { -CPPEXPOSE_COMPONENT(TextureStage, gloperate::Stage) +CPPEXPOSE_COMPONENT(TextureRenderTargetStage, gloperate::Stage) -TextureStage::TextureStage(gloperate::Environment * environment, const std::string & name) -: Stage(environment, "TextureStage", name) +TextureRenderTargetStage::TextureRenderTargetStage(gloperate::Environment * environment, const std::string & name) +: Stage(environment, "TextureRenderTargetStage", name) , internalFormat("internalFormat", this) , format("format", this) , type("type", this) @@ -33,11 +33,11 @@ TextureStage::TextureStage(gloperate::Environment * environment, const std::stri { } -TextureStage::~TextureStage() +TextureRenderTargetStage::~TextureRenderTargetStage() { } -void TextureStage::onContextInit(gloperate::AbstractGLContext *) +void TextureRenderTargetStage::onContextInit(gloperate::AbstractGLContext *) { // Create new texture m_texture = Texture::createDefault(GL_TEXTURE_2D); @@ -47,14 +47,14 @@ void TextureStage::onContextInit(gloperate::AbstractGLContext *) m_renderTarget->setTarget(m_texture.get()); } -void TextureStage::onContextDeinit(AbstractGLContext *) +void TextureRenderTargetStage::onContextDeinit(AbstractGLContext *) { // Clean up OpenGL objects m_texture = nullptr; m_renderTarget = nullptr; } -void TextureStage::onProcess() +void TextureRenderTargetStage::onProcess() { // Check if texture has been created successfully if (!m_texture.get()) From 3525c387c2637adf1da55d1efeefeb823371ac57 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 14:13:26 +0200 Subject: [PATCH 10/33] Reuse default FBO in gloperate-qt RenderWindow --- .../include/gloperate-qt/base/RenderWindow.h | 11 +++++++++-- source/gloperate-qt/source/base/RenderWindow.cpp | 7 +++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h b/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h index be704406..d328a2df 100644 --- a/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h +++ b/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h @@ -7,6 +7,12 @@ #include +namespace globjects +{ + class Framebuffer; +} + + namespace gloperate { class Environment; @@ -77,8 +83,9 @@ class GLOPERATE_QT_API RenderWindow : public OpenGLWindow protected: - gloperate::Environment * m_environment; ///< Gloperate environment to which the window belongs (must NOT be null) - std::unique_ptr m_canvas; ///< Canvas that renders onto the window (never null) + gloperate::Environment * m_environment; ///< Gloperate environment to which the window belongs (must NOT be null) + std::unique_ptr m_canvas; ///< Canvas that renders onto the window (never null) + std::unique_ptr m_framebuffer; ///< Target framebuffer for rendering }; diff --git a/source/gloperate-qt/source/base/RenderWindow.cpp b/source/gloperate-qt/source/base/RenderWindow.cpp index 08c56cf9..37700a8c 100644 --- a/source/gloperate-qt/source/base/RenderWindow.cpp +++ b/source/gloperate-qt/source/base/RenderWindow.cpp @@ -44,11 +44,13 @@ gloperate::Canvas * RenderWindow::canvas() const void RenderWindow::onContextInit() { m_canvas->setOpenGLContext(m_context.get()); + m_framebuffer = globjects::Framebuffer::defaultFBO(); } void RenderWindow::onContextDeinit() { m_canvas->setOpenGLContext(nullptr); + m_framebuffer = nullptr; } void RenderWindow::onResize(const QSize & deviceSize, const QSize & /*virtualSize*/) @@ -60,10 +62,7 @@ void RenderWindow::onResize(const QSize & deviceSize, const QSize & /*virtualSiz void RenderWindow::onPaint() { - // [TODO]: optimize memory reallocation problem - auto defaultFBO = globjects::Framebuffer::defaultFBO(); - - m_canvas->render(defaultFBO.get()); + m_canvas->render(m_framebuffer.get()); } void RenderWindow::onTimer() From 947c4e3355e539fa18ac55a8f6bee7716fd3240c Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 14:14:41 +0200 Subject: [PATCH 11/33] Introduce invalid viewport size --- .../gloperate/stages/base/ClearStage.h | 3 +++ .../stages/interfaces/RenderInterface.h | 4 ++++ .../source/stages/base/ClearStage.cpp | 19 +++++++++++++++---- .../stages/interfaces/RenderInterface.cpp | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index b2370080..0a454377 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -25,6 +25,9 @@ namespace gloperate /** * @brief * Stage that clears the screen with a background color +* +* If a valid viewport is set (width and height are greater or equal to '0', only the area of +* the given viewport is cleared, otherwise the full render targets are cleared. */ class GLOPERATE_API ClearStage : public Stage { diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 7a97b88c..ebf4e78a 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -38,6 +38,10 @@ class RenderTarget; * for rendering stages. It can just be instanciated on a stage or pipeline * and it will add the inputs and outputs directly to the stage (the interface * itself is not an object in the hierarchy). +* +* The viewport is initialized with an invalid width and height (i.e., -1.0 +* per component) which results in no rendering for rasterization stages and +* full clearing for clear stages. */ class GLOPERATE_API RenderInterface { diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index da6a91b5..e02e42bf 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -65,9 +65,16 @@ void ClearStage::onProcess() { if (*clear) { - // Setup OpenGL state - gl::glScissor(renderInterface.viewport->x, renderInterface.viewport->y, renderInterface.viewport->z, renderInterface.viewport->w); - gl::glEnable(gl::GL_SCISSOR_TEST); + if (renderInterface.viewport->z >= 0.0 || renderInterface.viewport->w >= 0.0) { + // Setup OpenGL state + gl::glScissor(renderInterface.viewport->x, renderInterface.viewport->y, renderInterface.viewport->z, renderInterface.viewport->w); + gl::glEnable(gl::GL_SCISSOR_TEST); + } + else + { + // Clear full render targets if viewport has invalid size + gl::glDisable(gl::GL_SCISSOR_TEST); + } size_t colorAttachmentIndex = 0; size_t depthAttachmentIndex = 0; @@ -90,7 +97,11 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer((**input)->attachmentBuffer(), (**input)->attachmentDrawBuffer(colorAttachmentIndex), **m_colorValueInputs.at(colorAttachmentIndex)); + const auto attachmentBuffer = (**input)->attachmentBuffer(); + const auto attachmentDrawBuffer = (**input)->attachmentDrawBuffer(colorAttachmentIndex); + const auto clearColor = **m_colorValueInputs.at(colorAttachmentIndex); + + fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColor); ++colorAttachmentIndex; } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index b6499870..84a1e6b3 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -19,7 +19,7 @@ namespace gloperate RenderInterface::RenderInterface(Stage * stage) -: viewport("viewport", stage) +: viewport("viewport", stage, glm::vec4(0.0, 0.0, -1.0, -1.0)) { // Hide inputs in property editor viewport.setOption("hidden", true); From 23479e6c43a2805b05bf811d2714edc2b6775db1 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 14:15:30 +0200 Subject: [PATCH 12/33] Remove actual framebuffer object from basic framebuffer stage Now this class may need renaming, depending on perceived functionality by a developer --- .../stages/base/BasicFramebufferStage.h | 5 -- .../stages/base/BasicFramebufferStage.cpp | 51 +++++++------------ 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h index e8fc04b8..3875fbc0 100644 --- a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h +++ b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h @@ -51,7 +51,6 @@ class GLOPERATE_API BasicFramebufferStage : public Stage Input viewport; ///< Texture size // Outputs - Output fbo; ///< Framebuffer Output colorTexture; ///< Color texture Output depthTexture; ///< Depth texture Output colorBuffer; ///< Color attachment @@ -83,12 +82,8 @@ class GLOPERATE_API BasicFramebufferStage : public Stage virtual void onContextDeinit(AbstractGLContext * context) override; virtual void onProcess() override; - // Helper functions - void rebuildFBO(); - protected: - std::unique_ptr m_fbo; ///< The created framebuffer std::unique_ptr m_colorTexture; ///< The created texture std::unique_ptr m_depthTexture; ///< The created texture std::unique_ptr m_colorBuffer; ///< Color texture diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 1e7b357d..5c43b038 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -18,7 +18,6 @@ CPPEXPOSE_COMPONENT(BasicFramebufferStage, gloperate::Stage) BasicFramebufferStage::BasicFramebufferStage(Environment * environment, const std::string & name) : Stage(environment, "BasicFramebufferStage", name) , viewport ("viewport", this) -, fbo ("fbo", this) , colorTexture("colorTexture", this) , depthTexture("depthTexture", this) , colorBuffer ("colorBuffer", this) @@ -32,6 +31,19 @@ BasicFramebufferStage::~BasicFramebufferStage() void BasicFramebufferStage::onContextInit(AbstractGLContext *) { + // Create color texture + m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); + + m_colorBuffer = cppassist::make_unique(); + m_colorBuffer->setTarget(m_colorTexture.get()); + m_colorBuffer->setAttachmentType(AttachmentType::Color); + + // Create depth texture + m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); + + m_depthBuffer = cppassist::make_unique(); + m_depthBuffer->setTarget(m_depthTexture.get()); + m_depthBuffer->setAttachmentType(AttachmentType::Depth); } void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) @@ -41,54 +53,27 @@ void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) m_depthBuffer = nullptr; m_colorTexture = nullptr; m_depthTexture = nullptr; - m_fbo = nullptr; } void BasicFramebufferStage::onProcess() { - // Check if FBO needs to be rebuilt - if (!fbo.isValid()) - { - // Rebuild FBO (and textures) - rebuildFBO(); - } - // Get texture size glm::ivec2 size = glm::ivec2((*this->viewport).z, (*this->viewport).w); + cppassist::debug() << "resize " << m_colorTexture->id(); + m_colorTexture->image2D(0, gl::GL_RGBA, size.x, size.y, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, nullptr); + + cppassist::debug() << "resize " << m_depthTexture->id(); + m_depthTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_UNSIGNED_BYTE, nullptr); // Update outputs - this->fbo.setValue(m_fbo.get()); this->colorTexture.setValue(m_colorTexture.get()); this->depthTexture.setValue(m_depthTexture.get()); this->colorBuffer.setValue(m_colorBuffer.get()); this->depthBuffer.setValue(m_depthBuffer.get()); } -void BasicFramebufferStage::rebuildFBO() -{ - // Create color texture - m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - - m_colorBuffer = cppassist::make_unique(); - m_colorBuffer->setTarget(m_colorTexture.get()); - m_colorBuffer->setAttachmentType(AttachmentType::Color); - - // Create depth texture - m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - - m_depthBuffer = cppassist::make_unique(); - m_depthBuffer->setTarget(m_depthTexture.get()); - m_depthBuffer->setAttachmentType(AttachmentType::Depth); - - // Create FBO - m_fbo = cppassist::make_unique(); - m_fbo->setDrawBuffers({ gl::GL_COLOR_ATTACHMENT0 }); - m_fbo->attachTexture(gl::GL_COLOR_ATTACHMENT0, m_colorTexture.get()); - m_fbo->attachTexture(gl::GL_DEPTH_ATTACHMENT, m_depthTexture.get()); -} - } // namespace gloperate From 0f7554f6631988584c47a434fc3becd91044c042 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 15:06:03 +0200 Subject: [PATCH 13/33] Use blitting if pipeline does not render in passed color render target --- .../demo-stages-plugins/ShapeDemo.cpp | 1 + .../gloperate/include/gloperate/base/Canvas.h | 2 ++ .../include/gloperate/stages/base/BlitStage.h | 2 ++ .../stages/interfaces/RenderInterface.h | 6 ++-- source/gloperate/source/base/Canvas.cpp | 31 +++++++++++++++++++ .../source/stages/base/BlitStage.cpp | 14 +++++++-- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 9e066aec..f001ae0c 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -175,6 +175,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Outputs *createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); + //*createOutput("ColorOut") << *shapeColorOutput; // Start rotation rotate = true; diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 07b34440..244a5975 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -33,6 +33,7 @@ class AbstractSlot; class MouseDevice; class KeyboardDevice; class RenderTarget; +class BlitStage; /** @@ -313,6 +314,7 @@ class GLOPERATE_API Canvas : public cppexpose::Object float m_timeDelta; ///< Time delta since the last update (in seconds) std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call + std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets std::unique_ptr m_mouseDevice; ///< Device for Mouse Events std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' diff --git a/source/gloperate/include/gloperate/stages/base/BlitStage.h b/source/gloperate/include/gloperate/stages/base/BlitStage.h index dda7a027..70605452 100644 --- a/source/gloperate/include/gloperate/stages/base/BlitStage.h +++ b/source/gloperate/include/gloperate/stages/base/BlitStage.h @@ -9,6 +9,8 @@ #include #include + +#include #include #include #include diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index ebf4e78a..0e016e0e 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -2,11 +2,11 @@ #pragma once -#include +#include + #include #include - -#include +#include namespace globjects diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index ac5186cf..76d2a8b9 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace cppassist; @@ -152,6 +153,7 @@ Canvas::Canvas(Environment * environment) , m_openGLContext(nullptr) , m_initialized(false) , m_timeDelta(0.0f) +, m_blitStage(cppassist::make_unique(environment, "FinalBlit")) , m_mouseDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_keyboardDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_replaceStage(false) @@ -258,6 +260,8 @@ void Canvas::setOpenGLContext(AbstractGLContext * context) m_renderStage->deinitContext(m_openGLContext); } + m_blitStage->deinitContext(m_openGLContext); + m_openGLContext = nullptr; } @@ -272,6 +276,8 @@ void Canvas::setOpenGLContext(AbstractGLContext * context) { m_renderStage->initContext(m_openGLContext); } + + m_blitStage->initContext(m_openGLContext); } // Reset status @@ -442,6 +448,31 @@ void Canvas::render(globjects::Framebuffer * targetFBO) // Render m_renderStage->process(); + + auto colorOutput = getOutput(m_renderStage.get(), [this](Output * output) { + gloperate::RenderTarget * renderTarget = **output; + + return renderTarget->attachmentType() == AttachmentType::Color; + }); + if (colorOutput) + { + if (**colorOutput == m_colorTarget.get()) + { + + } + else + { + auto viewport = getOutput(m_renderStage.get(), [this](Output *) { + return true; + }); + + m_blitStage->source = **colorOutput; + m_blitStage->sourceViewport = viewport ? **viewport : m_viewport; + m_blitStage->target = m_colorTarget.get(); + m_blitStage->targetViewport = m_viewport; + m_blitStage->process(); + } + } } void Canvas::promoteKeyPress(int key, int modifier) diff --git a/source/gloperate/source/stages/base/BlitStage.cpp b/source/gloperate/source/stages/base/BlitStage.cpp index ce3e614c..e4dd17d6 100644 --- a/source/gloperate/source/stages/base/BlitStage.cpp +++ b/source/gloperate/source/stages/base/BlitStage.cpp @@ -4,6 +4,8 @@ #include #include +#include + namespace gloperate { @@ -38,6 +40,13 @@ void BlitStage::onContextDeinit(AbstractGLContext * /*context*/) void BlitStage::onProcess() { + if (*source == *target) + { + targetOut.setValue(*target); + + return; + } + std::array sourceRect = {{ static_cast((*sourceViewport).x), static_cast((*sourceViewport).y), @@ -51,8 +60,9 @@ void BlitStage::onProcess() static_cast((*targetViewport).w) }}; - globjects::Framebuffer * sourceFBO = source->attachmentRequiresUserDefinedFramebuffer() ? m_sourceFBO.get() : m_defaultFBO.get(); - globjects::Framebuffer * targetFBO = target->attachmentRequiresUserDefinedFramebuffer() ? m_targetFBO.get() : m_defaultFBO.get(); + globjects::Framebuffer * sourceFBO = RenderInterface::configureFBO(0, *source, m_sourceFBO.get(), m_defaultFBO.get()); + globjects::Framebuffer * targetFBO = RenderInterface::configureFBO(0, *target, m_targetFBO.get(), m_defaultFBO.get()); + auto sourceAttachment = source->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : source->defaultFramebufferAttachment(); auto targetAttachment = target->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : target->defaultFramebufferAttachment(); From 49fd7408a31be17fc4fc573f0681b8608c9e1dc0 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 15:08:01 +0200 Subject: [PATCH 14/33] Remove obsolete include --- .../gloperate-glkernel/stages/MultiFrameAggregationPipeline.h | 1 - 1 file changed, 1 deletion(-) diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h index 51e5c29f..d7e0f028 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h @@ -6,7 +6,6 @@ #include #include -#include #include #include From 89d7d1f17e3b7a6457e0e28fdf5cc5feaaba371d Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 21 Jun 2017 19:01:37 +0200 Subject: [PATCH 15/33] Intermediate commit for RenderTarget subclasses --- .../demo-stages-plugins/ShapeDemo.cpp | 5 +- source/gloperate/CMakeLists.txt | 10 +++- .../gloperate/include/gloperate/base/Canvas.h | 46 ++++++++------- ...{RenderTarget.h => AbstractRenderTarget.h} | 21 ++++--- .../gloperate/rendering/ColorRenderTarget.h | 29 ++++++++++ .../gloperate/rendering/DepthRenderTarget.h | 29 ++++++++++ .../rendering/DepthStencilRenderTarget.h | 30 ++++++++++ .../stages/base/BasicFramebufferStage.h | 21 +++---- .../include/gloperate/stages/base/BlitStage.h | 16 ++--- .../base/RenderbufferRenderTargetStage.h | 22 ++++--- .../stages/base/TextureRenderTargetStage.h | 22 ++++--- .../stages/interfaces/CanvasInterface.h | 1 - .../stages/interfaces/RenderInterface.h | 58 +++++++++++++------ source/gloperate/source/base/Canvas.cpp | 58 +++++++++++-------- ...derTarget.cpp => AbstractRenderTarget.cpp} | 41 +++++++------ .../source/rendering/ColorRenderTarget.cpp | 9 +++ .../source/rendering/DepthRenderTarget.cpp | 9 +++ .../rendering/DepthStencilRenderTarget.cpp | 9 +++ .../stages/interfaces/RenderInterface.cpp | 51 ++++++++++++---- 19 files changed, 344 insertions(+), 143 deletions(-) rename source/gloperate/include/gloperate/rendering/{RenderTarget.h => AbstractRenderTarget.h} (93%) create mode 100644 source/gloperate/include/gloperate/rendering/ColorRenderTarget.h create mode 100644 source/gloperate/include/gloperate/rendering/DepthRenderTarget.h create mode 100644 source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h rename source/gloperate/source/rendering/{RenderTarget.cpp => AbstractRenderTarget.cpp} (63%) create mode 100644 source/gloperate/source/rendering/ColorRenderTarget.cpp create mode 100644 source/gloperate/source/rendering/DepthRenderTarget.cpp create mode 100644 source/gloperate/source/rendering/DepthStencilRenderTarget.cpp diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index f001ae0c..2cbcf8aa 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -174,8 +174,9 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; // Outputs - *createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); - //*createOutput("ColorOut") << *shapeColorOutput; + //*createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); + *createOutput("ColorOut") << *shapeColorOutput; + //*createOutput("ViewportOut") = glm::vec4(0, 0, 700, 700); // Start rotation rotate = true; diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 67905e8b..5078f3de 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -93,7 +93,10 @@ set(headers ${include_path}/rendering/RenderPass.h ${include_path}/rendering/LightType.h ${include_path}/rendering/Light.h - ${include_path}/rendering/RenderTarget.h + ${include_path}/rendering/AbstractRenderTarget.h + ${include_path}/rendering/ColorRenderTarget.h + ${include_path}/rendering/DepthRenderTarget.h + ${include_path}/rendering/DepthStencilRenderTarget.h ${include_path}/rendering/RenderTargetType.h ${include_path}/rendering/TransparencyMasksGenerator.h ${include_path}/rendering/ScreenAlignedQuad.h @@ -192,7 +195,10 @@ set(sources ${source_path}/rendering/Drawable.cpp ${source_path}/rendering/NoiseTexture.cpp ${source_path}/rendering/RenderPass.cpp - ${source_path}/rendering/RenderTarget.cpp + ${source_path}/rendering/AbstractRenderTarget.cpp + ${source_path}/rendering/ColorRenderTarget.cpp + ${source_path}/rendering/DepthRenderTarget.cpp + ${source_path}/rendering/DepthStencilRenderTarget.cpp ${source_path}/rendering/TransparencyMasksGenerator.cpp ${source_path}/rendering/ScreenAlignedQuad.cpp ${source_path}/rendering/ScreenAlignedTriangle.cpp diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 244a5975..017f856a 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -32,7 +32,9 @@ class Stage; class AbstractSlot; class MouseDevice; class KeyboardDevice; -class RenderTarget; +class ColorRenderTarget; +class DepthRenderTarget; +class DepthStencilRenderTarget; class BlitStage; @@ -306,27 +308,27 @@ class GLOPERATE_API Canvas : public cppexpose::Object protected: - Environment * m_environment; ///< Gloperate environment to which the canvas belongs - AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas - bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' - gloperate::ChronoTimer m_clock; ///< Time measurement - glm::vec4 m_viewport; ///< Viewport (in real device coordinates) - float m_timeDelta; ///< Time delta since the last update (in seconds) - std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas - std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call - std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets - std::unique_ptr m_mouseDevice; ///< Device for Mouse Events - std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events - bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' - std::mutex m_mutex; ///< Mutex for separating main and render thread - cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage - cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) - std::vector m_changedInputs; ///< List of changed input slots - std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs - - std::unique_ptr m_colorTarget; ///< Input render target for color attachment - std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment - std::unique_ptr m_depthStencilTarget; ///< Input render target for depth stencil attachment + Environment * m_environment; ///< Gloperate environment to which the canvas belongs + AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas + bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' + gloperate::ChronoTimer m_clock; ///< Time measurement + glm::vec4 m_viewport; ///< Viewport (in real device coordinates) + float m_timeDelta; ///< Time delta since the last update (in seconds) + std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas + std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call + std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets + std::unique_ptr m_mouseDevice; ///< Device for Mouse Events + std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events + bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' + std::mutex m_mutex; ///< Mutex for separating main and render thread + cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage + cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) + std::vector m_changedInputs; ///< List of changed input slots + std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs + + std::unique_ptr m_colorTarget; ///< Input render target for color attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment + std::unique_ptr m_depthStencilTarget; ///< Input render target for depth stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/RenderTarget.h b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h similarity index 93% rename from source/gloperate/include/gloperate/rendering/RenderTarget.h rename to source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h index 8fad5e6d..ff91436e 100644 --- a/source/gloperate/include/gloperate/rendering/RenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h @@ -1,16 +1,19 @@ #pragma once - -#include -#include - #include #include #include +namespace gl +{ + enum class GLenum : unsigned int; + using GLint = int; +} + + namespace globjects { class Framebuffer; @@ -26,26 +29,26 @@ namespace gloperate /** * @brief -* Render target that represents one target we can render into +* Abstract render target that represents one target we can render into * * A render target can internally be: a texture, a renderbuffer, * a symbolic attachment of the default renderbuffer, or a user-defined * renderbuffer with attachment specification. */ -class GLOPERATE_API RenderTarget +class GLOPERATE_API AbstractRenderTarget { public: /** * @brief * Constructor */ - RenderTarget(); + AbstractRenderTarget(); /** * @brief * Destructor */ - virtual ~RenderTarget(); + virtual ~AbstractRenderTarget(); /** * @brief @@ -188,7 +191,7 @@ class GLOPERATE_API RenderTarget gl::GLenum attachmentBuffer() const; - gl::GLint attachmentDrawBuffer(gl::GLint index) const; + gl::GLint attachmentDrawBuffer(size_t index) const; protected: RenderTargetType m_type; ///< Target type diff --git a/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h b/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h new file mode 100644 index 00000000..a56bc7cc --- /dev/null +++ b/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h @@ -0,0 +1,29 @@ + +#pragma once + + +#include + +#include + + +namespace gloperate +{ + + +/** +* @brief +* Color render target that represents one color target we can render into +* +* A render target can internally be: a texture, a renderbuffer, +* a symbolic attachment of the default renderbuffer, or a user-defined +* renderbuffer with attachment specification. +*/ +class GLOPERATE_API ColorRenderTarget : public AbstractRenderTarget +{ +public: + using AbstractRenderTarget::AbstractRenderTarget; +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h b/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h new file mode 100644 index 00000000..f8b4d744 --- /dev/null +++ b/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h @@ -0,0 +1,29 @@ + +#pragma once + + +#include + +#include + + +namespace gloperate +{ + + +/** +* @brief +* Depth render target that represents one depth target for depth tests during rasterization +* +* A render target can internally be: a texture, a renderbuffer, +* a symbolic attachment of the default renderbuffer, or a user-defined +* renderbuffer with attachment specification. +*/ +class GLOPERATE_API DepthRenderTarget : public AbstractRenderTarget +{ +public: + using AbstractRenderTarget::AbstractRenderTarget; +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h b/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h new file mode 100644 index 00000000..744ba745 --- /dev/null +++ b/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h @@ -0,0 +1,30 @@ + +#pragma once + + +#include + +#include + + +namespace gloperate +{ + + +/** +* @brief +* Depth stencil render target that represents one depth stencil target +* for depth and stencil tests during rasterization +* +* A render target can internally be: a texture, a renderbuffer, +* a symbolic attachment of the default renderbuffer, or a user-defined +* renderbuffer with attachment specification. +*/ +class GLOPERATE_API DepthStencilRenderTarget : public AbstractRenderTarget +{ +public: + using AbstractRenderTarget::AbstractRenderTarget; +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h index 3875fbc0..16ebd787 100644 --- a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h +++ b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h @@ -25,7 +25,8 @@ namespace gloperate { -class RenderTarget; +class ColorRenderTarget; +class DepthRenderTarget; /** @@ -48,13 +49,13 @@ class GLOPERATE_API BasicFramebufferStage : public Stage public: // Inputs - Input viewport; ///< Texture size + Input viewport; ///< Texture size // Outputs - Output colorTexture; ///< Color texture - Output depthTexture; ///< Depth texture - Output colorBuffer; ///< Color attachment - Output depthBuffer; ///< Depth attachment + Output colorTexture; ///< Color texture + Output depthTexture; ///< Depth texture + Output colorBuffer; ///< Color attachment + Output depthBuffer; ///< Depth attachment public: @@ -84,10 +85,10 @@ class GLOPERATE_API BasicFramebufferStage : public Stage protected: - std::unique_ptr m_colorTexture; ///< The created texture - std::unique_ptr m_depthTexture; ///< The created texture - std::unique_ptr m_colorBuffer; ///< Color texture - std::unique_ptr m_depthBuffer; ///< Depth texture + std::unique_ptr m_colorTexture; ///< The created texture + std::unique_ptr m_depthTexture; ///< The created texture + std::unique_ptr m_colorBuffer; ///< Color texture + std::unique_ptr m_depthBuffer; ///< Depth texture }; diff --git a/source/gloperate/include/gloperate/stages/base/BlitStage.h b/source/gloperate/include/gloperate/stages/base/BlitStage.h index 70605452..7f4ff0f0 100644 --- a/source/gloperate/include/gloperate/stages/base/BlitStage.h +++ b/source/gloperate/include/gloperate/stages/base/BlitStage.h @@ -15,7 +15,7 @@ #include #include -#include +#include namespace gloperate @@ -42,15 +42,15 @@ class GLOPERATE_API BlitStage : public Stage public: // Inputs - Input source; ///< FBO containing the source attachments - Input sourceViewport; ///< Viewport for reading from source FBO - Input target; ///< FBO with destination attachments - Input targetViewport; ///< Viewport for writing into destination FBO - Input minFilter; ///< Interpolation mode used when target size is lower than source size (default: linear interpolation) - Input magFilter; ///< Interpolation mode used when target size is greater than source size (default: nearest filtering) + Input source; ///< FBO containing the source attachments + Input sourceViewport; ///< Viewport for reading from source FBO + Input target; ///< FBO with destination attachments + Input targetViewport; ///< Viewport for writing into destination FBO + Input minFilter; ///< Interpolation mode used when target size is lower than source size (default: linear interpolation) + Input magFilter; ///< Interpolation mode used when target size is greater than source size (default: nearest filtering) // Outputs - Output targetOut; ///< Pass-through render target + Output targetOut; ///< Pass-through render target public: diff --git a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h index 478b861e..ca5bf7b9 100644 --- a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h @@ -24,12 +24,14 @@ namespace gloperate { -class RenderTarget; +class ColorRenderTarget; +class DepthRenderTarget; +class DepthStencilRenderTarget; /** * @brief -* Stage that creates an empty texture with a specified size and format +* Stage that creates an empty render buffer with a specified size and format as render target */ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage { @@ -39,7 +41,7 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage , "" // Tags , "" // Icon , "" // Annotations - , "Stage that creates an empty renderbuffer as render target with a specified size and format" + , "Stage that creates an empty render buffer with a specified size and format as render target" , GLOPERATE_AUTHOR_ORGANIZATION , "v1.0.0" ) @@ -48,11 +50,13 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage public: // Inputs Input internalFormat; ///< OpenGL internal image format - Input size; ///< Viewport size + Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs - Output renderbuffer; ///< Texture - Output renderTarget; ///< RenderTarget + Output renderbuffer; ///< Renderbuffer + Output colorRenderTarget; ///< Color RenderTarget + Output depthRenderTarget; ///< Depth RenderTarget + Output depthStencilRenderTarget; ///< Stencil RenderTarget public: @@ -82,8 +86,10 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage protected: - std::unique_ptr m_renderbuffer; ///< The created renderbuffer - std::unique_ptr m_renderTarget; ///< The passed render target + std::unique_ptr m_renderbuffer; ///< The created renderbuffer + std::unique_ptr m_colorRenderTarget; ///< The color render target + std::unique_ptr m_depthRenderTarget; ///< The depth render target + std::unique_ptr m_depthStencilRenderTarget; ///< The depth stencil render target }; diff --git a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h index 8e3d4531..05913783 100644 --- a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h @@ -24,12 +24,14 @@ namespace gloperate { -class RenderTarget; +class ColorRenderTarget; +class DepthRenderTarget; +class DepthStencilRenderTarget; /** * @brief -* Stage that creates an empty texture with a specified size and format +* Stage that creates an empty texture with a specified size and format as render target */ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage { @@ -39,7 +41,7 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage , "" // Tags , "" // Icon , "" // Annotations - , "Stage that creates an empty texture as render target with a specified size and format" + , "Stage that creates an empty texture with a specified size and format as render target" , GLOPERATE_AUTHOR_ORGANIZATION , "v1.0.0" ) @@ -50,11 +52,13 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage Input internalFormat; ///< OpenGL internal image format Input format; ///< OpenGL image format Input type; ///< OpenGL data type - Input size; ///< Viewport size + Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs - Output texture; ///< Texture - Output renderTarget; ///< RenderTarget + Output texture; ///< Texture + Output colorRenderTarget; ///< Color RenderTarget + Output depthRenderTarget; ///< Depth RenderTarget + Output depthStencilRenderTarget; ///< Stencil RenderTarget public: @@ -84,8 +88,10 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage protected: - std::unique_ptr m_texture; ///< The created texture - std::unique_ptr m_renderTarget; ///< The passed render target + std::unique_ptr m_texture; ///< The created texture + std::unique_ptr m_colorRenderTarget; ///< The color render target + std::unique_ptr m_depthRenderTarget; ///< The depth render target + std::unique_ptr m_depthStencilRenderTarget; ///< The depth stencil render target }; diff --git a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h index 9b079ca0..7f662647 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h @@ -15,7 +15,6 @@ namespace gloperate class Stage; -class RenderTarget; /** diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 0e016e0e..52c5c466 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -24,7 +24,9 @@ namespace gloperate class Stage; -class RenderTarget; +class ColorRenderTarget; +class DepthRenderTarget; +class DepthStencilRenderTarget; /** @@ -47,7 +49,7 @@ class GLOPERATE_API RenderInterface { public: // Inputs - Input viewport; ///< Viewport (in framebuffer coordinates) + Input viewport; ///< Viewport (in framebuffer coordinates) // Rendertarget Inputs -> subject to pipeline/stage designer // Rendertarget Outputs -> subject to pipeline/stage designer @@ -71,21 +73,29 @@ class GLOPERATE_API RenderInterface bool allRenderTargetsCompatible() const; - size_t renderTargetInputSize() const; + const std::vector *> & colorRenderTargetInputs() const; + const std::vector *> & depthRenderTargetInputs() const; + const std::vector *> & depthStencilRenderTargetInputs() const; - const std::vector *> & renderTargetInputs() const; + Input * colorRenderTargetInput(size_t index) const; + Input * depthRenderTargetInput(size_t index) const; + Input * depthStencilRenderTargetInput(size_t index) const; - Input * renderTargetInput(size_t index) const; + ColorRenderTarget * inputColorRenderTarget(size_t index) const; + DepthRenderTarget * inputDepthRenderTarget(size_t index) const; + DepthStencilRenderTarget * inputDepthStencilRenderTarget(size_t index) const; - RenderTarget * inputRenderTarget(size_t index) const; + const std::vector *> & colorRenderTargetOutputs() const; + const std::vector *> & depthRenderTargetOutputs() const; + const std::vector *> & depthStencilRenderTargetOutputs() const; - size_t renderTargetOutputSize() const; + Output * colorRenderTargetOutput(size_t index) const; + Output * depthRenderTargetOutput(size_t index) const; + Output * depthStencilRenderTargetOutput(size_t index) const; - const std::vector *> & renderTargetOutputs() const; - - Output * renderTargetOutput(size_t index) const; - - RenderTarget * outputRenderTarget(size_t index) const; + ColorRenderTarget * outputColorRenderTarget(size_t index) const; + DepthRenderTarget * outputDepthRenderTarget(size_t index) const; + DepthStencilRenderTarget * outputDepthStencilRenderTarget(size_t index) const; /** * @brief @@ -94,7 +104,9 @@ class GLOPERATE_API RenderInterface * @param[in] input * New render target input */ - void addRenderTargetInput(Input * input); + void addRenderTargetInput(Input * input); + void addRenderTargetInput(Input * input); + void addRenderTargetInput(Input * input); /** * @brief @@ -103,17 +115,27 @@ class GLOPERATE_API RenderInterface * @param[in] input * New render target input */ - void addRenderTargetOutput(Output * input); + void addRenderTargetOutput(Output * input); + void addRenderTargetOutput(Output * input); + void addRenderTargetOutput(Output * input); - void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; - static globjects::Framebuffer * configureFBO(size_t index, RenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + static globjects::Framebuffer * configureFBO(size_t index, ColorRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + static globjects::Framebuffer * configureFBO(size_t index, DepthRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + static globjects::Framebuffer * configureFBO(size_t index, DepthStencilRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); protected: - std::vector *> m_renderTargetInputs; ///< List of input render targets - std::vector *> m_renderTargetOutputs; ///< List of output render targets (pass-through) + std::vector *> m_colorRenderTargetInputs; ///< List of input color render targets + std::vector *> m_depthRenderTargetInputs; ///< List of input depth render targets + std::vector *> m_depthStencilRenderTargetInputs; ///< List of input depth-stencil render targets + std::vector *> m_colorRenderTargetOutputs; ///< List of output color render targets (pass-through) + std::vector *> m_depthRenderTargetOutputs; ///< List of output depth render targets (pass-through) + std::vector *> m_depthStencilRenderTargetOutputs; ///< List of output depth-stencil render targets (pass-through) }; diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 76d2a8b9..522ad1d2 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -6,6 +6,8 @@ #include +#include + #include #include #include @@ -20,7 +22,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -157,9 +161,9 @@ Canvas::Canvas(Environment * environment) , m_mouseDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_keyboardDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_replaceStage(false) -, m_colorTarget(cppassist::make_unique()) -, m_depthTarget(cppassist::make_unique()) -, m_depthStencilTarget(cppassist::make_unique()) +, m_colorTarget(cppassist::make_unique()) +, m_depthTarget(cppassist::make_unique()) +, m_depthStencilTarget(cppassist::make_unique()) { // Register functions addFunction("onStageInputChanged", this, &Canvas::scr_onStageInputChanged); @@ -369,7 +373,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) if (slotViewport) slotViewport->setValue(m_viewport); // Mark output as required - forAllOutputs(m_renderStage.get(), [](Output * output) { + forAllOutputs(m_renderStage.get(), [](Output * output) { output->setRequired(true); }); @@ -422,38 +426,44 @@ void Canvas::render(globjects::Framebuffer * targetFBO) } // Update render stage input render targets - forAllInputs(m_renderStage.get(), [this](Input * input) { - gloperate::RenderTarget * renderTarget = **input; + forAllInputs(m_renderStage.get(), [this](Input * input) { + const auto renderTarget = **input; if (renderTarget == nullptr) { return; } - switch (renderTarget->attachmentType()) + input->setValue(m_colorTarget.get()); + }); + forAllInputs(m_renderStage.get(), [this](Input * input) { + const auto renderTarget = **input; + + if (renderTarget == nullptr) { - case AttachmentType::Color: - input->setValue(m_colorTarget.get()); - break; - case AttachmentType::Depth: - input->setValue(m_depthTarget.get()); - break; - case AttachmentType::DepthStencil: - input->setValue(m_depthStencilTarget.get()); - break; - default: - input->setValue(nullptr); + return; } + + input->setValue(m_depthTarget.get()); + }); + forAllInputs(m_renderStage.get(), [this](Input * input) { + const auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return; + } + + input->setValue(m_depthStencilTarget.get()); }); // Render m_renderStage->process(); - auto colorOutput = getOutput(m_renderStage.get(), [this](Output * output) { - gloperate::RenderTarget * renderTarget = **output; - - return renderTarget->attachmentType() == AttachmentType::Color; + auto colorOutput = getOutput(m_renderStage.get(), [this](Output * output) { + return **output != nullptr; }); + if (colorOutput) { if (**colorOutput == m_colorTarget.get()) @@ -556,7 +566,7 @@ void Canvas::promoteMouseWheel(const glm::vec2 & delta, const glm::ivec2 & pos) void Canvas::checkRedraw() { bool redraw = false; - forAllOutputs(m_renderStage.get(), [& redraw](Output * output) { + forAllOutputs(m_renderStage.get(), [& redraw](Output * output) { if (**output && !output->isValid()) { redraw = true; diff --git a/source/gloperate/source/rendering/RenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp similarity index 63% rename from source/gloperate/source/rendering/RenderTarget.cpp rename to source/gloperate/source/rendering/AbstractRenderTarget.cpp index 7566318d..2f5307ce 100644 --- a/source/gloperate/source/rendering/RenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -1,5 +1,8 @@ -#include +#include + +#include +#include #include #include @@ -11,7 +14,7 @@ namespace gloperate { -RenderTarget::RenderTarget() +AbstractRenderTarget::AbstractRenderTarget() : m_type(RenderTargetType::Invalid) , m_attachment(gl::GL_NONE) , m_texture(nullptr) @@ -20,11 +23,11 @@ RenderTarget::RenderTarget() { } -RenderTarget::~RenderTarget() +AbstractRenderTarget::~AbstractRenderTarget() { } -void RenderTarget::releaseTarget() +void AbstractRenderTarget::releaseTarget() { switch (m_type) { @@ -49,12 +52,12 @@ void RenderTarget::releaseTarget() m_type = RenderTargetType::Invalid; } -AttachmentType RenderTarget::attachmentType() const +AttachmentType AbstractRenderTarget::attachmentType() const { return m_attachmentType; } -gl::GLenum RenderTarget::attachmentGLType() const +gl::GLenum AbstractRenderTarget::attachmentGLType() const { switch (m_attachmentType) { @@ -68,12 +71,12 @@ gl::GLenum RenderTarget::attachmentGLType() const } } -void RenderTarget::setAttachmentType(AttachmentType attachmentType) +void AbstractRenderTarget::setAttachmentType(AttachmentType attachmentType) { m_attachmentType = attachmentType; } -void RenderTarget::setTarget(globjects::Texture * texture) +void AbstractRenderTarget::setTarget(globjects::Texture * texture) { releaseTarget(); @@ -82,7 +85,7 @@ void RenderTarget::setTarget(globjects::Texture * texture) m_texture = texture; } -void RenderTarget::setTarget(globjects::Renderbuffer * renderbuffer) +void AbstractRenderTarget::setTarget(globjects::Renderbuffer * renderbuffer) { releaseTarget(); @@ -91,7 +94,7 @@ void RenderTarget::setTarget(globjects::Renderbuffer * renderbuffer) m_renderbuffer = renderbuffer; } -void RenderTarget::setTarget(gl::GLenum attachment) +void AbstractRenderTarget::setTarget(gl::GLenum attachment) { releaseTarget(); @@ -100,7 +103,7 @@ void RenderTarget::setTarget(gl::GLenum attachment) m_attachment = attachment; } -void RenderTarget::setTarget(globjects::FramebufferAttachment * fboAttachment) +void AbstractRenderTarget::setTarget(globjects::FramebufferAttachment * fboAttachment) { releaseTarget(); @@ -109,46 +112,46 @@ void RenderTarget::setTarget(globjects::FramebufferAttachment * fboAttachment) m_userDefined = fboAttachment; } -RenderTargetType RenderTarget::type() const +RenderTargetType AbstractRenderTarget::type() const { return m_type; } -gl::GLenum RenderTarget::defaultFramebufferAttachment() const +gl::GLenum AbstractRenderTarget::defaultFramebufferAttachment() const { return m_attachment; } -globjects::Texture * RenderTarget::textureAttachment() const +globjects::Texture * AbstractRenderTarget::textureAttachment() const { return m_texture; } -globjects::Renderbuffer * RenderTarget::renderbufferAttachment() const +globjects::Renderbuffer * AbstractRenderTarget::renderbufferAttachment() const { return m_renderbuffer; } -globjects::FramebufferAttachment * RenderTarget::framebufferAttachment() const +globjects::FramebufferAttachment * AbstractRenderTarget::framebufferAttachment() const { return m_userDefined; } -bool RenderTarget::attachmentRequiresUserDefinedFramebuffer() const +bool AbstractRenderTarget::attachmentRequiresUserDefinedFramebuffer() const { return m_type == RenderTargetType::Texture || m_type == RenderTargetType::Renderbuffer || m_type == RenderTargetType::UserDefinedFBOAttachment; } -gl::GLenum RenderTarget::attachmentBuffer() const +gl::GLenum AbstractRenderTarget::attachmentBuffer() const { return attachmentRequiresUserDefinedFramebuffer() ? attachmentGLType() : m_attachment; } -gl::GLint RenderTarget::attachmentDrawBuffer(gl::GLint index) const +gl::GLint AbstractRenderTarget::attachmentDrawBuffer(size_t index) const { return attachmentRequiresUserDefinedFramebuffer() ? (m_attachmentType == AttachmentType::Color ? index : 0) diff --git a/source/gloperate/source/rendering/ColorRenderTarget.cpp b/source/gloperate/source/rendering/ColorRenderTarget.cpp new file mode 100644 index 00000000..8cca1df6 --- /dev/null +++ b/source/gloperate/source/rendering/ColorRenderTarget.cpp @@ -0,0 +1,9 @@ + +#include + + +namespace gloperate +{ + + +} // namespace gloperate diff --git a/source/gloperate/source/rendering/DepthRenderTarget.cpp b/source/gloperate/source/rendering/DepthRenderTarget.cpp new file mode 100644 index 00000000..b907c7cf --- /dev/null +++ b/source/gloperate/source/rendering/DepthRenderTarget.cpp @@ -0,0 +1,9 @@ + +#include + + +namespace gloperate +{ + + +} // namespace gloperate diff --git a/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp b/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp new file mode 100644 index 00000000..3ee669b2 --- /dev/null +++ b/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp @@ -0,0 +1,9 @@ + +#include + + +namespace gloperate +{ + + +} // namespace gloperate diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 84a1e6b3..7699c0cb 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -11,7 +11,9 @@ #include #include -#include +#include +#include +#include namespace gloperate @@ -25,20 +27,44 @@ RenderInterface::RenderInterface(Stage * stage) viewport.setOption("hidden", true); stage->inputAdded.connect( [this] (AbstractSlot * connectedInput) { - auto renderTargetInput = dynamic_cast *>(connectedInput); + auto colorRenderTargetInput = dynamic_cast *>(connectedInput); + auto depthRenderTargetInput = dynamic_cast *>(connectedInput); + auto depthStencilRenderTargetInput = dynamic_cast *>(connectedInput); - if (renderTargetInput) + if (colorRenderTargetInput) { - addRenderTargetInput(renderTargetInput); + addRenderTargetInput(colorRenderTargetInput); + } + + if (depthRenderTargetInput) + { + addRenderTargetInput(depthRenderTargetInput); + } + + if (depthStencilRenderTargetInput) + { + addRenderTargetInput(depthStencilRenderTargetInput); } }); stage->outputAdded.connect( [this] (AbstractSlot * connectedOutput) { - auto renderTargetOutput = dynamic_cast *>(connectedOutput); + auto colorRenderTargetOutput = dynamic_cast *>(connectedOutput); + auto depthRenderTargetOutput = dynamic_cast *>(connectedOutput); + auto depthStencilRenderTargetOutput = dynamic_cast *>(connectedOutput); + + if (colorRenderTargetOutput) + { + addRenderTargetOutput(colorRenderTargetOutput); + } - if (renderTargetOutput) + if (depthRenderTargetOutput) { - addRenderTargetOutput(renderTargetOutput); + addRenderTargetOutput(depthRenderTargetOutput); + } + + if (depthStencilRenderTargetOutput) + { + addRenderTargetOutput(depthStencilRenderTargetOutput); } }); } @@ -49,14 +75,12 @@ RenderInterface::~RenderInterface() bool RenderInterface::allRenderTargetsCompatible() const { - if (renderTargetInputSize() == 0) + if (m_colorRenderTargetOutputs.empty() && m_depthRenderTargetOutputs.empty() && m_depthStencilRenderTargetOutputs.empty()) { return true; } - auto numberOfDepthAttachments = std::count_if(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { - return input ? (**input)->attachmentType() == AttachmentType::Depth || (**input)->attachmentType() == AttachmentType::DepthStencil : false; - }); + auto numberOfDepthAttachments = m_depthRenderTargetOutputs.size() + m_depthStencilRenderTargetOutputs.size(); auto allDefaultFramebufferAttachments = std::all_of(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; @@ -151,7 +175,10 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * currentFBO = nextFBO; } - assert(nextFBO == currentFBO); + if (nextFBO != currentFBO) + { + return nullptr; + } if ((**input)->attachmentType() == AttachmentType::Color) { From 9f93d96553d3f1e73f853d741dd3afc6abfb79f3 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 22 Jun 2017 19:37:49 +0200 Subject: [PATCH 16/33] Further intermediate commit --- source/gloperate/CMakeLists.txt | 4 +- .../gloperate/include/gloperate/base/Canvas.h | 44 ++-- .../gloperate/rendering/AttachmentType.h | 4 +- ...ilRenderTarget.h => StencilRenderTarget.h} | 2 +- .../stages/base/BasicFramebufferStage.h | 19 +- .../stages/interfaces/RenderInterface.h | 37 ++- source/gloperate/source/base/Canvas.cpp | 39 +-- .../source/rendering/AbstractRenderTarget.cpp | 2 +- .../rendering/DepthStencilRenderTarget.cpp | 9 - .../source/rendering/StencilRenderTarget.cpp | 9 + .../stages/base/BasicFramebufferStage.cpp | 53 ++-- .../stages/interfaces/RenderInterface.cpp | 233 +++++++++++++++--- 12 files changed, 316 insertions(+), 139 deletions(-) rename source/gloperate/include/gloperate/rendering/{DepthStencilRenderTarget.h => StencilRenderTarget.h} (88%) delete mode 100644 source/gloperate/source/rendering/DepthStencilRenderTarget.cpp create mode 100644 source/gloperate/source/rendering/StencilRenderTarget.cpp diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 5078f3de..196f4520 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -96,7 +96,7 @@ set(headers ${include_path}/rendering/AbstractRenderTarget.h ${include_path}/rendering/ColorRenderTarget.h ${include_path}/rendering/DepthRenderTarget.h - ${include_path}/rendering/DepthStencilRenderTarget.h + ${include_path}/rendering/StencilRenderTarget.h ${include_path}/rendering/RenderTargetType.h ${include_path}/rendering/TransparencyMasksGenerator.h ${include_path}/rendering/ScreenAlignedQuad.h @@ -198,7 +198,7 @@ set(sources ${source_path}/rendering/AbstractRenderTarget.cpp ${source_path}/rendering/ColorRenderTarget.cpp ${source_path}/rendering/DepthRenderTarget.cpp - ${source_path}/rendering/DepthStencilRenderTarget.cpp + ${source_path}/rendering/StencilRenderTarget.cpp ${source_path}/rendering/TransparencyMasksGenerator.cpp ${source_path}/rendering/ScreenAlignedQuad.cpp ${source_path}/rendering/ScreenAlignedTriangle.cpp diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 017f856a..c8553569 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -34,7 +34,7 @@ class MouseDevice; class KeyboardDevice; class ColorRenderTarget; class DepthRenderTarget; -class DepthStencilRenderTarget; +class StencilRenderTarget; class BlitStage; @@ -308,27 +308,27 @@ class GLOPERATE_API Canvas : public cppexpose::Object protected: - Environment * m_environment; ///< Gloperate environment to which the canvas belongs - AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas - bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' - gloperate::ChronoTimer m_clock; ///< Time measurement - glm::vec4 m_viewport; ///< Viewport (in real device coordinates) - float m_timeDelta; ///< Time delta since the last update (in seconds) - std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas - std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call - std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets - std::unique_ptr m_mouseDevice; ///< Device for Mouse Events - std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events - bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' - std::mutex m_mutex; ///< Mutex for separating main and render thread - cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage - cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) - std::vector m_changedInputs; ///< List of changed input slots - std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs - - std::unique_ptr m_colorTarget; ///< Input render target for color attachment - std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment - std::unique_ptr m_depthStencilTarget; ///< Input render target for depth stencil attachment + Environment * m_environment; ///< Gloperate environment to which the canvas belongs + AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas + bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' + gloperate::ChronoTimer m_clock; ///< Time measurement + glm::vec4 m_viewport; ///< Viewport (in real device coordinates) + float m_timeDelta; ///< Time delta since the last update (in seconds) + std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas + std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call + std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets + std::unique_ptr m_mouseDevice; ///< Device for Mouse Events + std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events + bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' + std::mutex m_mutex; ///< Mutex for separating main and render thread + cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage + cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) + std::vector m_changedInputs; ///< List of changed input slots + std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs + + std::unique_ptr m_colorTarget; ///< Input render target for color attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment + std::unique_ptr m_stencilTarget; ///< Input render target for depth stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/AttachmentType.h b/source/gloperate/include/gloperate/rendering/AttachmentType.h index 98a5f055..93cd58ca 100644 --- a/source/gloperate/include/gloperate/rendering/AttachmentType.h +++ b/source/gloperate/include/gloperate/rendering/AttachmentType.h @@ -18,7 +18,8 @@ enum class AttachmentType : unsigned int { Color, ///< Color attachment Depth, ///< Depth only attachment - DepthStencil ///< Depth stencil attachment + Stencil, ///< Stencil attachment + DepthStencil ///< Combined depth-stencil attachment }; @@ -65,6 +66,7 @@ struct EnumDefaultStrings return { { gloperate::AttachmentType::Color, "Color" }, { gloperate::AttachmentType::Depth, "Depth" }, + { gloperate::AttachmentType::Stencil, "Stencil" }, { gloperate::AttachmentType::DepthStencil, "DepthStencil" } }; } diff --git a/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h b/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h similarity index 88% rename from source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h rename to source/gloperate/include/gloperate/rendering/StencilRenderTarget.h index 744ba745..c9366529 100644 --- a/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h @@ -20,7 +20,7 @@ namespace gloperate * a symbolic attachment of the default renderbuffer, or a user-defined * renderbuffer with attachment specification. */ -class GLOPERATE_API DepthStencilRenderTarget : public AbstractRenderTarget +class GLOPERATE_API StencilRenderTarget : public AbstractRenderTarget { public: using AbstractRenderTarget::AbstractRenderTarget; diff --git a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h index 16ebd787..a7f4fcd8 100644 --- a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h +++ b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h @@ -27,6 +27,7 @@ namespace gloperate class ColorRenderTarget; class DepthRenderTarget; +class StencilRenderTarget; /** @@ -52,10 +53,11 @@ class GLOPERATE_API BasicFramebufferStage : public Stage Input viewport; ///< Texture size // Outputs - Output colorTexture; ///< Color texture - Output depthTexture; ///< Depth texture - Output colorBuffer; ///< Color attachment - Output depthBuffer; ///< Depth attachment + Output colorTexture; ///< Color texture + Output depthStencilTexture; ///< Combined depth-stencil texture + Output colorBuffer; ///< Color attachment + Output depthBuffer; ///< Depth attachment + Output stencilBuffer; ///< Stencil attachment public: @@ -85,10 +87,11 @@ class GLOPERATE_API BasicFramebufferStage : public Stage protected: - std::unique_ptr m_colorTexture; ///< The created texture - std::unique_ptr m_depthTexture; ///< The created texture - std::unique_ptr m_colorBuffer; ///< Color texture - std::unique_ptr m_depthBuffer; ///< Depth texture + std::unique_ptr m_colorTexture; ///< Internal color texture + std::unique_ptr m_depthStencilTexture; ///< Internal, combined depth-stencil texture + std::unique_ptr m_colorBuffer; ///< Color texture + std::unique_ptr m_depthBuffer; ///< Depth texture + std::unique_ptr m_stencilBuffer; ///< Stencil texture }; diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 52c5c466..ce741474 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -24,9 +24,10 @@ namespace gloperate class Stage; +class AbstractRenderTarget; class ColorRenderTarget; class DepthRenderTarget; -class DepthStencilRenderTarget; +class StencilRenderTarget; /** @@ -75,27 +76,27 @@ class GLOPERATE_API RenderInterface const std::vector *> & colorRenderTargetInputs() const; const std::vector *> & depthRenderTargetInputs() const; - const std::vector *> & depthStencilRenderTargetInputs() const; + const std::vector *> & stencilRenderTargetInputs() const; Input * colorRenderTargetInput(size_t index) const; Input * depthRenderTargetInput(size_t index) const; - Input * depthStencilRenderTargetInput(size_t index) const; + Input * stencilRenderTargetInput(size_t index) const; ColorRenderTarget * inputColorRenderTarget(size_t index) const; DepthRenderTarget * inputDepthRenderTarget(size_t index) const; - DepthStencilRenderTarget * inputDepthStencilRenderTarget(size_t index) const; + StencilRenderTarget * inputStencilRenderTarget(size_t index) const; const std::vector *> & colorRenderTargetOutputs() const; const std::vector *> & depthRenderTargetOutputs() const; - const std::vector *> & depthStencilRenderTargetOutputs() const; + const std::vector *> & stencilRenderTargetOutputs() const; Output * colorRenderTargetOutput(size_t index) const; Output * depthRenderTargetOutput(size_t index) const; - Output * depthStencilRenderTargetOutput(size_t index) const; + Output * stencilRenderTargetOutput(size_t index) const; ColorRenderTarget * outputColorRenderTarget(size_t index) const; DepthRenderTarget * outputDepthRenderTarget(size_t index) const; - DepthStencilRenderTarget * outputDepthStencilRenderTarget(size_t index) const; + StencilRenderTarget * outputStencilRenderTarget(size_t index) const; /** * @brief @@ -106,7 +107,7 @@ class GLOPERATE_API RenderInterface */ void addRenderTargetInput(Input * input); void addRenderTargetInput(Input * input); - void addRenderTargetInput(Input * input); + void addRenderTargetInput(Input * input); /** * @brief @@ -117,25 +118,23 @@ class GLOPERATE_API RenderInterface */ void addRenderTargetOutput(Output * input); void addRenderTargetOutput(Output * input); - void addRenderTargetOutput(Output * input); + void addRenderTargetOutput(Output * input); void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); - void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; - static globjects::Framebuffer * configureFBO(size_t index, ColorRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); - static globjects::Framebuffer * configureFBO(size_t index, DepthRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); - static globjects::Framebuffer * configureFBO(size_t index, DepthStencilRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + static globjects::Framebuffer * configureFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); protected: - std::vector *> m_colorRenderTargetInputs; ///< List of input color render targets - std::vector *> m_depthRenderTargetInputs; ///< List of input depth render targets - std::vector *> m_depthStencilRenderTargetInputs; ///< List of input depth-stencil render targets - std::vector *> m_colorRenderTargetOutputs; ///< List of output color render targets (pass-through) - std::vector *> m_depthRenderTargetOutputs; ///< List of output depth render targets (pass-through) - std::vector *> m_depthStencilRenderTargetOutputs; ///< List of output depth-stencil render targets (pass-through) + std::vector *> m_colorRenderTargetInputs; ///< List of input color render targets + std::vector *> m_depthRenderTargetInputs; ///< List of input depth render targets + std::vector *> m_stencilRenderTargetInputs; ///< List of input depth-stencil render targets + std::vector *> m_colorRenderTargetOutputs; ///< List of output color render targets (pass-through) + std::vector *> m_depthRenderTargetOutputs; ///< List of output depth render targets (pass-through) + std::vector *> m_stencilRenderTargetOutputs; ///< List of output depth-stencil render targets (pass-through) }; diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 522ad1d2..adba1d19 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -163,7 +163,7 @@ Canvas::Canvas(Environment * environment) , m_replaceStage(false) , m_colorTarget(cppassist::make_unique()) , m_depthTarget(cppassist::make_unique()) -, m_depthStencilTarget(cppassist::make_unique()) +, m_stencilTarget(cppassist::make_unique()) { // Register functions addFunction("onStageInputChanged", this, &Canvas::scr_onStageInputChanged); @@ -184,7 +184,7 @@ Canvas::Canvas(Environment * environment) m_colorTarget->setAttachmentType(AttachmentType::Color); m_depthTarget->setAttachmentType(AttachmentType::Depth); - m_depthStencilTarget->setAttachmentType(AttachmentType::DepthStencil); + m_stencilTarget->setAttachmentType(AttachmentType::Stencil); } Canvas::~Canvas() @@ -386,7 +386,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) { m_colorTarget->setTarget(gl::GL_BACK_LEFT); m_depthTarget->setTarget(gl::GL_DEPTH_ATTACHMENT); - m_depthStencilTarget->setTarget(gl::GL_DEPTH_STENCIL_ATTACHMENT); + m_stencilTarget->setTarget(gl::GL_STENCIL_ATTACHMENT); } else { @@ -397,6 +397,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) colorAttachment = targetFBO->getAttachment(gl::GL_COLOR_ATTACHMENT0+i); } const auto depthAttachment = targetFBO->getAttachment(gl::GL_DEPTH_ATTACHMENT); + const auto stencilAttachment = targetFBO->getAttachment(gl::GL_STENCIL_ATTACHMENT); const auto depthStencilAttachment = targetFBO->getAttachment(gl::GL_DEPTH_STENCIL_ATTACHMENT); if (colorAttachment) @@ -411,17 +412,27 @@ void Canvas::render(globjects::Framebuffer * targetFBO) if (depthStencilAttachment) { m_depthTarget->setTarget(depthStencilAttachment); - m_depthStencilTarget->setTarget(depthStencilAttachment); - } - else if (depthAttachment) - { - m_depthTarget->setTarget(depthAttachment); - m_depthStencilTarget->setTarget(depthAttachment); + m_stencilTarget->setTarget(depthStencilAttachment); } else { - m_depthTarget->releaseTarget(); - m_depthStencilTarget->releaseTarget(); + if (depthAttachment) + { + m_depthTarget->setTarget(depthAttachment); + } + else + { + m_depthTarget->releaseTarget(); + } + + if (stencilAttachment) + { + m_stencilTarget->setTarget(stencilAttachment); + } + else + { + m_stencilTarget->releaseTarget(); + } } } @@ -446,7 +457,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) input->setValue(m_depthTarget.get()); }); - forAllInputs(m_renderStage.get(), [this](Input * input) { + forAllInputs(m_renderStage.get(), [this](Input * input) { const auto renderTarget = **input; if (renderTarget == nullptr) @@ -454,7 +465,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) return; } - input->setValue(m_depthStencilTarget.get()); + input->setValue(m_stencilTarget.get()); }); // Render diff --git a/source/gloperate/source/rendering/AbstractRenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp index 2f5307ce..a48a2216 100644 --- a/source/gloperate/source/rendering/AbstractRenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -63,7 +63,7 @@ gl::GLenum AbstractRenderTarget::attachmentGLType() const { case AttachmentType::Depth: return gl::GL_DEPTH; - case AttachmentType::DepthStencil: + case AttachmentType::Stencil: return gl::GL_DEPTH_STENCIL; case AttachmentType::Color: default: diff --git a/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp b/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp deleted file mode 100644 index 3ee669b2..00000000 --- a/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp +++ /dev/null @@ -1,9 +0,0 @@ - -#include - - -namespace gloperate -{ - - -} // namespace gloperate diff --git a/source/gloperate/source/rendering/StencilRenderTarget.cpp b/source/gloperate/source/rendering/StencilRenderTarget.cpp new file mode 100644 index 00000000..482ccb2b --- /dev/null +++ b/source/gloperate/source/rendering/StencilRenderTarget.cpp @@ -0,0 +1,9 @@ + +#include + + +namespace gloperate +{ + + +} // namespace gloperate diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 5c43b038..22c3d4b0 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -5,7 +5,10 @@ #include -#include +#include +#include +#include +#include namespace gloperate @@ -17,11 +20,12 @@ CPPEXPOSE_COMPONENT(BasicFramebufferStage, gloperate::Stage) BasicFramebufferStage::BasicFramebufferStage(Environment * environment, const std::string & name) : Stage(environment, "BasicFramebufferStage", name) -, viewport ("viewport", this) -, colorTexture("colorTexture", this) -, depthTexture("depthTexture", this) -, colorBuffer ("colorBuffer", this) -, depthBuffer ("depthBuffer", this) +, viewport ("viewport", this) +, colorTexture ("colorTexture", this) +, depthStencilTexture("depthStencilTexture", this) +, colorBuffer ("colorBuffer", this) +, depthBuffer ("depthBuffer", this) +, stencilBuffer ("stencilBuffer", this) { } @@ -31,28 +35,34 @@ BasicFramebufferStage::~BasicFramebufferStage() void BasicFramebufferStage::onContextInit(AbstractGLContext *) { + m_colorBuffer = cppassist::make_unique(); + m_colorBuffer->setAttachmentType(AttachmentType::Color); + + m_depthBuffer = cppassist::make_unique(); + m_depthBuffer->setAttachmentType(AttachmentType::DepthStencil); + + m_stencilBuffer = cppassist::make_unique(); + m_stencilBuffer->setAttachmentType(AttachmentType::DepthStencil); + // Create color texture m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - m_colorBuffer = cppassist::make_unique(); - m_colorBuffer->setTarget(m_colorTexture.get()); - m_colorBuffer->setAttachmentType(AttachmentType::Color); - // Create depth texture - m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); + m_depthStencilTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); - m_depthBuffer = cppassist::make_unique(); - m_depthBuffer->setTarget(m_depthTexture.get()); - m_depthBuffer->setAttachmentType(AttachmentType::Depth); + m_colorBuffer->setTarget(m_colorTexture.get()); + m_depthBuffer->setTarget(m_depthStencilTexture.get()); + m_stencilBuffer->setTarget(m_depthStencilTexture.get()); } void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) { // Clean up OpenGL objects - m_colorBuffer = nullptr; - m_depthBuffer = nullptr; - m_colorTexture = nullptr; - m_depthTexture = nullptr; + m_colorBuffer = nullptr; + m_depthBuffer = nullptr; + m_stencilBuffer = nullptr; + m_colorTexture = nullptr; + m_depthStencilTexture = nullptr; } void BasicFramebufferStage::onProcess() @@ -64,15 +74,16 @@ void BasicFramebufferStage::onProcess() m_colorTexture->image2D(0, gl::GL_RGBA, size.x, size.y, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, nullptr); - cppassist::debug() << "resize " << m_depthTexture->id(); + cppassist::debug() << "resize " << m_depthStencilTexture->id(); - m_depthTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_UNSIGNED_BYTE, nullptr); + m_depthStencilTexture->image2D(0, gl::GL_DEPTH24_STENCIL8, size.x, size.y, 0, gl::GL_DEPTH_STENCIL, gl::GL_UNSIGNED_BYTE, nullptr); // Update outputs this->colorTexture.setValue(m_colorTexture.get()); - this->depthTexture.setValue(m_depthTexture.get()); + this->depthStencilTexture.setValue(m_depthStencilTexture.get()); this->colorBuffer.setValue(m_colorBuffer.get()); this->depthBuffer.setValue(m_depthBuffer.get()); + this->stencilBuffer.setValue(m_stencilBuffer.get()); } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 7699c0cb..e869afb0 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace gloperate @@ -29,7 +29,7 @@ RenderInterface::RenderInterface(Stage * stage) stage->inputAdded.connect( [this] (AbstractSlot * connectedInput) { auto colorRenderTargetInput = dynamic_cast *>(connectedInput); auto depthRenderTargetInput = dynamic_cast *>(connectedInput); - auto depthStencilRenderTargetInput = dynamic_cast *>(connectedInput); + auto stencilRenderTargetInput = dynamic_cast *>(connectedInput); if (colorRenderTargetInput) { @@ -41,16 +41,16 @@ RenderInterface::RenderInterface(Stage * stage) addRenderTargetInput(depthRenderTargetInput); } - if (depthStencilRenderTargetInput) + if (stencilRenderTargetInput) { - addRenderTargetInput(depthStencilRenderTargetInput); + addRenderTargetInput(stencilRenderTargetInput); } }); stage->outputAdded.connect( [this] (AbstractSlot * connectedOutput) { auto colorRenderTargetOutput = dynamic_cast *>(connectedOutput); auto depthRenderTargetOutput = dynamic_cast *>(connectedOutput); - auto depthStencilRenderTargetOutput = dynamic_cast *>(connectedOutput); + auto stencilRenderTargetOutput = dynamic_cast *>(connectedOutput); if (colorRenderTargetOutput) { @@ -62,9 +62,9 @@ RenderInterface::RenderInterface(Stage * stage) addRenderTargetOutput(depthRenderTargetOutput); } - if (depthStencilRenderTargetOutput) + if (stencilRenderTargetOutput) { - addRenderTargetOutput(depthStencilRenderTargetOutput); + addRenderTargetOutput(stencilRenderTargetOutput); } }); } @@ -75,87 +75,198 @@ RenderInterface::~RenderInterface() bool RenderInterface::allRenderTargetsCompatible() const { - if (m_colorRenderTargetOutputs.empty() && m_depthRenderTargetOutputs.empty() && m_depthStencilRenderTargetOutputs.empty()) + if (m_colorRenderTargetOutputs.empty() && m_depthRenderTargetOutputs.empty() && m_stencilRenderTargetOutputs.empty()) { return true; } - auto numberOfDepthAttachments = m_depthRenderTargetOutputs.size() + m_depthStencilRenderTargetOutputs.size(); + auto numberOfDepthAttachments = m_depthRenderTargetOutputs.size() + m_stencilRenderTargetOutputs.size(); - auto allDefaultFramebufferAttachments = std::all_of(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { + auto allDefaultFramebufferAttachments = + std::all_of(m_colorRenderTargetInputs.begin(), m_colorRenderTargetInputs.end(), [](Input * input) { + return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }) && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { + return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }) && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; }); - auto allUserDefinedFramebufferAttachments = std::all_of(m_renderTargetInputs.begin(), m_renderTargetInputs.end(), [](Input * input) { - return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }); + auto allUserDefinedFramebufferAttachments = std::all_of(m_colorRenderTargetInputs.begin(), m_colorRenderTargetInputs.end(), [](Input * input) { + return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }) && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { + return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }) && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { + return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; + }); return allDefaultFramebufferAttachments != allUserDefinedFramebufferAttachments && numberOfDepthAttachments <= 1; } -size_t RenderInterface::renderTargetInputSize() const +const std::vector *> & RenderInterface::colorRenderTargetInputs() const +{ + return m_colorRenderTargetInputs; +} + +const std::vector *> & RenderInterface::depthRenderTargetInputs() const +{ + return m_depthRenderTargetInputs; +} + +const std::vector *> & RenderInterface::stencilRenderTargetInputs() const +{ + return m_stencilRenderTargetInputs; +} + +Input * RenderInterface::colorRenderTargetInput(size_t index) const +{ + return m_colorRenderTargetInputs.size() > index ? m_colorRenderTargetInputs.at(index) : nullptr; +} + +Input * RenderInterface::depthRenderTargetInput(size_t index) const { - return m_renderTargetInputs.size(); + return m_depthRenderTargetInputs.size() > index ? m_depthRenderTargetInputs.at(index) : nullptr; } -const std::vector *> & RenderInterface::renderTargetInputs() const +Input * RenderInterface::stencilRenderTargetInput(size_t index) const { - return m_renderTargetInputs; + return m_stencilRenderTargetInputs.size() > index ? m_stencilRenderTargetInputs.at(index) : nullptr; } -Input * RenderInterface::renderTargetInput(size_t index) const +ColorRenderTarget * RenderInterface::inputColorRenderTarget(size_t index) const { - return m_renderTargetInputs.size() > index ? m_renderTargetInputs.at(index) : nullptr; + const auto input = colorRenderTargetInput(index); + + return input ? **input : nullptr; } -RenderTarget * RenderInterface::inputRenderTarget(size_t index) const +DepthRenderTarget * RenderInterface::inputDepthRenderTarget(size_t index) const { - const auto input = renderTargetInput(index); + const auto input = depthRenderTargetInput(index); return input ? **input : nullptr; } -size_t RenderInterface::renderTargetOutputSize() const +StencilRenderTarget * RenderInterface::inputStencilRenderTarget(size_t index) const { - return m_renderTargetOutputs.size(); + const auto input = stencilRenderTargetInput(index); + + return input ? **input : nullptr; } -const std::vector *> & RenderInterface::renderTargetOutputs() const +const std::vector *> & RenderInterface::colorRenderTargetOutputs() const { - return m_renderTargetOutputs; + return m_colorRenderTargetOutputs; } -Output * RenderInterface::renderTargetOutput(size_t index) const +const std::vector *> & RenderInterface::depthRenderTargetOutputs() const { - return m_renderTargetOutputs.size() > index ? m_renderTargetOutputs.at(index) : nullptr; + return m_depthRenderTargetOutputs; } -RenderTarget * RenderInterface::outputRenderTarget(size_t index) const +const std::vector *> & RenderInterface::stencilRenderTargetOutputs() const { - const auto output = renderTargetOutput(index); + return m_stencilRenderTargetOutputs; +} + +Output * RenderInterface::colorRenderTargetOutput(size_t index) const +{ + return m_colorRenderTargetOutputs.size() > index ? m_colorRenderTargetOutputs.at(index) : nullptr; +} + +Output * RenderInterface::depthRenderTargetOutput(size_t index) const +{ + return m_depthRenderTargetOutputs.size() > index ? m_depthRenderTargetOutputs.at(index) : nullptr; +} + +Output * RenderInterface::stencilRenderTargetOutput(size_t index) const +{ + return m_stencilRenderTargetOutputs.size() > index ? m_stencilRenderTargetOutputs.at(index) : nullptr; +} + +ColorRenderTarget * RenderInterface::outputColorRenderTarget(size_t index) const +{ + const auto output = colorRenderTargetOutput(index); return output ? **output : nullptr; } -void RenderInterface::addRenderTargetInput(Input * input) +DepthRenderTarget * RenderInterface::outputDepthRenderTarget(size_t index) const { - m_renderTargetInputs.push_back(input); + const auto output = depthRenderTargetOutput(index); + + return output ? **output : nullptr; } -void RenderInterface::addRenderTargetOutput(Output * input) +StencilRenderTarget * RenderInterface::outputStencilRenderTarget(size_t index) const { - m_renderTargetOutputs.push_back(input); + const auto output = stencilRenderTargetOutput(index); + + return output ? **output : nullptr; +} + +void RenderInterface::addRenderTargetInput(Input * input) +{ + m_colorRenderTargetInputs.push_back(input); } -void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) +void RenderInterface::addRenderTargetInput(Input * input) +{ + m_depthRenderTargetInputs.push_back(input); +} + +void RenderInterface::addRenderTargetInput(Input * input) +{ + m_stencilRenderTargetInputs.push_back(input); +} + +void RenderInterface::addRenderTargetOutput(Output * input) +{ + m_colorRenderTargetOutputs.push_back(input); +} + +void RenderInterface::addRenderTargetOutput(Output * input) +{ + m_depthRenderTargetOutputs.push_back(input); +} + +void RenderInterface::addRenderTargetOutput(Output * input) +{ + m_stencilRenderTargetOutputs.push_back(input); +} + +void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) { const auto end = includeIncompletePairs - ? std::max(m_renderTargetInputs.size(), m_renderTargetOutputs.size()) - : std::min(m_renderTargetInputs.size(), m_renderTargetOutputs.size()); + ? std::max(m_colorRenderTargetInputs.size(), m_colorRenderTargetOutputs.size()) + : std::min(m_colorRenderTargetInputs.size(), m_colorRenderTargetOutputs.size()); for (auto i = size_t(0); i < end; ++i) { - callback(renderTargetInput(i), renderTargetOutput(i)); + callback(colorRenderTargetInput(i), colorRenderTargetOutput(i)); + } +} + +void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) +{ + const auto end = includeIncompletePairs + ? std::max(m_depthRenderTargetInputs.size(), m_depthRenderTargetOutputs.size()) + : std::min(m_depthRenderTargetInputs.size(), m_depthRenderTargetOutputs.size()); + + for (auto i = size_t(0); i < end; ++i) + { + callback(depthRenderTargetInput(i), depthRenderTargetOutput(i)); + } +} + +void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) +{ + const auto end = includeIncompletePairs + ? std::max(m_stencilRenderTargetInputs.size(), m_stencilRenderTargetOutputs.size()) + : std::min(m_stencilRenderTargetInputs.size(), m_stencilRenderTargetOutputs.size()); + + for (auto i = size_t(0); i < end; ++i) + { + callback(stencilRenderTargetInput(i), stencilRenderTargetOutput(i)); } } @@ -166,7 +277,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * std::vector drawBuffers; globjects::Framebuffer * currentFBO = nullptr; auto colorAttachmentIndex = size_t(0); - for (auto input : m_renderTargetInputs) + for (auto input : m_colorRenderTargetInputs) { auto nextFBO = configureFBO(colorAttachmentIndex, **input, fbo, defaultFBO); @@ -180,10 +291,45 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * return nullptr; } - if ((**input)->attachmentType() == AttachmentType::Color) + if (**input) { drawBuffers.push_back((**input)->type() == RenderTargetType::DefaultFBOAttachment ? (**input)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); - ++colorAttachmentIndex; + } + else + { + drawBuffers.push_back(gl::GL_NONE); + } + + ++colorAttachmentIndex; + } + + for (auto input : m_depthRenderTargetInputs) + { + auto nextFBO = configureFBO(0, **input, fbo, defaultFBO); + + if (!currentFBO) + { + currentFBO = nextFBO; + } + + if (nextFBO != currentFBO) + { + return nullptr; + } + } + + for (auto input : m_stencilRenderTargetInputs) + { + auto nextFBO = configureFBO(0, **input, fbo, defaultFBO); + + if (!currentFBO) + { + currentFBO = nextFBO; + } + + if (nextFBO != currentFBO) + { + return nullptr; } } @@ -192,7 +338,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * return currentFBO; } -globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) +globjects::Framebuffer * RenderInterface::configureFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) { auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; @@ -201,6 +347,11 @@ globjects::Framebuffer * RenderInterface::configureFBO(size_t index, RenderTarge attachmentIndex = gl::GL_DEPTH_ATTACHMENT; } + if (renderTarget->attachmentType() == AttachmentType::Stencil) + { + attachmentIndex = gl::GL_STENCIL_ATTACHMENT; + } + if (renderTarget->attachmentType() == AttachmentType::DepthStencil) { attachmentIndex = gl::GL_DEPTH_STENCIL_ATTACHMENT; From a9f8b7768dcc185817bf68c693b8f191ba22bf05 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Mon, 26 Jun 2017 16:19:58 +0200 Subject: [PATCH 17/33] Refine ClearStage and RasterizationStage --- .../gloperate/stages/base/ClearStage.h | 1 + .../stages/interfaces/RenderInterface.h | 2 + .../source/stages/base/ClearStage.cpp | 126 ++++++++++++------ .../source/stages/base/RasterizationStage.cpp | 4 +- .../stages/interfaces/RenderInterface.cpp | 12 ++ 5 files changed, 102 insertions(+), 43 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index 0a454377..8ca312c4 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -80,6 +80,7 @@ class GLOPERATE_API ClearStage : public Stage protected: std::vector *> m_colorValueInputs; std::vector *> m_depthValueInputs; + std::vector *> m_stencilValueInputs; std::vector> *> m_depthStencilValueInputs; std::unique_ptr m_defaultFBO; ///< Default FBO for clearing std::unique_ptr m_fbo; ///< Intermediate FBO for clearing diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index ce741474..b3efd8a7 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -72,6 +72,8 @@ class GLOPERATE_API RenderInterface */ ~RenderInterface(); + void updateRenderTargetOutputs(); + bool allRenderTargetsCompatible() const; const std::vector *> & colorRenderTargetInputs() const; diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index e02e42bf..245889f4 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -8,7 +8,9 @@ #include #include -#include +#include +#include +#include namespace gloperate @@ -26,6 +28,7 @@ ClearStage::ClearStage(Environment * environment, const std::string & name) inputAdded.connect( [this] (AbstractSlot * connectedInput) { auto colorValueInput = dynamic_cast *>(connectedInput); auto depthValueInput = dynamic_cast *>(connectedInput); + auto stencilValueInput = dynamic_cast *>(connectedInput); auto depthStencilValueInput = dynamic_cast> *>(connectedInput); if (colorValueInput) @@ -38,6 +41,11 @@ ClearStage::ClearStage(Environment * environment, const std::string & name) m_depthValueInputs.push_back(depthValueInput); } + if (stencilValueInput) + { + m_stencilValueInputs.push_back(stencilValueInput); + } + if (depthStencilValueInput) { m_depthStencilValueInputs.push_back(depthStencilValueInput); @@ -78,65 +86,105 @@ void ClearStage::onProcess() size_t colorAttachmentIndex = 0; size_t depthAttachmentIndex = 0; + size_t stencilAttachmentIndex = 0; size_t depthStencilAttachmentIndex = 0; + std::set clearedDepthStencilTargets; - renderInterface.pairwiseRenderTargetsDo([this, & colorAttachmentIndex, & depthAttachmentIndex, & depthStencilAttachmentIndex](Input * input, Output * output) { + renderInterface.pairwiseRenderTargetsDo([this, & colorAttachmentIndex](Input * input, Output * output) { if (!output->isRequired() || !**input) { return; } - switch ((**input)->attachmentType()) + if (m_colorValueInputs.size() <= colorAttachmentIndex) { - case AttachmentType::Color: - { - if (m_colorValueInputs.size() <= colorAttachmentIndex) - { - return; - } + return; + } - auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - const auto attachmentBuffer = (**input)->attachmentBuffer(); - const auto attachmentDrawBuffer = (**input)->attachmentDrawBuffer(colorAttachmentIndex); - const auto clearColor = **m_colorValueInputs.at(colorAttachmentIndex); + const auto attachmentBuffer = (**input)->attachmentBuffer(); + const auto attachmentDrawBuffer = (**input)->attachmentDrawBuffer(colorAttachmentIndex); + const auto clearColor = **m_colorValueInputs.at(colorAttachmentIndex); - fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColor); + fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColor); - ++colorAttachmentIndex; - } - break; - case AttachmentType::Depth: + ++colorAttachmentIndex; + }); + + renderInterface.pairwiseRenderTargetsDo([this, & depthAttachmentIndex, & depthStencilAttachmentIndex, & clearedDepthStencilTargets](Input * input, Output * output) { + if (!output->isRequired() || !**input) + { + return; + } + + if ((**input)->attachmentType() == AttachmentType::Depth) + { + if (m_depthValueInputs.size() <= depthAttachmentIndex) { - if (m_depthValueInputs.size() <= depthAttachmentIndex) - { - return; - } + return; + } - auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH_STENCIL, **m_depthValueInputs.at(depthAttachmentIndex), 0, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, **m_depthValueInputs.at(depthAttachmentIndex), 0, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); - ++depthAttachmentIndex; + ++depthAttachmentIndex; + } + else if ((**input)->attachmentType() == AttachmentType::DepthStencil) + { + if (m_depthStencilValueInputs.size() <= depthStencilAttachmentIndex) + { + return; } - break; - case AttachmentType::DepthStencil: + + auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthStencilAttachmentIndex)); + + ++depthStencilAttachmentIndex; + clearedDepthStencilTargets.insert(**input); + } + }); + + renderInterface.pairwiseRenderTargetsDo([this, & stencilAttachmentIndex, & depthStencilAttachmentIndex, & clearedDepthStencilTargets](Input * input, Output * output) { + if (!output->isRequired() || !**input) + { + return; + } + + if ((**input)->attachmentType() == AttachmentType::Stencil) + { + if (m_stencilValueInputs.size() <= stencilAttachmentIndex) { - if (m_depthStencilValueInputs.size() <= depthStencilAttachmentIndex) - { - return; - } + return; + } - auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.configureFBO(stencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); + fbo->clearBuffer(gl::GL_STENCIL, (**input)->attachmentDrawBuffer(stencilAttachmentIndex), **m_stencilValueInputs.at(stencilAttachmentIndex)); - ++depthStencilAttachmentIndex; + ++stencilAttachmentIndex; + } + else if ((**input)->attachmentType() == AttachmentType::DepthStencil) + { + if (std::find(clearedDepthStencilTargets.begin(), clearedDepthStencilTargets.end(), **input) != clearedDepthStencilTargets.end()) + { + return; + } + + if (m_depthStencilValueInputs.size() <= depthStencilAttachmentIndex) + { + return; } - break; - default: - break; + + auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthStencilAttachmentIndex)); + + ++depthStencilAttachmentIndex; } + }); // Reset OpenGL state @@ -144,9 +192,7 @@ void ClearStage::onProcess() } // Update outputs - renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { - output->setValue(**input); - }); + renderInterface.updateRenderTargetOutputs(); } } // namespace gloperate diff --git a/source/gloperate/source/stages/base/RasterizationStage.cpp b/source/gloperate/source/stages/base/RasterizationStage.cpp index 242dce84..61ddfd6e 100644 --- a/source/gloperate/source/stages/base/RasterizationStage.cpp +++ b/source/gloperate/source/stages/base/RasterizationStage.cpp @@ -71,9 +71,7 @@ void RasterizationStage::onProcess() } // Update outputs - renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { - output->setValue(**input); - }); + renderInterface.updateRenderTargetOutputs(); } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index e869afb0..18c519a3 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -73,6 +73,18 @@ RenderInterface::~RenderInterface() { } +void RenderInterface::updateRenderTargetOutputs() { + pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); + pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); + pairwiseRenderTargetsDo([](Input * input, Output * output) { + output->setValue(**input); + }); +} + bool RenderInterface::allRenderTargetsCompatible() const { if (m_colorRenderTargetOutputs.empty() && m_depthRenderTargetOutputs.empty() && m_stencilRenderTargetOutputs.empty()) From 6e20c15d1db622d184b62362c5a2e0715a7836d8 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 27 Jun 2017 11:53:56 +0200 Subject: [PATCH 18/33] Fix ClearStage behavior, refactor Texture- and RenderbufferRenderTargetStage --- .../base/RenderbufferRenderTargetStage.h | 18 +++--- .../stages/base/TextureRenderTargetStage.h | 18 +++--- .../source/stages/base/ClearStage.cpp | 2 +- .../base/RenderbufferRenderTargetStage.cpp | 57 ++++++++++++++++--- .../stages/base/TextureRenderTargetStage.cpp | 57 ++++++++++++++++--- 5 files changed, 119 insertions(+), 33 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h index ca5bf7b9..577d484b 100644 --- a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h @@ -26,7 +26,7 @@ namespace gloperate class ColorRenderTarget; class DepthRenderTarget; -class DepthStencilRenderTarget; +class StencilRenderTarget; /** @@ -53,10 +53,10 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs - Output renderbuffer; ///< Renderbuffer - Output colorRenderTarget; ///< Color RenderTarget - Output depthRenderTarget; ///< Depth RenderTarget - Output depthStencilRenderTarget; ///< Stencil RenderTarget + Output renderbuffer; ///< Renderbuffer + Output colorRenderTarget; ///< Color RenderTarget + Output depthRenderTarget; ///< Depth RenderTarget + Output stencilRenderTarget; ///< Stencil RenderTarget public: @@ -86,10 +86,10 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage protected: - std::unique_ptr m_renderbuffer; ///< The created renderbuffer - std::unique_ptr m_colorRenderTarget; ///< The color render target - std::unique_ptr m_depthRenderTarget; ///< The depth render target - std::unique_ptr m_depthStencilRenderTarget; ///< The depth stencil render target + std::unique_ptr m_renderbuffer; ///< The created renderbuffer + std::unique_ptr m_colorRenderTarget; ///< The color render target + std::unique_ptr m_depthRenderTarget; ///< The depth render target + std::unique_ptr m_stencilRenderTarget; ///< The stencil render target }; diff --git a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h index 05913783..06b22b14 100644 --- a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h @@ -26,7 +26,7 @@ namespace gloperate class ColorRenderTarget; class DepthRenderTarget; -class DepthStencilRenderTarget; +class StencilRenderTarget; /** @@ -55,10 +55,10 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs - Output texture; ///< Texture - Output colorRenderTarget; ///< Color RenderTarget - Output depthRenderTarget; ///< Depth RenderTarget - Output depthStencilRenderTarget; ///< Stencil RenderTarget + Output texture; ///< Texture + Output colorRenderTarget; ///< Color RenderTarget + Output depthRenderTarget; ///< Depth RenderTarget + Output stencilRenderTarget; ///< Stencil RenderTarget public: @@ -88,10 +88,10 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage protected: - std::unique_ptr m_texture; ///< The created texture - std::unique_ptr m_colorRenderTarget; ///< The color render target - std::unique_ptr m_depthRenderTarget; ///< The depth render target - std::unique_ptr m_depthStencilRenderTarget; ///< The depth stencil render target + std::unique_ptr m_texture; ///< The created texture + std::unique_ptr m_colorRenderTarget; ///< The color render target + std::unique_ptr m_depthRenderTarget; ///< The depth render target + std::unique_ptr m_stencilRenderTarget; ///< The stencil render target }; diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index 245889f4..d9b869d3 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -127,7 +127,7 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH_STENCIL, **m_depthValueInputs.at(depthAttachmentIndex), 0, (**input)->attachmentDrawBuffer(depthAttachmentIndex)); + fbo->clearBuffer(gl::GL_DEPTH, (**input)->attachmentDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex)); ++depthAttachmentIndex; } diff --git a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp index b0261eab..b442a228 100644 --- a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp +++ b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp @@ -8,7 +8,9 @@ #include -#include +#include +#include +#include using namespace gl; @@ -27,7 +29,9 @@ RenderbufferRenderTargetStage::RenderbufferRenderTargetStage(gloperate::Environm , internalFormat("internalFormat", this) , size("size", this) , renderbuffer("renderbuffer", this) -, renderTarget("renderTarget", this) +, colorRenderTarget("colorRenderTarget", this) +, depthRenderTarget("depthRenderTarget", this) +, stencilRenderTarget("stencilRenderTarget", this) { } @@ -41,15 +45,21 @@ void RenderbufferRenderTargetStage::onContextInit(gloperate::AbstractGLContext * m_renderbuffer = cppassist::make_unique(); // Create wrapping render target - m_renderTarget = cppassist::make_unique(); - m_renderTarget->setTarget(m_renderbuffer.get()); + m_colorRenderTarget = cppassist::make_unique(); + m_depthRenderTarget = cppassist::make_unique(); + m_stencilRenderTarget = cppassist::make_unique(); + + m_colorRenderTarget->setAttachmentType(AttachmentType::Color); + m_stencilRenderTarget->setAttachmentType(AttachmentType::DepthStencil); } void RenderbufferRenderTargetStage::onContextDeinit(AbstractGLContext *) { // Clean up OpenGL objects - m_renderbuffer = nullptr; - m_renderTarget = nullptr; + m_renderbuffer = nullptr; + m_colorRenderTarget = nullptr; + m_depthRenderTarget = nullptr; + m_stencilRenderTarget = nullptr; } void RenderbufferRenderTargetStage::onProcess() @@ -65,9 +75,42 @@ void RenderbufferRenderTargetStage::onProcess() const auto height = (*size)[3]; m_renderbuffer->storage(*internalFormat, width, height); + switch(*internalFormat) + { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32F: + m_colorRenderTarget->releaseTarget(); + m_stencilRenderTarget->releaseTarget(); + + m_depthRenderTarget->setTarget(m_renderbuffer.get()); + + m_depthRenderTarget->setAttachmentType(AttachmentType::Depth); + break; + case GL_DEPTH_STENCIL: + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + m_colorRenderTarget->releaseTarget(); + + m_depthRenderTarget->setTarget(m_renderbuffer.get()); + m_stencilRenderTarget->setTarget(m_renderbuffer.get()); + + m_depthRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + break; + default: // Color attachment + m_depthRenderTarget->releaseTarget(); + m_stencilRenderTarget->releaseTarget(); + + m_colorRenderTarget->setTarget(m_renderbuffer.get()); + break; + } + // Update outputs renderbuffer.setValue(m_renderbuffer.get()); - renderTarget.setValue(m_renderTarget.get()); + colorRenderTarget.setValue(m_colorRenderTarget.get()); + depthRenderTarget.setValue(m_depthRenderTarget.get()); + stencilRenderTarget.setValue(m_stencilRenderTarget.get()); } diff --git a/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp index 4a71f795..45e5299e 100644 --- a/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp +++ b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp @@ -8,7 +8,9 @@ #include -#include +#include +#include +#include using namespace gl; @@ -29,7 +31,9 @@ TextureRenderTargetStage::TextureRenderTargetStage(gloperate::Environment * envi , type("type", this) , size("size", this) , texture("texture", this) -, renderTarget("renderTarget", this) +, colorRenderTarget("colorRenderTarget", this) +, depthRenderTarget("depthRenderTarget", this) +, stencilRenderTarget("stencilRenderTarget", this) { } @@ -43,15 +47,21 @@ void TextureRenderTargetStage::onContextInit(gloperate::AbstractGLContext *) m_texture = Texture::createDefault(GL_TEXTURE_2D); // Create wrapping render target - m_renderTarget = cppassist::make_unique(); - m_renderTarget->setTarget(m_texture.get()); + m_colorRenderTarget = cppassist::make_unique(); + m_depthRenderTarget = cppassist::make_unique(); + m_stencilRenderTarget = cppassist::make_unique(); + + m_colorRenderTarget->setAttachmentType(AttachmentType::Color); + m_stencilRenderTarget->setAttachmentType(AttachmentType::DepthStencil); } void TextureRenderTargetStage::onContextDeinit(AbstractGLContext *) { // Clean up OpenGL objects - m_texture = nullptr; - m_renderTarget = nullptr; + m_texture = nullptr; + m_colorRenderTarget = nullptr; + m_depthRenderTarget = nullptr; + m_stencilRenderTarget = nullptr; } void TextureRenderTargetStage::onProcess() @@ -67,9 +77,42 @@ void TextureRenderTargetStage::onProcess() const auto height = (*size)[3]; m_texture->image2D(0, *internalFormat, width, height, 0, *format, *type, nullptr); + switch(*internalFormat) + { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32F: + m_colorRenderTarget->releaseTarget(); + m_stencilRenderTarget->releaseTarget(); + + m_depthRenderTarget->setTarget(m_texture.get()); + + m_depthRenderTarget->setAttachmentType(AttachmentType::Depth); + break; + case GL_DEPTH_STENCIL: + case GL_DEPTH24_STENCIL8: + case GL_DEPTH32F_STENCIL8: + m_colorRenderTarget->releaseTarget(); + + m_depthRenderTarget->setTarget(m_texture.get()); + m_stencilRenderTarget->setTarget(m_texture.get()); + + m_depthRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + break; + default: // Color attachment + m_depthRenderTarget->releaseTarget(); + m_stencilRenderTarget->releaseTarget(); + + m_colorRenderTarget->setTarget(m_texture.get()); + break; + } + // Update outputs texture.setValue(m_texture.get()); - renderTarget.setValue(m_renderTarget.get()); + colorRenderTarget.setValue(m_colorRenderTarget.get()); + depthRenderTarget.setValue(m_depthRenderTarget.get()); + stencilRenderTarget.setValue(m_stencilRenderTarget.get()); } From a91e6434af7f06d675aad4849499ea01b02e5907 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 27 Jun 2017 13:53:32 +0200 Subject: [PATCH 19/33] Finish RenderTarget subclasses refactoring --- .../demo-stages-plugins/ShapeDemo.cpp | 19 ++++----- .../examples/demo-stages-plugins/ShapeDemo.h | 3 -- .../IntermediateFramePreparationStage.h | 8 ++-- .../IntermediateFramePreparationStage.cpp | 2 +- .../stages/MultiFrameAggregationPipeline.cpp | 40 +++++++------------ .../stages/MultiFrameAggregationStage.cpp | 6 +-- .../stages/base/BasicFramebufferStage.h | 4 +- .../stages/base/BasicFramebufferStage.cpp | 15 ++----- .../FFMPEGVideoExporter.cpp | 2 +- 9 files changed, 36 insertions(+), 63 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 2cbcf8aa..555dc968 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include CPPEXPOSE_COMPONENT(ShapeDemo, gloperate::Stage) @@ -37,7 +37,6 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , angle("angle", this, 0.0f) , rotate("rotate", this, false) , color("color", this, Color(255, 255, 255, 255)) -, m_colorTarget(cppassist::make_unique()) , m_timer(cppassist::make_unique(environment, "Timer")) , m_floatSelection(cppassist::make_unique(environment, "FloatSelection")) , m_trackball(cppassist::make_unique(environment, "Trackball")) @@ -53,8 +52,6 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , m_colorizeRenderPass(cppassist::make_unique(environment, "ColorizeRenderPass")) , m_colorizeRasterization(cppassist::make_unique(environment, "ColorizeRasterization")) { - m_colorTarget->setAttachmentType(gloperate::AttachmentType::Color); - // Get data path std::string dataPath = gloperate::dataPath(); @@ -133,8 +130,8 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Rasterization stage for shape addStage(m_shapeRasterization.get()); - m_shapeRasterization->createInput("ColorAttachment") << *m_clear->createOutput("ColorAttachmentOut"); - m_shapeRasterization->createInput("DepthAttachment") << *m_clear->createOutput("DepthAttachmentOut"); + m_shapeRasterization->createInput("ColorAttachment") << *m_clear->createOutput("ColorAttachmentOut"); + m_shapeRasterization->createInput("DepthAttachment") << *m_clear->createOutput("DepthAttachmentOut"); m_shapeRasterization->renderInterface.viewport << canvasInterface.viewport; m_shapeRasterization->drawable << m_shapeRenderPass->renderPass; @@ -157,25 +154,25 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRenderPass->createInput("source") << *colorTextureOutput; /* Hack Start */ - auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); + auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); shapeColorOutput->valueChanged.onFire([=]() { colorTextureOutput->setValue(**colorTextureInput); }); shapeColorOutput->valueInvalidated.onFire([=]() { - m_clear->renderInterface.renderTargetOutput(0)->invalidate(); - m_clear->renderInterface.renderTargetOutput(1)->invalidate(); + m_clear->renderInterface.colorRenderTargetOutput(0)->invalidate(); + m_clear->renderInterface.depthRenderTargetOutput(0)->invalidate(); }); /* Hack End */ // Colorize rasterization stage addStage(m_colorizeRasterization.get()); - m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color", m_colorTarget.get()); + m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color"); m_colorizeRasterization->renderInterface.viewport << canvasInterface.viewport; m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; // Outputs //*createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); - *createOutput("ColorOut") << *shapeColorOutput; + *createOutput("ColorOut") << *shapeColorOutput; //*createOutput("ViewportOut") = glm::vec4(0, 0, 700, 700); // Start rotation diff --git a/source/examples/demo-stages-plugins/ShapeDemo.h b/source/examples/demo-stages-plugins/ShapeDemo.h index 5e854439..e6aac5f0 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.h +++ b/source/examples/demo-stages-plugins/ShapeDemo.h @@ -88,9 +88,6 @@ class ShapeDemo : public gloperate::Pipeline protected: - // Misc - std::unique_ptr m_colorTarget; - // Stages std::unique_ptr m_timer; ///< Timer for continuous rendering and animation diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h index 9fb41460..5cc8dfe3 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h @@ -37,14 +37,14 @@ class GLOPERATE_GLKERNEL_API IntermediateFramePreparationStage : public gloperat public: // Render Interface - gloperate::RenderInterface renderInterface; ///< Render interface for aggregation target + gloperate::RenderInterface renderInterface; ///< Render interface for aggregation target // Inputs - Input intermediateRenderTarget; ///< Intermediate frame render target - Input intermediateFrameTexture; ///< Designated intermediate frame texture + Input intermediateRenderTarget; ///< Intermediate frame render target + Input intermediateFrameTexture; ///< Designated intermediate frame texture // Outputs - Output intermediateFrameTextureOut; ///< Intermediate frame texture with same contents as intermediateRenderTarget + Output intermediateFrameTextureOut; ///< Intermediate frame texture with same contents as intermediateRenderTarget public: diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index a06d3a60..1fec1f2c 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index 840037d3..fe512fc6 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -134,8 +134,8 @@ MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environm // Additional Stages , m_renderStage(nullptr) { - canvasInterface.addRenderTargetInput(createInput("ColorTarget")); - canvasInterface.addRenderTargetOutput(createOutput("ColorTargetOut")); + createInput ("ColorTarget"); + createOutput("ColorTargetOut"); addStage(m_colorRenderTargetStage.get()); m_colorRenderTargetStage->size << canvasInterface.viewport; @@ -158,8 +158,8 @@ MultiFrameAggregationPipeline::MultiFrameAggregationPipeline(gloperate::Environm m_framePreparationStage->intermediateFrameTexture << m_colorRenderTargetStage->texture; addStage(m_aggregationStage.get()); - (*m_aggregationStage->createInput("ColorTarget")) << (*canvasInterface.renderTargetInput(0)); - (*canvasInterface.renderTargetOutput(0)) << (*m_aggregationStage->createOutput("ColorTargetOut")); + (*m_aggregationStage->createInput("ColorTarget")) << (*canvasInterface.colorRenderTargetInput(0)); + (*canvasInterface.colorRenderTargetOutput(0)) << (*m_aggregationStage->createOutput("ColorTargetOut")); m_aggregationStage->intermediateFrame << m_framePreparationStage->intermediateFrameTextureOut; // set by setRenderStage m_aggregationStage->renderInterface.viewport << canvasInterface.viewport; m_aggregationStage->aggregationFactor << m_controlStage->aggregationFactor; @@ -201,30 +201,20 @@ void MultiFrameAggregationPipeline::setRenderStage(gloperate::Stage * stage) (*slotViewport) << canvasInterface.viewport; // Update render stage input render targets - forAllInputs(m_renderStage, [this](Input * input) { - gloperate::RenderTarget * renderTarget = **input; - - switch (renderTarget->attachmentType()) - { - case gloperate::AttachmentType::Color: - (*input) << m_colorRenderTargetStage->renderTarget; - break; - case gloperate::AttachmentType::Depth: - (*input) << m_depthStencilRenderTargetStage->renderTarget; - break; - case gloperate::AttachmentType::DepthStencil: - (*input) << m_depthStencilRenderTargetStage->renderTarget; - break; - default: - input->setValue(nullptr); - } + forAllInputs(m_renderStage, [this](Input * input) { + (*input) << m_colorRenderTargetStage->colorRenderTarget; + }); + forAllInputs(m_renderStage, [this](Input * input) { + (*input) << m_depthStencilRenderTargetStage->depthRenderTarget; + }); + forAllInputs(m_renderStage, [this](Input * input) { + (*input) << m_depthStencilRenderTargetStage->stencilRenderTarget; }); - // Connect Color Output - auto slotColorRenderTarget = getOutput(m_renderStage, [](Output * output) { - gloperate::RenderTarget * target = **output; - return target->attachmentType() == gloperate::AttachmentType::Color; + // Connect Color Output + auto slotColorRenderTarget = getOutput(m_renderStage, [](Output * /*output*/) { + return true; }); if (slotColorRenderTarget) diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp index afe17909..a03fc65d 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include @@ -75,9 +75,7 @@ void MultiFrameAggregationStage::onProcess() gl::glDisable(gl::GL_BLEND); - renderInterface.pairwiseRenderTargetsDo([](Input * input, Output * output) { - output->setValue(**input); - }); + renderInterface.updateRenderTargetOutputs(); } diff --git a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h index a7f4fcd8..dfd6d232 100644 --- a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h +++ b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h @@ -54,10 +54,9 @@ class GLOPERATE_API BasicFramebufferStage : public Stage // Outputs Output colorTexture; ///< Color texture - Output depthStencilTexture; ///< Combined depth-stencil texture + Output depthTexture; ///< Combined depth-stencil texture Output colorBuffer; ///< Color attachment Output depthBuffer; ///< Depth attachment - Output stencilBuffer; ///< Stencil attachment public: @@ -91,7 +90,6 @@ class GLOPERATE_API BasicFramebufferStage : public Stage std::unique_ptr m_depthStencilTexture; ///< Internal, combined depth-stencil texture std::unique_ptr m_colorBuffer; ///< Color texture std::unique_ptr m_depthBuffer; ///< Depth texture - std::unique_ptr m_stencilBuffer; ///< Stencil texture }; diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 22c3d4b0..14b27803 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -22,10 +22,9 @@ BasicFramebufferStage::BasicFramebufferStage(Environment * environment, const st : Stage(environment, "BasicFramebufferStage", name) , viewport ("viewport", this) , colorTexture ("colorTexture", this) -, depthStencilTexture("depthStencilTexture", this) +, depthTexture("depthStencilTexture", this) , colorBuffer ("colorBuffer", this) , depthBuffer ("depthBuffer", this) -, stencilBuffer ("stencilBuffer", this) { } @@ -39,10 +38,7 @@ void BasicFramebufferStage::onContextInit(AbstractGLContext *) m_colorBuffer->setAttachmentType(AttachmentType::Color); m_depthBuffer = cppassist::make_unique(); - m_depthBuffer->setAttachmentType(AttachmentType::DepthStencil); - - m_stencilBuffer = cppassist::make_unique(); - m_stencilBuffer->setAttachmentType(AttachmentType::DepthStencil); + m_depthBuffer->setAttachmentType(AttachmentType::Depth); // Create color texture m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); @@ -52,7 +48,6 @@ void BasicFramebufferStage::onContextInit(AbstractGLContext *) m_colorBuffer->setTarget(m_colorTexture.get()); m_depthBuffer->setTarget(m_depthStencilTexture.get()); - m_stencilBuffer->setTarget(m_depthStencilTexture.get()); } void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) @@ -60,7 +55,6 @@ void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) // Clean up OpenGL objects m_colorBuffer = nullptr; m_depthBuffer = nullptr; - m_stencilBuffer = nullptr; m_colorTexture = nullptr; m_depthStencilTexture = nullptr; } @@ -76,14 +70,13 @@ void BasicFramebufferStage::onProcess() cppassist::debug() << "resize " << m_depthStencilTexture->id(); - m_depthStencilTexture->image2D(0, gl::GL_DEPTH24_STENCIL8, size.x, size.y, 0, gl::GL_DEPTH_STENCIL, gl::GL_UNSIGNED_BYTE, nullptr); + m_depthStencilTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_FLOAT, nullptr); // Update outputs this->colorTexture.setValue(m_colorTexture.get()); - this->depthStencilTexture.setValue(m_depthStencilTexture.get()); + this->depthTexture.setValue(m_depthStencilTexture.get()); this->colorBuffer.setValue(m_colorBuffer.get()); this->depthBuffer.setValue(m_depthBuffer.get()); - this->stencilBuffer.setValue(m_stencilBuffer.get()); } diff --git a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp index 4ca10fa6..f3f18947 100644 --- a/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp +++ b/source/plugins/gloperate-ffmpeg-exporter/FFMPEGVideoExporter.cpp @@ -92,7 +92,7 @@ void FFMPEGVideoExporter::createVideo(AbstractVideoExporter::ContextHandling con auto fps = m_parameters.at("fps").toULongLong(); auto length = m_parameters.at("duration").toULongLong() * fps; - auto timeDelta = 1.f / static_cast(fps); + //auto timeDelta = 1.f / static_cast(fps); initialize(contextHandling); From f3c290445de78088dee89cf1de2faeaf0fe02489 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 27 Jun 2017 13:57:56 +0200 Subject: [PATCH 20/33] Cleanup BasicFramebufferStage --- .../stages/base/BasicFramebufferStage.h | 16 ++++++------- .../stages/base/BasicFramebufferStage.cpp | 24 ++++++++----------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h index dfd6d232..5115a3b7 100644 --- a/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h +++ b/source/gloperate/include/gloperate/stages/base/BasicFramebufferStage.h @@ -53,10 +53,10 @@ class GLOPERATE_API BasicFramebufferStage : public Stage Input viewport; ///< Texture size // Outputs - Output colorTexture; ///< Color texture - Output depthTexture; ///< Combined depth-stencil texture - Output colorBuffer; ///< Color attachment - Output depthBuffer; ///< Depth attachment + Output colorTexture; ///< Color texture + Output depthTexture; ///< Depth texture + Output colorBuffer; ///< Color attachment + Output depthBuffer; ///< Depth attachment public: @@ -86,10 +86,10 @@ class GLOPERATE_API BasicFramebufferStage : public Stage protected: - std::unique_ptr m_colorTexture; ///< Internal color texture - std::unique_ptr m_depthStencilTexture; ///< Internal, combined depth-stencil texture - std::unique_ptr m_colorBuffer; ///< Color texture - std::unique_ptr m_depthBuffer; ///< Depth texture + std::unique_ptr m_colorTexture; ///< Internal color texture + std::unique_ptr m_depthTexture; ///< Internal depth texture + std::unique_ptr m_colorBuffer; ///< Color texture + std::unique_ptr m_depthBuffer; ///< Depth texture }; diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 14b27803..60cf1d6c 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -20,11 +20,11 @@ CPPEXPOSE_COMPONENT(BasicFramebufferStage, gloperate::Stage) BasicFramebufferStage::BasicFramebufferStage(Environment * environment, const std::string & name) : Stage(environment, "BasicFramebufferStage", name) -, viewport ("viewport", this) -, colorTexture ("colorTexture", this) -, depthTexture("depthStencilTexture", this) -, colorBuffer ("colorBuffer", this) -, depthBuffer ("depthBuffer", this) +, viewport ("viewport", this) +, colorTexture ("colorTexture", this) +, depthTexture ("depthTexture", this) +, colorBuffer ("colorBuffer", this) +, depthBuffer ("depthBuffer", this) { } @@ -44,10 +44,10 @@ void BasicFramebufferStage::onContextInit(AbstractGLContext *) m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); // Create depth texture - m_depthStencilTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); + m_depthTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); m_colorBuffer->setTarget(m_colorTexture.get()); - m_depthBuffer->setTarget(m_depthStencilTexture.get()); + m_depthBuffer->setTarget(m_depthTexture.get()); } void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) @@ -56,7 +56,7 @@ void BasicFramebufferStage::onContextDeinit(AbstractGLContext *) m_colorBuffer = nullptr; m_depthBuffer = nullptr; m_colorTexture = nullptr; - m_depthStencilTexture = nullptr; + m_depthTexture = nullptr; } void BasicFramebufferStage::onProcess() @@ -64,17 +64,13 @@ void BasicFramebufferStage::onProcess() // Get texture size glm::ivec2 size = glm::ivec2((*this->viewport).z, (*this->viewport).w); - cppassist::debug() << "resize " << m_colorTexture->id(); - m_colorTexture->image2D(0, gl::GL_RGBA, size.x, size.y, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, nullptr); - cppassist::debug() << "resize " << m_depthStencilTexture->id(); - - m_depthStencilTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_FLOAT, nullptr); + m_depthTexture->image2D(0, gl::GL_DEPTH_COMPONENT, size.x, size.y, 0, gl::GL_DEPTH_COMPONENT, gl::GL_FLOAT, nullptr); // Update outputs this->colorTexture.setValue(m_colorTexture.get()); - this->depthTexture.setValue(m_depthStencilTexture.get()); + this->depthTexture.setValue(m_depthTexture.get()); this->colorBuffer.setValue(m_colorBuffer.get()); this->depthBuffer.setValue(m_depthBuffer.get()); } From 31022b241517ba5763585f09d1a7240bfcbaffd2 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 27 Jun 2017 15:26:26 +0200 Subject: [PATCH 21/33] Extend Stage find input and output interface --- .../stages/MultiFrameAggregationPipeline.cpp | 109 +-------------- .../include/gloperate/pipeline/Stage.h | 53 ++++++++ .../include/gloperate/pipeline/Stage.inl | 74 +++++++++++ source/gloperate/source/base/Canvas.cpp | 124 ++---------------- source/gloperate/source/pipeline/Stage.cpp | 16 +++ 5 files changed, 158 insertions(+), 218 deletions(-) diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index fe512fc6..86232882 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -14,105 +14,6 @@ #include -namespace -{ - - -template -gloperate::Slot * getSlot(gloperate::Stage * stage, const std::string & name) -{ - if (!stage) { - return nullptr; - } else { - return static_cast *>(stage->property(name)); - } -} - -template -gloperate::Input * getInput(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return nullptr; - } - - const auto & inputs = stage->inputs(); - - const auto it = std::find_if(inputs.begin(), inputs.end(), [callback](gloperate::AbstractSlot * slot) { - const auto input = dynamic_cast *>(slot); - - if (!input) - { - return false; - } - - return callback(input); - }); - - if (it == inputs.end()) - { - return nullptr; - } - - return static_cast *>(*it); -} - -template -void forAllInputs(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return; - } - - const auto & inputs = stage->inputs(); - - for (const auto input : inputs) - { - const auto inputT = dynamic_cast *>(input); - - if (!inputT) - { - continue; - } - - callback(inputT); - } -} - -template -gloperate::Output * getOutput(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return nullptr; - } - - const auto & outputs = stage->outputs(); - - const auto it = std::find_if(outputs.begin(), outputs.end(), [callback](gloperate::AbstractSlot * slot) { - const auto output = dynamic_cast *>(slot); - - if (!output) - { - return false; - } - - return callback(output); - }); - - if (it == outputs.end()) - { - return nullptr; - } - - return static_cast *>(*it); -} - - -} - - namespace gloperate_glkernel { @@ -197,23 +98,23 @@ void MultiFrameAggregationPipeline::setRenderStage(gloperate::Stage * stage) m_renderStage = stage; // Promote viewport information - auto slotViewport = getInput(m_renderStage, [](Input* input) { return input->name() == "viewport"; }); + auto slotViewport = m_renderStage->findInput([](Input* input) { return input->name() == "viewport"; }); (*slotViewport) << canvasInterface.viewport; // Update render stage input render targets - forAllInputs(m_renderStage, [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { (*input) << m_colorRenderTargetStage->colorRenderTarget; }); - forAllInputs(m_renderStage, [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { (*input) << m_depthStencilRenderTargetStage->depthRenderTarget; }); - forAllInputs(m_renderStage, [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { (*input) << m_depthStencilRenderTargetStage->stencilRenderTarget; }); // Connect Color Output - auto slotColorRenderTarget = getOutput(m_renderStage, [](Output * /*output*/) { + auto slotColorRenderTarget = m_renderStage->findOutput([](Output * /*output*/) { return true; }); diff --git a/source/gloperate/include/gloperate/pipeline/Stage.h b/source/gloperate/include/gloperate/pipeline/Stage.h index 18692257..fd57d32e 100644 --- a/source/gloperate/include/gloperate/pipeline/Stage.h +++ b/source/gloperate/include/gloperate/pipeline/Stage.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -599,6 +600,58 @@ class GLOPERATE_API Stage : public cppexpose::Object */ std::string qualifiedName() const; + /** + * @brief + * Return the first input of type T where the callback returns 'true' + * + * @param[in] callback + * The callback + * + * @return + * The first input where the callback returns 'true' + */ + template + gloperate::Input * findInput(std::function *)> callback); + + /** + * @brief + * Iterate over all inputs and execute the callback. + */ + void forAllInputs(std::function callback); + + /** + * @brief + * Iterate over all inputs of type T and execute the callback. + */ + template + void forAllInputs(std::function *)> callback); + + /** + * @brief + * Return the first output of type T where the callback returns 'true' + * + * @param[in] callback + * The callback + * + * @return + * The first output where the callback returns 'true' + */ + template + gloperate::Output * findOutput(std::function *)> callback); + + /** + * @brief + * Iterate over all inputs and execute the callback. + */ + void forAllOutputs(std::function callback); + + /** + * @brief + * Iterate over all inputs of type T and execute the callback. + */ + template + void forAllOutputs(std::function *)> callback); + protected: /** diff --git a/source/gloperate/include/gloperate/pipeline/Stage.inl b/source/gloperate/include/gloperate/pipeline/Stage.inl index d0fa55c6..cc16d32c 100644 --- a/source/gloperate/include/gloperate/pipeline/Stage.inl +++ b/source/gloperate/include/gloperate/pipeline/Stage.inl @@ -107,5 +107,79 @@ Slot * Stage::createSlot(const std::string & slotType, const std::string & na return nullptr; } +template +gloperate::Input * Stage::findInput(std::function *)> callback) +{ + const auto it = std::find_if(m_inputs.begin(), m_inputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto input = dynamic_cast *>(slot); + + if (!input) + { + return false; + } + + return callback(input); + }); + + if (it == m_inputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + +template +void Stage::forAllInputs(std::function *)> callback) +{ + forAllInputs([& callback](gloperate::AbstractSlot * input) { + const auto inputT = dynamic_cast *>(input); + + if (!inputT) + { + return; + } + + callback(inputT); + }); +} + +template +gloperate::Output * Stage::findOutput(std::function *)> callback) +{ + const auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [callback](gloperate::AbstractSlot * slot) { + const auto output = dynamic_cast *>(slot); + + if (!output) + { + return false; + } + + return callback(output); + }); + + if (it == m_outputs.end()) + { + return nullptr; + } + + return static_cast *>(*it); +} + +template +void Stage::forAllOutputs(std::function *)> callback) +{ + forAllOutputs([& callback](gloperate::AbstractSlot * output) { + const auto outputT = dynamic_cast *>(output); + + if (!outputT) + { + return; + } + + callback(outputT); + }); +} + } // namespace gloperate diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index adba1d19..55c306a6 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -37,110 +37,6 @@ namespace { -template -gloperate::Input * getInput(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return nullptr; - } - - const auto & inputs = stage->inputs(); - - const auto it = std::find_if(inputs.begin(), inputs.end(), [callback](gloperate::AbstractSlot * slot) { - const auto input = dynamic_cast *>(slot); - - if (!input) - { - return false; - } - - return callback(input); - }); - - if (it == inputs.end()) - { - return nullptr; - } - - return static_cast *>(*it); -} - -template -void forAllInputs(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return; - } - - const auto & inputs = stage->inputs(); - - for (const auto input : inputs) - { - const auto inputT = dynamic_cast *>(input); - - if (!inputT) - { - continue; - } - - callback(inputT); - } -} - -template -gloperate::Output * getOutput(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return nullptr; - } - - const auto & outputs = stage->outputs(); - - const auto it = std::find_if(outputs.begin(), outputs.end(), [callback](gloperate::AbstractSlot * slot) { - const auto output = dynamic_cast *>(slot); - - if (!output) - { - return false; - } - - return callback(output); - }); - - if (it == outputs.end()) - { - return nullptr; - } - - return static_cast *>(*it); -} - -template -void forAllOutputs(gloperate::Stage * stage, std::function *)> callback) -{ - if (!stage) - { - return; - } - - const auto & outputs = stage->outputs(); - - for (const auto output : outputs) - { - const auto outputT = dynamic_cast *>(output); - - if (!outputT) - { - continue; - } - - callback(outputT); - } -} - auto s_nextCanvasId = size_t(0); @@ -305,7 +201,7 @@ void Canvas::updateTime() m_timeDelta += timeDelta; // Update timing - auto slotTimeDelta = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "timeDelta"; }); + auto slotTimeDelta = m_renderStage->findInput([](Input* input) { return input->name() == "timeDelta"; }); if (slotTimeDelta) { slotTimeDelta->setValue(m_timeDelta); @@ -327,7 +223,7 @@ void Canvas::setViewport(const glm::vec4 & deviceViewport) m_initialized = true; // Promote new viewport - auto slotViewport = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "viewport"; }); + auto slotViewport = m_renderStage->findInput([](Input* input) { return input->name() == "viewport"; }); if (slotViewport) slotViewport->setValue(m_viewport); // Check if a redraw is required @@ -369,11 +265,11 @@ void Canvas::render(globjects::Framebuffer * targetFBO) m_renderStage->initContext(m_openGLContext); // Promote viewport information - auto slotViewport = getInput(m_renderStage.get(), [](Input* input) { return input->name() == "viewport"; }); + auto slotViewport = m_renderStage->findInput([](Input* input) { return input->name() == "viewport"; }); if (slotViewport) slotViewport->setValue(m_viewport); // Mark output as required - forAllOutputs(m_renderStage.get(), [](Output * output) { + m_renderStage->forAllOutputs([](Output * output) { output->setRequired(true); }); @@ -437,7 +333,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) } // Update render stage input render targets - forAllInputs(m_renderStage.get(), [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { const auto renderTarget = **input; if (renderTarget == nullptr) @@ -447,7 +343,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) input->setValue(m_colorTarget.get()); }); - forAllInputs(m_renderStage.get(), [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { const auto renderTarget = **input; if (renderTarget == nullptr) @@ -457,7 +353,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) input->setValue(m_depthTarget.get()); }); - forAllInputs(m_renderStage.get(), [this](Input * input) { + m_renderStage->forAllInputs([this](Input * input) { const auto renderTarget = **input; if (renderTarget == nullptr) @@ -471,7 +367,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) // Render m_renderStage->process(); - auto colorOutput = getOutput(m_renderStage.get(), [this](Output * output) { + auto colorOutput = m_renderStage->findOutput([this](Output * output) { return **output != nullptr; }); @@ -483,7 +379,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) } else { - auto viewport = getOutput(m_renderStage.get(), [this](Output *) { + auto viewport = m_renderStage->findOutput([this](Output *) { return true; }); @@ -577,7 +473,7 @@ void Canvas::promoteMouseWheel(const glm::vec2 & delta, const glm::ivec2 & pos) void Canvas::checkRedraw() { bool redraw = false; - forAllOutputs(m_renderStage.get(), [& redraw](Output * output) { + m_renderStage->forAllOutputs([& redraw](Output * output) { if (**output && !output->isValid()) { redraw = true; diff --git a/source/gloperate/source/pipeline/Stage.cpp b/source/gloperate/source/pipeline/Stage.cpp index d20153d8..c7ca7025 100644 --- a/source/gloperate/source/pipeline/Stage.cpp +++ b/source/gloperate/source/pipeline/Stage.cpp @@ -514,5 +514,21 @@ void Stage::invalidateInputConnections() } } +void Stage::forAllInputs(std::function callback) +{ + for (const auto input : m_inputs) + { + callback(input); + } +} + +void Stage::forAllOutputs(std::function callback) +{ + for (const auto output : m_outputs) + { + callback(output); + } +} + } // namespace gloperate From deec9bba1b732a1e2ea8c002a4d9a784a5f556d2 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 27 Jun 2017 15:59:00 +0200 Subject: [PATCH 22/33] Add explicit extraction stage from RenderTarget to Texture --- .../demo-stages-plugins/ShapeDemo.cpp | 31 ++++---- .../examples/demo-stages-plugins/ShapeDemo.h | 32 ++++---- source/gloperate/CMakeLists.txt | 2 + .../TextureFromRenderTargetExtractionStage.h | 79 +++++++++++++++++++ ...TextureFromRenderTargetExtractionStage.cpp | 47 +++++++++++ 5 files changed, 160 insertions(+), 31 deletions(-) create mode 100644 source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h create mode 100644 source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 555dc968..0ec96a75 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -20,6 +20,7 @@ #include #include #include +#include CPPEXPOSE_COMPONENT(ShapeDemo, gloperate::Stage) @@ -49,6 +50,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , m_shapeRenderPass(cppassist::make_unique(environment, "ShapeRenderPass")) , m_shapeRasterization(cppassist::make_unique(environment, "ShapeRasterization")) , m_colorizeProgram(cppassist::make_unique(environment, "ColorizeProgram")) +, m_textureExtractionStage(cppassist::make_unique(environment, "TextureExtraction")) , m_colorizeRenderPass(cppassist::make_unique(environment, "ColorizeRenderPass")) , m_colorizeRasterization(cppassist::make_unique(environment, "ColorizeRasterization")) { @@ -135,35 +137,32 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_shapeRasterization->renderInterface.viewport << canvasInterface.viewport; m_shapeRasterization->drawable << m_shapeRenderPass->renderPass; - auto colorTextureInput = m_shapeRasterization->createInput("ColorTexture"); - auto colorTextureOutput = m_shapeRasterization->createOutput("ColorTextureOut"); - *colorTextureInput << m_framebuffer->colorTexture; - // Colorize program stage addStage(m_colorizeProgram.get()); *m_colorizeProgram->createInput("shader1") = dataPath + "/gloperate/shaders/geometry/screenaligned.vert"; *m_colorizeProgram->createInput("shader2") = dataPath + "/gloperate/shaders/demo/colorize.frag"; - // Colorize render pass stage - addStage(m_colorizeRenderPass.get()); - // m_colorizeRenderPass->drawable is set in onContextInit() - m_colorizeRenderPass->program << m_colorizeProgram->program; - m_colorizeRenderPass->culling = false; - m_colorizeRenderPass->depthTest = false; - m_colorizeRenderPass->createInput("color") << this->color; - m_colorizeRenderPass->createInput("source") << *colorTextureOutput; + auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); /* Hack Start */ - auto shapeColorOutput = m_shapeRasterization->createOutput("ColorAttachmentOut"); - shapeColorOutput->valueChanged.onFire([=]() { - colorTextureOutput->setValue(**colorTextureInput); - }); shapeColorOutput->valueInvalidated.onFire([=]() { m_clear->renderInterface.colorRenderTargetOutput(0)->invalidate(); m_clear->renderInterface.depthRenderTargetOutput(0)->invalidate(); }); /* Hack End */ + addStage(m_textureExtractionStage.get()); + m_textureExtractionStage->colorRenderTarget << *shapeColorOutput; + + // Colorize render pass stage + addStage(m_colorizeRenderPass.get()); + // m_colorizeRenderPass->drawable is set in onContextInit() + m_colorizeRenderPass->program << m_colorizeProgram->program; + m_colorizeRenderPass->culling = false; + m_colorizeRenderPass->depthTest = false; + m_colorizeRenderPass->createInput("color") << this->color; + m_colorizeRenderPass->createInput("source") << m_textureExtractionStage->texture; + // Colorize rasterization stage addStage(m_colorizeRasterization.get()); m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color"); diff --git a/source/examples/demo-stages-plugins/ShapeDemo.h b/source/examples/demo-stages-plugins/ShapeDemo.h index e6aac5f0..abe0c862 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.h +++ b/source/examples/demo-stages-plugins/ShapeDemo.h @@ -29,6 +29,7 @@ namespace gloperate class TimerStage; class TransformStage; class FloatSelectionStage; + class TextureFromRenderTargetExtractionStage; } @@ -89,27 +90,28 @@ class ShapeDemo : public gloperate::Pipeline protected: // Stages - std::unique_ptr m_timer; ///< Timer for continuous rendering and animation + std::unique_ptr m_timer; ///< Timer for continuous rendering and animation - std::unique_ptr m_floatSelection; ///< Selection between user-defined angle and timer-updated angle + std::unique_ptr m_floatSelection; ///< Selection between user-defined angle and timer-updated angle - std::unique_ptr m_trackball; ///< Trackball camera navigation stage + std::unique_ptr m_trackball; ///< Trackball camera navigation stage - std::unique_ptr m_shape; ///< Stage that generates a basic shape - std::unique_ptr m_texture; ///< Stage that loads a static picture - std::unique_ptr m_framebuffer; ///< Framebuffer for rendering the shape + std::unique_ptr m_shape; ///< Stage that generates a basic shape + std::unique_ptr m_texture; ///< Stage that loads a static picture + std::unique_ptr m_framebuffer; ///< Framebuffer for rendering the shape - std::unique_ptr m_clear; ///< Clears the output image + std::unique_ptr m_clear; ///< Clears the output image - std::unique_ptr m_shapeTransform; ///< Rotates the shape around its axis - std::unique_ptr m_shapeProgram; ///< Builds the Program for rendering the shape - std::unique_ptr m_shapeRenderPass; ///< Builds the RenderPass for rendering the shape - std::unique_ptr m_shapeRasterization; ///< Executes the RenderPass + std::unique_ptr m_shapeTransform; ///< Rotates the shape around its axis + std::unique_ptr m_shapeProgram; ///< Builds the Program for rendering the shape + std::unique_ptr m_shapeRenderPass; ///< Builds the RenderPass for rendering the shape + std::unique_ptr m_shapeRasterization; ///< Executes the RenderPass - std::unique_ptr m_colorizeProgram; ///< Builds the Program for blending - std::unique_ptr m_colorizeRenderPass; ///< Builds the RenderPass for blending - std::unique_ptr m_colorizeRasterization; ///< Executes the RenderPass + std::unique_ptr m_colorizeProgram; ///< Builds the Program for blending + std::unique_ptr m_textureExtractionStage; ///< Texture from rendertarget extraction + std::unique_ptr m_colorizeRenderPass; ///< Builds the RenderPass for blending + std::unique_ptr m_colorizeRasterization; ///< Executes the RenderPass // Internal data - std::unique_ptr m_quad; ///< Screen-aligned quad for colorization in demo + std::unique_ptr m_quad; ///< Screen-aligned quad for colorization in demo }; diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index 196f4520..bdc1d6f8 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -137,6 +137,7 @@ set(headers ${include_path}/stages/base/ShapeStage.h ${include_path}/stages/base/TransformStage.h ${include_path}/stages/base/TimerStage.h + ${include_path}/stages/base/TextureFromRenderTargetExtractionStage.h ${include_path}/stages/navigation/TrackballStage.h ${include_path}/stages/lights/LightCreationStage.h ${include_path}/stages/lights/LightBufferTextureStage.h @@ -234,6 +235,7 @@ set(sources ${source_path}/stages/base/ShapeStage.cpp ${source_path}/stages/base/TransformStage.cpp ${source_path}/stages/base/TimerStage.cpp + ${source_path}/stages/base/TextureFromRenderTargetExtractionStage.cpp ${source_path}/stages/navigation/TrackballStage.cpp ${source_path}/stages/lights/LightCreationStage.cpp ${source_path}/stages/lights/LightBufferTextureStage.cpp diff --git a/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h b/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h new file mode 100644 index 00000000..549367c8 --- /dev/null +++ b/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h @@ -0,0 +1,79 @@ + +#pragma once + + +#include + +#include + +#include +#include +#include +#include + + +namespace globjects +{ + class Texture; +} + + +namespace gloperate +{ + + +class ColorRenderTarget; + + +/** +* @brief +* Stage that extracts the texture from a RenderTarget, if one is attached. +*/ +class GLOPERATE_API TextureFromRenderTargetExtractionStage : public gloperate::Stage +{ +public: + CPPEXPOSE_DECLARE_COMPONENT( + TextureFromRenderTargetExtractionStage, gloperate::Stage + , "" // Tags + , "" // Icon + , "" // Annotations + , "Stage that extracts the texture from a RenderTarget, if one is attached" + , GLOPERATE_AUTHOR_ORGANIZATION + , "v1.0.0" + ) + + +public: + // Inputs + Input colorRenderTarget; ///< Color render target + + // Outputs + Output texture; ///< Internal texture of render target + + +public: + /** + * @brief + * Constructor + * + * @param[in] environment + * Environment to which the stage belongs (must NOT be null!) + * @param[in] name + * Stage name + */ + TextureFromRenderTargetExtractionStage(Environment * environment, const std::string & name = ""); + + /** + * @brief + * Destructor + */ + virtual ~TextureFromRenderTargetExtractionStage(); + + +protected: + // Virtual Stage interface + virtual void onProcess() override; +}; + + +} // namespace gloperate diff --git a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp new file mode 100644 index 00000000..ff348fc6 --- /dev/null +++ b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp @@ -0,0 +1,47 @@ + +#include + +#include + +#include + + +namespace gloperate +{ + + +CPPEXPOSE_COMPONENT(TextureFromRenderTargetExtractionStage, gloperate::Stage) + + +TextureFromRenderTargetExtractionStage::TextureFromRenderTargetExtractionStage(gloperate::Environment * environment, const std::string & name) +: Stage(environment, "TextureFromRenderTargetExtractionStage", name) +, colorRenderTarget("colorRenderTarget", this) +, texture("texture", this) +{ +} + +TextureFromRenderTargetExtractionStage::~TextureFromRenderTargetExtractionStage() +{ +} + +void TextureFromRenderTargetExtractionStage::onProcess() +{ + switch (colorRenderTarget->type()) + { + case RenderTargetType::Texture: + texture.setValue(colorRenderTarget->textureAttachment()); + break; + case RenderTargetType::UserDefinedFBOAttachment: + { + auto attachment = colorRenderTarget->framebufferAttachment()->asTextureAttachment(); + + texture.setValue(attachment ? attachment->texture() : nullptr); + } + break; + default: + texture.setValue(nullptr); + } +} + + +} // namespace gloperate From 3205224c207a7ef2f2d2cd7ddde3d969dbd933fd Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 28 Jun 2017 16:03:12 +0200 Subject: [PATCH 23/33] Add documentation for added/changed interfaces --- .../demo-stages-plugins/ShapeDemo.cpp | 6 +- .../examples/demo-stages-plugins/ShapeDemo.h | 24 +- .../IntermediateFramePreparationStage.h | 3 +- .../stages/MultiFrameAggregationPipeline.h | 20 +- .../stages/MultiFrameAggregationStage.h | 9 +- .../IntermediateFramePreparationStage.cpp | 2 +- .../stages/MultiFrameAggregationPipeline.cpp | 10 - .../include/gloperate-qt/base/RenderWindow.h | 6 +- .../gloperate/include/gloperate/base/Canvas.h | 10 +- .../rendering/AbstractRenderTarget.h | 57 ++-- .../include/gloperate/stages/base/BlitStage.h | 10 +- .../gloperate/stages/base/ClearStage.h | 20 +- .../stages/base/FloatSelectionStage.h | 8 +- .../stages/base/RasterizationStage.h | 6 +- .../stages/base/TextureRenderTargetStage.h | 8 +- .../stages/interfaces/CanvasInterface.h | 1 - .../stages/interfaces/RenderInterface.h | 281 ++++++++++++++++-- source/gloperate/source/base/Canvas.cpp | 6 +- .../source/rendering/AbstractRenderTarget.cpp | 62 ++-- .../stages/base/BasicFramebufferStage.cpp | 14 +- .../source/stages/base/ClearStage.cpp | 22 +- .../base/RenderbufferRenderTargetStage.cpp | 8 +- ...TextureFromRenderTargetExtractionStage.cpp | 2 +- .../stages/base/TextureRenderTargetStage.cpp | 8 +- .../stages/interfaces/RenderInterface.cpp | 31 +- 25 files changed, 441 insertions(+), 193 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 0ec96a75..00427a6d 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -55,7 +55,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) , m_colorizeRasterization(cppassist::make_unique(environment, "ColorizeRasterization")) { // Get data path - std::string dataPath = gloperate::dataPath(); + const auto dataPath = gloperate::dataPath(); // Setup parameters texture = dataPath + "/gloperate/textures/gloperate-logo.glraw"; @@ -193,9 +193,9 @@ void ShapeDemo::onContextInit(AbstractGLContext * context) void ShapeDemo::onContextDeinit(AbstractGLContext * context) { - Pipeline::onContextDeinit(context); - m_quad = nullptr; + + Pipeline::onContextDeinit(context); } void ShapeDemo::onRotateChanged(const bool & rotate) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.h b/source/examples/demo-stages-plugins/ShapeDemo.h index abe0c862..04812067 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.h +++ b/source/examples/demo-stages-plugins/ShapeDemo.h @@ -53,14 +53,14 @@ class ShapeDemo : public gloperate::Pipeline public: // Interfaces - gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs - Input shape; ///< Shape type - Input texture; ///< Texture filename - Input angle; ///< Current rotation angle - Input rotate; ///< Rotation automatically? - Input color; ///< Mixer color + Input shape; ///< Shape type + Input texture; ///< Texture filename + Input angle; ///< Current rotation angle + Input rotate; ///< Rotation automatically? + Input color; ///< Mixer color public: @@ -83,7 +83,19 @@ class ShapeDemo : public gloperate::Pipeline protected: + /** + * @brief + * React on rotation type change + * + * @param[in] rotate + * Rotation flag + * + * @remarks + * A 'rotate' value of 'true' enables automatic rotation, 'false' disables it + */ void onRotateChanged(const bool & rotate); + + // Virtual Stage interface virtual void onContextInit(gloperate::AbstractGLContext * context) override; virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h index 5cc8dfe3..335e1ec6 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h @@ -29,7 +29,7 @@ class GLOPERATE_GLKERNEL_API IntermediateFramePreparationStage : public gloperat , "" , "" , "" - , "Stage that ensures the intermediate frame is in the outer color attachment" + , "Stage that ensures the intermediate frame is in the output color attachment" , GLOPERATE_AUTHOR_ORGANIZATION , "v0.1.0" ) @@ -72,6 +72,7 @@ class GLOPERATE_GLKERNEL_API IntermediateFramePreparationStage : public gloperat virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; virtual void onProcess() override; + protected: // Data std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h index d7e0f028..61dcbdf4 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationPipeline.h @@ -18,7 +18,7 @@ namespace gloperate class RenderbufferRenderTargetStage; class FramebufferStage; class BlitStage; -} +} // namespace gloperate namespace gloperate_glkernel @@ -53,9 +53,7 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs - Input multiFrameCount; ///< Maximum number of frames to aggregate - - // Additional Inputs + Input multiFrameCount; ///< Maximum number of frames to aggregate public: @@ -78,12 +76,6 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P protected: - // Virtual Stage interface - //virtual void onProcess() override; - - // Helper functions - void disconnectRenderStage(); - /** * @brief * Set the intermediate frame generating stage/pipeline @@ -93,6 +85,12 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P */ void setRenderStage(gloperate::Stage * stage); + /** + * @brief + * Disconnects the current render stage. + */ + void disconnectRenderStage(); + protected: // Aggregation stages @@ -103,7 +101,7 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationPipeline : public gloperate::P std::unique_ptr m_aggregationStage; ///< Aggregation stage // Inserted Stage/Pipeline - Stage * m_renderStage; ///< Actual rendering stage, providing intermediate frames + Stage * m_renderStage; ///< Actual rendering stage, providing intermediate frames }; diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h index 25b3a6eb..5c2bd1b4 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h @@ -4,8 +4,6 @@ #include -#include - #include #include @@ -72,11 +70,12 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; virtual void onProcess() override; + protected: // Data - std::unique_ptr m_triangle; ///< Screen-aligned Triangle for 'blitting' - std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets - std::unique_ptr m_fbo; ///< Framebuffer for render targets + std::unique_ptr m_triangle; ///< Screen-aligned Triangle for 'blitting' + std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets + std::unique_ptr m_fbo; ///< Framebuffer for render targets }; diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index 1fec1f2c..4738f28b 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -56,7 +56,7 @@ void IntermediateFramePreparationStage::onProcess() return; } - if (intermediateRenderTarget->type() != gloperate::RenderTargetType::Texture + if (intermediateRenderTarget->currentTargetType() != gloperate::RenderTargetType::Texture || intermediateRenderTarget->textureAttachment() != *intermediateFrameTexture) { std::array rect = {{ diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp index 86232882..2edf518f 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationPipeline.cpp @@ -81,16 +81,6 @@ MultiFrameAggregationPipeline::~MultiFrameAggregationPipeline() { } -/*void MultiFrameAggregationPipeline::onProcess() -{ - if (!m_renderStage) - { - return; - } - - Pipeline::onProcess(); -}*/ - void MultiFrameAggregationPipeline::setRenderStage(gloperate::Stage * stage) { disconnectRenderStage(); diff --git a/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h b/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h index d328a2df..44c38997 100644 --- a/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h +++ b/source/gloperate-qt/include/gloperate-qt/base/RenderWindow.h @@ -26,7 +26,7 @@ namespace gloperate_qt /** * @brief -* Window that renders a gloperate scene +* Window that displays a gloperate canvas */ class GLOPERATE_QT_API RenderWindow : public OpenGLWindow { @@ -83,8 +83,8 @@ class GLOPERATE_QT_API RenderWindow : public OpenGLWindow protected: - gloperate::Environment * m_environment; ///< Gloperate environment to which the window belongs (must NOT be null) - std::unique_ptr m_canvas; ///< Canvas that renders onto the window (never null) + gloperate::Environment * m_environment; ///< Gloperate environment to which the window belongs (must NOT be null) + std::unique_ptr m_canvas; ///< Canvas that renders onto the window (never null) std::unique_ptr m_framebuffer; ///< Target framebuffer for rendering }; diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index c8553569..0b79c24b 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -263,6 +263,7 @@ class GLOPERATE_API Canvas : public cppexpose::Object protected: + //@{ /** * @brief * Check if a redraw is required @@ -287,7 +288,9 @@ class GLOPERATE_API Canvas : public cppexpose::Object * Input slot */ void stageInputChanged(AbstractSlot * slot); + //@} + //@{ // Scripting functions void scr_onStageInputChanged(const cppexpose::Variant & func); cppexpose::Variant scr_getSlotTypes(const std::string & path); @@ -301,10 +304,13 @@ class GLOPERATE_API Canvas : public cppexpose::Object cppexpose::Variant scr_getSlot(const std::string & path, const std::string & slot); cppexpose::Variant scr_getValue(const std::string & path, const std::string & slot); void scr_setValue(const std::string & path, const std::string & slot, const cppexpose::Variant & value); + //@} + //@{ // Helper functions Stage * getStageObject(const std::string & path) const; cppexpose::Variant getSlotStatus(const std::string & path, const std::string & slot); + //@} protected: @@ -327,8 +333,8 @@ class GLOPERATE_API Canvas : public cppexpose::Object std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs std::unique_ptr m_colorTarget; ///< Input render target for color attachment - std::unique_ptr m_depthTarget; ///< Input render target for depth only attachment - std::unique_ptr m_stencilTarget; ///< Input render target for depth stencil attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth attachment + std::unique_ptr m_stencilTarget; ///< Input render target for stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h index ff91436e..fedceb92 100644 --- a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h @@ -63,25 +63,25 @@ class GLOPERATE_API AbstractRenderTarget * @return * The attachment type */ - AttachmentType attachmentType() const; + AttachmentType underlyingAttachmentType() const; /** * @brief - * Get attachment type as GLenum + * Set attachment type * - * @return - * The attachment type as GLenum + * @param[in] type + * The attachment type */ - gl::GLenum attachmentGLType() const; + void setUnderlyingAttachmentType(AttachmentType underlyingAttachmentType); /** * @brief - * Set attachment type + * Get attachment type as GLenum * - * @param[in] type - * The attachment type + * @return + * The attachment type as GLenum */ - void setAttachmentType(AttachmentType attachmentType); + gl::GLenum attachmentGLType() const; /** * @brief @@ -126,7 +126,7 @@ class GLOPERATE_API AbstractRenderTarget * @return * The current target type */ - RenderTargetType type() const; + RenderTargetType currentTargetType() const; /** * @brief @@ -189,17 +189,38 @@ class GLOPERATE_API AbstractRenderTarget */ bool attachmentRequiresUserDefinedFramebuffer() const; - gl::GLenum attachmentBuffer() const; + /** + * @brief + * Get the symbolic constant of the attachment type used for glClearBuffer + * + * @return + * The symbolic constant for glClearBuffer parameter 1 + */ + gl::GLenum clearBufferAttachment() const; + + /** + * @brief + * Get the draw buffer attachment index + * + * @param[in] index + * The current color attachment index. + * + * @return + * The draw buffer attachment index used for glClearBuffer parameter 1 + * + * @remarks + * If this is no color attachment, '0' is returned + */ + gl::GLint clearBufferDrawBuffer(size_t index) const; - gl::GLint attachmentDrawBuffer(size_t index) const; protected: - RenderTargetType m_type; ///< Target type - AttachmentType m_attachmentType; ///< OpenGL attachment type - gl::GLenum m_attachment; ///< Default framebuffer attachment target - globjects::Texture * m_texture; ///< Texture target - globjects::Renderbuffer * m_renderbuffer; ///< Renderbuffer target - globjects::FramebufferAttachment * m_userDefined; ///< User defined framebuffer attachment target + RenderTargetType m_currentTargetType; ///< Target type + AttachmentType m_internalAttachmentType; ///< Internal OpenGL attachment type + gl::GLenum m_defaultFBOAttachment; ///< Default framebuffer attachment target + globjects::Texture * m_texture; ///< Texture target + globjects::Renderbuffer * m_renderbuffer; ///< Renderbuffer target + globjects::FramebufferAttachment * m_userDefinedFBOAttachment; ///< User-defined framebuffer attachment target }; diff --git a/source/gloperate/include/gloperate/stages/base/BlitStage.h b/source/gloperate/include/gloperate/stages/base/BlitStage.h index 7f4ff0f0..1c1d1d16 100644 --- a/source/gloperate/include/gloperate/stages/base/BlitStage.h +++ b/source/gloperate/include/gloperate/stages/base/BlitStage.h @@ -42,15 +42,15 @@ class GLOPERATE_API BlitStage : public Stage public: // Inputs - Input source; ///< FBO containing the source attachments - Input sourceViewport; ///< Viewport for reading from source FBO - Input target; ///< FBO with destination attachments - Input targetViewport; ///< Viewport for writing into destination FBO + Input source; ///< Source render target + Input sourceViewport; ///< Source Viewport for reading from source + Input target; ///< Target render target + Input targetViewport; ///< Target viewport for writing into target Input minFilter; ///< Interpolation mode used when target size is lower than source size (default: linear interpolation) Input magFilter; ///< Interpolation mode used when target size is greater than source size (default: nearest filtering) // Outputs - Output targetOut; ///< Pass-through render target + Output targetOut; ///< Pass-through target render target public: diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index 8ca312c4..e2fd33ad 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -44,11 +44,11 @@ class GLOPERATE_API ClearStage : public Stage public: - // Inputs - - Input clear; ///< Flag if buffers should get cleared + // Interfaces + RenderInterface renderInterface; ///< Renderinterface to manage render targets inputs and outputs - RenderInterface renderInterface; ///< Renderinterface to manage render targets inputs and outputs + // Inputs + Input clear; ///< Flag if buffers should get cleared public: @@ -78,12 +78,12 @@ class GLOPERATE_API ClearStage : public Stage protected: - std::vector *> m_colorValueInputs; - std::vector *> m_depthValueInputs; - std::vector *> m_stencilValueInputs; - std::vector> *> m_depthStencilValueInputs; - std::unique_ptr m_defaultFBO; ///< Default FBO for clearing - std::unique_ptr m_fbo; ///< Intermediate FBO for clearing + std::vector *> m_colorValueInputs; ///< Color clear values + std::vector *> m_depthValueInputs; ///< Depth clear values + std::vector *> m_stencilValueInputs; ///< Stencil clear values + std::vector> *> m_depthStencilValueInputs; ///< Depth-stencil clear values + std::unique_ptr m_defaultFBO; ///< Default FBO for clearing + std::unique_ptr m_fbo; ///< Intermediate FBO for clearing }; diff --git a/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h b/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h index 349ccef7..5d602105 100644 --- a/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h +++ b/source/gloperate/include/gloperate/stages/base/FloatSelectionStage.h @@ -17,7 +17,7 @@ namespace gloperate /** * @brief -* Stage that selects a float from a given index +* Stage that selects a float value from a given index */ class GLOPERATE_API FloatSelectionStage : public gloperate::Stage { @@ -34,9 +34,11 @@ class GLOPERATE_API FloatSelectionStage : public gloperate::Stage public: + // Inputs Input index; ///< Index of float to select - Output value; ///< Resulting float + // Outputs + Output value; ///< Resulting float value public: @@ -64,7 +66,7 @@ class GLOPERATE_API FloatSelectionStage : public gloperate::Stage protected: - std::vector *> m_floatInputs; + std::vector *> m_floatInputs; ///< The list of all connected float inputs }; diff --git a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h index bb98d98a..93bf3aa3 100644 --- a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h +++ b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h @@ -27,7 +27,7 @@ class AbstractDrawable; /** * @brief -* Stage that rasterizes a given drawable +* Stage that rasterizes a given drawable into render targets */ class GLOPERATE_API RasterizationStage : public Stage { @@ -78,8 +78,8 @@ class GLOPERATE_API RasterizationStage : public Stage protected: - std::unique_ptr m_defaultFBO; ///< Default FBO for clearing - std::unique_ptr m_fbo; ///< Intermediate FBO for clearing + std::unique_ptr m_defaultFBO; ///< Default FBO for rasterization + std::unique_ptr m_fbo; ///< Intermediate FBO for rasterization }; diff --git a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h index 06b22b14..b9abb18b 100644 --- a/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/TextureRenderTargetStage.h @@ -49,10 +49,10 @@ class GLOPERATE_API TextureRenderTargetStage : public gloperate::Stage public: // Inputs - Input internalFormat; ///< OpenGL internal image format - Input format; ///< OpenGL image format - Input type; ///< OpenGL data type - Input size; ///< Viewport size (only z and w component is used as width and height) + Input internalFormat; ///< OpenGL internal image format + Input format; ///< OpenGL image format + Input type; ///< OpenGL data type + Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs Output texture; ///< Texture diff --git a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h index 7f662647..c89dacca 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/CanvasInterface.h @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index b3efd8a7..fd34ff50 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -11,12 +11,8 @@ namespace globjects { - - -class Framebuffer; - - -} // namespace globjects + class Framebuffer; +} namespace gloperate @@ -72,63 +68,306 @@ class GLOPERATE_API RenderInterface */ ~RenderInterface(); + /** + * @brief + * Set value of all output render targets to their input render target counterparts + */ void updateRenderTargetOutputs(); + /** + * @brief + * Test if all registered render targets can be attached to a single FBO + * + * @return + * 'true', if all registered render targets are compatible using one single FBO, else 'false' + */ bool allRenderTargetsCompatible() const; + /** + * @brief + * Configures all render targets as attachments for a framebuffer + * + * Further, the draw buffers are updated on the framebuffer. + * + * @param[in] fbo + * The user-defined framebuffer used for user-defined attachments + * @param[in] defaultFBO + * The default framebuffer used for default framebuffer attachments + * + * @return + * The matching framebuffer; either fbo or defaultFBO, depending on the type of render target attachments + * + * @remarks + * allRenderTargetsCompatible() is expected to return 'true'. + */ + globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; + + /** + * @brief + * Configures one render target as attachment for a framebuffer + * + * @param[in] index + * The next color attachment index + * @param[in] renderTarget + * The render target to attach + * @param[in] fbo + * The user-defined framebuffer used for user-defined attachments + * @param[in] defaultFBO + * The default framebuffer used for default framebuffer attachments + * + * @return + * The matching framebuffer; either fbo or defaultFBO, depending on the type of the render target attachment + */ + static globjects::Framebuffer * configureFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + + /** + * @brief + * Get the vector of all registered color render target inputs + * + * @return + * The vector of color render target inputs + */ const std::vector *> & colorRenderTargetInputs() const; + + /** + * @brief + * Get the vector of all registered depth render target inputs + * + * @return + * The vector of depth render target inputs + */ const std::vector *> & depthRenderTargetInputs() const; + + /** + * @brief + * Get the vector of all registered stencil render target inputs + * + * @return + * The vector of stencil render target inputs + */ const std::vector *> & stencilRenderTargetInputs() const; + /** + * @brief + * Get the color render target input at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The color render target input at given index, 'null' if index is invalid + */ Input * colorRenderTargetInput(size_t index) const; + + /** + * @brief + * Get the depth render target input at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The depth render target input at given index, 'null' if index is invalid + */ Input * depthRenderTargetInput(size_t index) const; + + /** + * @brief + * Get the stencil render target input at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The stencil render target input at given index, 'null' if index is invalid + */ Input * stencilRenderTargetInput(size_t index) const; + /** + * @brief + * Get the color render target at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The color render target at given index, 'null' if index is invalid + */ ColorRenderTarget * inputColorRenderTarget(size_t index) const; + + /** + * @brief + * Get the depth render target at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The depth render target at given index, 'null' if index is invalid + */ DepthRenderTarget * inputDepthRenderTarget(size_t index) const; + + /** + * @brief + * Get the stencil render target at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The stencil render target at given index, 'null' if index is invalid + */ StencilRenderTarget * inputStencilRenderTarget(size_t index) const; + /** + * @brief + * Get the vector of all registered color render target outputs + * + * @return + * The vector of color render target outputs + */ const std::vector *> & colorRenderTargetOutputs() const; + + /** + * @brief + * Get the vector of all registered depth render target outputs + * + * @return + * The vector of depth render target outputs + */ const std::vector *> & depthRenderTargetOutputs() const; + + /** + * @brief + * Get the vector of all registered stencil render target outputs + * + * @return + * The vector of stencil render target outputs + */ const std::vector *> & stencilRenderTargetOutputs() const; + /** + * @brief + * Get the color render target output at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The color render target output at given index, 'null' if index is invalid + */ Output * colorRenderTargetOutput(size_t index) const; + + /** + * @brief + * Get the depth render target output at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The depth render target output at given index, 'null' if index is invalid + */ Output * depthRenderTargetOutput(size_t index) const; - Output * stencilRenderTargetOutput(size_t index) const; - ColorRenderTarget * outputColorRenderTarget(size_t index) const; - DepthRenderTarget * outputDepthRenderTarget(size_t index) const; - StencilRenderTarget * outputStencilRenderTarget(size_t index) const; + /** + * @brief + * Get the stencil render target output at given index + * + * @param[in] index + * The index of the render target + * + * @return + * The stencil render target output at given index, 'null' if index is invalid + */ + Output * stencilRenderTargetOutput(size_t index) const; /** * @brief - * Registers new render target input + * Registers new color render target input * * @param[in] input - * New render target input + * New color render target input */ void addRenderTargetInput(Input * input); + + /** + * @brief + * Registers new depth render target input + * + * @param[in] input + * New depth render target input + */ void addRenderTargetInput(Input * input); + + /** + * @brief + * Registers new stencil render target input + * + * @param[in] input + * New stencil render target input + */ void addRenderTargetInput(Input * input); /** * @brief - * Registers new render target input + * Registers new color render target output + * + * @param[in] input + * New render color target output + */ + void addRenderTargetOutput(Output * output); + + /** + * @brief + * Registers new depth render target output + * + * @param[in] input + * New render depth target output + */ + void addRenderTargetOutput(Output * output); + + /** + * @brief + * Registers new stencil render target output * * @param[in] input - * New render target input + * New render stencil target output */ - void addRenderTargetOutput(Output * input); - void addRenderTargetOutput(Output * input); - void addRenderTargetOutput(Output * input); + void addRenderTargetOutput(Output * output); + /** + * @brief + * Iterate over all pairs of color render target inputs and outputs and call the callback + * + * @param[in] callback + * The callback + * @param[in] includeIncompletePairs + * If 'true', also incomplete pairs are passed to the callback (i.e., either input or output is 'null') + */ void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); - void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); - void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); - globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; + /** + * @brief + * Iterate over all pairs of depth render target inputs and outputs and call the callback + * + * @param[in] callback + * The callback + * @param[in] includeIncompletePairs + * If 'true', also incomplete pairs are passed to the callback (i.e., either input or output is 'null') + */ + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); - static globjects::Framebuffer * configureFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + /** + * @brief + * Iterate over all pairs of stencil render target inputs and outputs and call the callback + * + * @param[in] callback + * The callback + * @param[in] includeIncompletePairs + * If 'true', also incomplete pairs are passed to the callback (i.e., either input or output is 'null') + */ + void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); protected: std::vector *> m_colorRenderTargetInputs; ///< List of input color render targets diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 55c306a6..79c19e32 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -78,9 +78,9 @@ Canvas::Canvas(Environment * environment) // Register canvas m_environment->registerCanvas(this); - m_colorTarget->setAttachmentType(AttachmentType::Color); - m_depthTarget->setAttachmentType(AttachmentType::Depth); - m_stencilTarget->setAttachmentType(AttachmentType::Stencil); + m_colorTarget->setUnderlyingAttachmentType(AttachmentType::Color); + m_depthTarget->setUnderlyingAttachmentType(AttachmentType::Depth); + m_stencilTarget->setUnderlyingAttachmentType(AttachmentType::Stencil); } Canvas::~Canvas() diff --git a/source/gloperate/source/rendering/AbstractRenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp index a48a2216..2928955c 100644 --- a/source/gloperate/source/rendering/AbstractRenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -15,11 +15,11 @@ namespace gloperate AbstractRenderTarget::AbstractRenderTarget() -: m_type(RenderTargetType::Invalid) -, m_attachment(gl::GL_NONE) +: m_currentTargetType(RenderTargetType::Invalid) +, m_defaultFBOAttachment(gl::GL_NONE) , m_texture(nullptr) , m_renderbuffer(nullptr) -, m_userDefined(nullptr) +, m_userDefinedFBOAttachment(nullptr) { } @@ -29,7 +29,7 @@ AbstractRenderTarget::~AbstractRenderTarget() void AbstractRenderTarget::releaseTarget() { - switch (m_type) + switch (m_currentTargetType) { case RenderTargetType::Texture: m_texture = nullptr; @@ -38,32 +38,34 @@ void AbstractRenderTarget::releaseTarget() m_renderbuffer = nullptr; break; case RenderTargetType::DefaultFBOAttachment: - m_attachment = gl::GL_NONE; + m_defaultFBOAttachment = gl::GL_NONE; break; case RenderTargetType::UserDefinedFBOAttachment: - m_userDefined = nullptr; + m_userDefinedFBOAttachment = nullptr; break; case RenderTargetType::Invalid: default: - m_attachment = gl::GL_NONE; + m_defaultFBOAttachment = gl::GL_NONE; break; } - m_type = RenderTargetType::Invalid; + m_currentTargetType = RenderTargetType::Invalid; } -AttachmentType AbstractRenderTarget::attachmentType() const +AttachmentType AbstractRenderTarget::underlyingAttachmentType() const { - return m_attachmentType; + return m_internalAttachmentType; } gl::GLenum AbstractRenderTarget::attachmentGLType() const { - switch (m_attachmentType) + switch (m_internalAttachmentType) { case AttachmentType::Depth: return gl::GL_DEPTH; case AttachmentType::Stencil: + return gl::GL_STENCIL; + case AttachmentType::DepthStencil: return gl::GL_DEPTH_STENCIL; case AttachmentType::Color: default: @@ -71,16 +73,16 @@ gl::GLenum AbstractRenderTarget::attachmentGLType() const } } -void AbstractRenderTarget::setAttachmentType(AttachmentType attachmentType) +void AbstractRenderTarget::setUnderlyingAttachmentType(AttachmentType attachmentType) { - m_attachmentType = attachmentType; + m_internalAttachmentType = attachmentType; } void AbstractRenderTarget::setTarget(globjects::Texture * texture) { releaseTarget(); - m_type = RenderTargetType::Texture; + m_currentTargetType = RenderTargetType::Texture; m_texture = texture; } @@ -89,7 +91,7 @@ void AbstractRenderTarget::setTarget(globjects::Renderbuffer * renderbuffer) { releaseTarget(); - m_type = RenderTargetType::Renderbuffer; + m_currentTargetType = RenderTargetType::Renderbuffer; m_renderbuffer = renderbuffer; } @@ -98,28 +100,28 @@ void AbstractRenderTarget::setTarget(gl::GLenum attachment) { releaseTarget(); - m_type = RenderTargetType::DefaultFBOAttachment; + m_currentTargetType = RenderTargetType::DefaultFBOAttachment; - m_attachment = attachment; + m_defaultFBOAttachment = attachment; } void AbstractRenderTarget::setTarget(globjects::FramebufferAttachment * fboAttachment) { releaseTarget(); - m_type = RenderTargetType::UserDefinedFBOAttachment; + m_currentTargetType = RenderTargetType::UserDefinedFBOAttachment; - m_userDefined = fboAttachment; + m_userDefinedFBOAttachment = fboAttachment; } -RenderTargetType AbstractRenderTarget::type() const +RenderTargetType AbstractRenderTarget::currentTargetType() const { - return m_type; + return m_currentTargetType; } gl::GLenum AbstractRenderTarget::defaultFramebufferAttachment() const { - return m_attachment; + return m_defaultFBOAttachment; } globjects::Texture * AbstractRenderTarget::textureAttachment() const @@ -134,27 +136,27 @@ globjects::Renderbuffer * AbstractRenderTarget::renderbufferAttachment() const globjects::FramebufferAttachment * AbstractRenderTarget::framebufferAttachment() const { - return m_userDefined; + return m_userDefinedFBOAttachment; } bool AbstractRenderTarget::attachmentRequiresUserDefinedFramebuffer() const { - return m_type == RenderTargetType::Texture - || m_type == RenderTargetType::Renderbuffer - || m_type == RenderTargetType::UserDefinedFBOAttachment; + return m_currentTargetType == RenderTargetType::Texture + || m_currentTargetType == RenderTargetType::Renderbuffer + || m_currentTargetType == RenderTargetType::UserDefinedFBOAttachment; } -gl::GLenum AbstractRenderTarget::attachmentBuffer() const +gl::GLenum AbstractRenderTarget::clearBufferAttachment() const { return attachmentRequiresUserDefinedFramebuffer() ? attachmentGLType() - : m_attachment; + : m_defaultFBOAttachment; } -gl::GLint AbstractRenderTarget::attachmentDrawBuffer(size_t index) const +gl::GLint AbstractRenderTarget::clearBufferDrawBuffer(size_t index) const { return attachmentRequiresUserDefinedFramebuffer() - ? (m_attachmentType == AttachmentType::Color ? index : 0) + ? (m_internalAttachmentType == AttachmentType::Color ? index : 0) : 0; } diff --git a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp index 60cf1d6c..39bb1343 100644 --- a/source/gloperate/source/stages/base/BasicFramebufferStage.cpp +++ b/source/gloperate/source/stages/base/BasicFramebufferStage.cpp @@ -20,11 +20,11 @@ CPPEXPOSE_COMPONENT(BasicFramebufferStage, gloperate::Stage) BasicFramebufferStage::BasicFramebufferStage(Environment * environment, const std::string & name) : Stage(environment, "BasicFramebufferStage", name) -, viewport ("viewport", this) -, colorTexture ("colorTexture", this) -, depthTexture ("depthTexture", this) -, colorBuffer ("colorBuffer", this) -, depthBuffer ("depthBuffer", this) +, viewport ("viewport", this) +, colorTexture("colorTexture", this) +, depthTexture("depthTexture", this) +, colorBuffer ("colorBuffer", this) +, depthBuffer ("depthBuffer", this) { } @@ -35,10 +35,10 @@ BasicFramebufferStage::~BasicFramebufferStage() void BasicFramebufferStage::onContextInit(AbstractGLContext *) { m_colorBuffer = cppassist::make_unique(); - m_colorBuffer->setAttachmentType(AttachmentType::Color); + m_colorBuffer->setUnderlyingAttachmentType(AttachmentType::Color); m_depthBuffer = cppassist::make_unique(); - m_depthBuffer->setAttachmentType(AttachmentType::Depth); + m_depthBuffer->setUnderlyingAttachmentType(AttachmentType::Depth); // Create color texture m_colorTexture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D); diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index d9b869d3..12e79eef 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -22,8 +22,8 @@ CPPEXPOSE_COMPONENT(ClearStage, gloperate::Stage) ClearStage::ClearStage(Environment * environment, const std::string & name) : Stage(environment, "ClearStage", name) -, clear("clear", this, true) , renderInterface(this) +, clear("clear", this, true) { inputAdded.connect( [this] (AbstractSlot * connectedInput) { auto colorValueInput = dynamic_cast *>(connectedInput); @@ -103,8 +103,8 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - const auto attachmentBuffer = (**input)->attachmentBuffer(); - const auto attachmentDrawBuffer = (**input)->attachmentDrawBuffer(colorAttachmentIndex); + const auto attachmentBuffer = (**input)->clearBufferAttachment(); + const auto attachmentDrawBuffer = (**input)->clearBufferDrawBuffer(colorAttachmentIndex); const auto clearColor = **m_colorValueInputs.at(colorAttachmentIndex); fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColor); @@ -118,7 +118,7 @@ void ClearStage::onProcess() return; } - if ((**input)->attachmentType() == AttachmentType::Depth) + if ((**input)->underlyingAttachmentType() == AttachmentType::Depth) { if (m_depthValueInputs.size() <= depthAttachmentIndex) { @@ -127,11 +127,11 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH, (**input)->attachmentDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex)); + fbo->clearBuffer(gl::GL_DEPTH, (**input)->clearBufferDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex)); ++depthAttachmentIndex; } - else if ((**input)->attachmentType() == AttachmentType::DepthStencil) + else if ((**input)->underlyingAttachmentType() == AttachmentType::DepthStencil) { if (m_depthStencilValueInputs.size() <= depthStencilAttachmentIndex) { @@ -140,7 +140,7 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthStencilAttachmentIndex)); + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->clearBufferDrawBuffer(depthStencilAttachmentIndex)); ++depthStencilAttachmentIndex; clearedDepthStencilTargets.insert(**input); @@ -153,7 +153,7 @@ void ClearStage::onProcess() return; } - if ((**input)->attachmentType() == AttachmentType::Stencil) + if ((**input)->underlyingAttachmentType() == AttachmentType::Stencil) { if (m_stencilValueInputs.size() <= stencilAttachmentIndex) { @@ -162,11 +162,11 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(stencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_STENCIL, (**input)->attachmentDrawBuffer(stencilAttachmentIndex), **m_stencilValueInputs.at(stencilAttachmentIndex)); + fbo->clearBuffer(gl::GL_STENCIL, (**input)->clearBufferDrawBuffer(stencilAttachmentIndex), **m_stencilValueInputs.at(stencilAttachmentIndex)); ++stencilAttachmentIndex; } - else if ((**input)->attachmentType() == AttachmentType::DepthStencil) + else if ((**input)->underlyingAttachmentType() == AttachmentType::DepthStencil) { if (std::find(clearedDepthStencilTargets.begin(), clearedDepthStencilTargets.end(), **input) != clearedDepthStencilTargets.end()) { @@ -180,7 +180,7 @@ void ClearStage::onProcess() auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); - fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->attachmentDrawBuffer(depthStencilAttachmentIndex)); + fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->clearBufferDrawBuffer(depthStencilAttachmentIndex)); ++depthStencilAttachmentIndex; } diff --git a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp index b442a228..9806c55e 100644 --- a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp +++ b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp @@ -49,8 +49,8 @@ void RenderbufferRenderTargetStage::onContextInit(gloperate::AbstractGLContext * m_depthRenderTarget = cppassist::make_unique(); m_stencilRenderTarget = cppassist::make_unique(); - m_colorRenderTarget->setAttachmentType(AttachmentType::Color); - m_stencilRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + m_colorRenderTarget->setUnderlyingAttachmentType(AttachmentType::Color); + m_stencilRenderTarget->setUnderlyingAttachmentType(AttachmentType::DepthStencil); } void RenderbufferRenderTargetStage::onContextDeinit(AbstractGLContext *) @@ -86,7 +86,7 @@ void RenderbufferRenderTargetStage::onProcess() m_depthRenderTarget->setTarget(m_renderbuffer.get()); - m_depthRenderTarget->setAttachmentType(AttachmentType::Depth); + m_depthRenderTarget->setUnderlyingAttachmentType(AttachmentType::Depth); break; case GL_DEPTH_STENCIL: case GL_DEPTH24_STENCIL8: @@ -96,7 +96,7 @@ void RenderbufferRenderTargetStage::onProcess() m_depthRenderTarget->setTarget(m_renderbuffer.get()); m_stencilRenderTarget->setTarget(m_renderbuffer.get()); - m_depthRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + m_depthRenderTarget->setUnderlyingAttachmentType(AttachmentType::DepthStencil); break; default: // Color attachment m_depthRenderTarget->releaseTarget(); diff --git a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp index ff348fc6..8653ee4b 100644 --- a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp +++ b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp @@ -26,7 +26,7 @@ TextureFromRenderTargetExtractionStage::~TextureFromRenderTargetExtractionStage( void TextureFromRenderTargetExtractionStage::onProcess() { - switch (colorRenderTarget->type()) + switch (colorRenderTarget->currentTargetType()) { case RenderTargetType::Texture: texture.setValue(colorRenderTarget->textureAttachment()); diff --git a/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp index 45e5299e..6f76ece5 100644 --- a/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp +++ b/source/gloperate/source/stages/base/TextureRenderTargetStage.cpp @@ -51,8 +51,8 @@ void TextureRenderTargetStage::onContextInit(gloperate::AbstractGLContext *) m_depthRenderTarget = cppassist::make_unique(); m_stencilRenderTarget = cppassist::make_unique(); - m_colorRenderTarget->setAttachmentType(AttachmentType::Color); - m_stencilRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + m_colorRenderTarget->setUnderlyingAttachmentType(AttachmentType::Color); + m_stencilRenderTarget->setUnderlyingAttachmentType(AttachmentType::DepthStencil); } void TextureRenderTargetStage::onContextDeinit(AbstractGLContext *) @@ -88,7 +88,7 @@ void TextureRenderTargetStage::onProcess() m_depthRenderTarget->setTarget(m_texture.get()); - m_depthRenderTarget->setAttachmentType(AttachmentType::Depth); + m_depthRenderTarget->setUnderlyingAttachmentType(AttachmentType::Depth); break; case GL_DEPTH_STENCIL: case GL_DEPTH24_STENCIL8: @@ -98,7 +98,7 @@ void TextureRenderTargetStage::onProcess() m_depthRenderTarget->setTarget(m_texture.get()); m_stencilRenderTarget->setTarget(m_texture.get()); - m_depthRenderTarget->setAttachmentType(AttachmentType::DepthStencil); + m_depthRenderTarget->setUnderlyingAttachmentType(AttachmentType::DepthStencil); break; default: // Color attachment m_depthRenderTarget->releaseTarget(); diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 18c519a3..1c29ed35 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -195,27 +195,6 @@ Output * RenderInterface::stencilRenderTargetOutput(size_ return m_stencilRenderTargetOutputs.size() > index ? m_stencilRenderTargetOutputs.at(index) : nullptr; } -ColorRenderTarget * RenderInterface::outputColorRenderTarget(size_t index) const -{ - const auto output = colorRenderTargetOutput(index); - - return output ? **output : nullptr; -} - -DepthRenderTarget * RenderInterface::outputDepthRenderTarget(size_t index) const -{ - const auto output = depthRenderTargetOutput(index); - - return output ? **output : nullptr; -} - -StencilRenderTarget * RenderInterface::outputStencilRenderTarget(size_t index) const -{ - const auto output = stencilRenderTargetOutput(index); - - return output ? **output : nullptr; -} - void RenderInterface::addRenderTargetInput(Input * input) { m_colorRenderTargetInputs.push_back(input); @@ -305,7 +284,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * if (**input) { - drawBuffers.push_back((**input)->type() == RenderTargetType::DefaultFBOAttachment ? (**input)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); + drawBuffers.push_back((**input)->currentTargetType() == RenderTargetType::DefaultFBOAttachment ? (**input)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); } else { @@ -354,22 +333,22 @@ globjects::Framebuffer * RenderInterface::configureFBO(size_t index, AbstractRen { auto attachmentIndex = gl::GL_COLOR_ATTACHMENT0 + index; - if (renderTarget->attachmentType() == AttachmentType::Depth) + if (renderTarget->underlyingAttachmentType() == AttachmentType::Depth) { attachmentIndex = gl::GL_DEPTH_ATTACHMENT; } - if (renderTarget->attachmentType() == AttachmentType::Stencil) + if (renderTarget->underlyingAttachmentType() == AttachmentType::Stencil) { attachmentIndex = gl::GL_STENCIL_ATTACHMENT; } - if (renderTarget->attachmentType() == AttachmentType::DepthStencil) + if (renderTarget->underlyingAttachmentType() == AttachmentType::DepthStencil) { attachmentIndex = gl::GL_DEPTH_STENCIL_ATTACHMENT; } - switch (renderTarget->type()) + switch (renderTarget->currentTargetType()) { case RenderTargetType::DefaultFBOAttachment: return defaultFBO; From bd0ae40535fea2c99f5dc5b07d73139bd0a9707b Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 28 Jun 2017 16:19:40 +0200 Subject: [PATCH 24/33] Extend RenderTarget interface and review RenderInterface interface --- .../stages/IntermediateFramePreparationStage.cpp | 2 +- .../gloperate/rendering/AbstractRenderTarget.h | 12 ++++++++++++ .../gloperate/stages/interfaces/RenderInterface.h | 6 +++--- .../source/rendering/AbstractRenderTarget.cpp | 7 +++++++ source/gloperate/source/stages/base/BlitStage.cpp | 4 ++-- .../source/stages/interfaces/RenderInterface.cpp | 6 +++--- 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index 4738f28b..8a89907f 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -67,7 +67,7 @@ void IntermediateFramePreparationStage::onProcess() }}; auto sourceFBO = renderInterface.configureFBO(0, *intermediateRenderTarget, m_fbo.get(), m_defaultFBO.get()); - auto sourceAttachment = (*intermediateRenderTarget)->attachmentRequiresUserDefinedFramebuffer() ? (*intermediateRenderTarget)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0; + auto sourceAttachment = (*intermediateRenderTarget)->drawBufferAttachment(0); auto targetFBO = m_targetFBO.get(); auto targetAttachment = gl::GL_COLOR_ATTACHMENT0; diff --git a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h index fedceb92..29e229b8 100644 --- a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h @@ -213,6 +213,18 @@ class GLOPERATE_API AbstractRenderTarget */ gl::GLint clearBufferDrawBuffer(size_t index) const; + /** + * @brief + * Get the symbolic constant for the attachment name given a color attachment index + * + * @param[in] index + * The color attachment index + * + * @return + * The symbolic constant for the attachment name + */ + gl::GLenum drawBufferAttachment(size_t index) const; + protected: RenderTargetType m_currentTargetType; ///< Target type diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index fd34ff50..c05e3468 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -193,7 +193,7 @@ class GLOPERATE_API RenderInterface * @return * The color render target at given index, 'null' if index is invalid */ - ColorRenderTarget * inputColorRenderTarget(size_t index) const; + ColorRenderTarget * colorRenderTarget(size_t index) const; /** * @brief @@ -205,7 +205,7 @@ class GLOPERATE_API RenderInterface * @return * The depth render target at given index, 'null' if index is invalid */ - DepthRenderTarget * inputDepthRenderTarget(size_t index) const; + DepthRenderTarget * depthRenderTarget(size_t index) const; /** * @brief @@ -217,7 +217,7 @@ class GLOPERATE_API RenderInterface * @return * The stencil render target at given index, 'null' if index is invalid */ - StencilRenderTarget * inputStencilRenderTarget(size_t index) const; + StencilRenderTarget * stencilRenderTarget(size_t index) const; /** * @brief diff --git a/source/gloperate/source/rendering/AbstractRenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp index 2928955c..ff53f660 100644 --- a/source/gloperate/source/rendering/AbstractRenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -160,5 +160,12 @@ gl::GLint AbstractRenderTarget::clearBufferDrawBuffer(size_t index) const : 0; } +gl::GLenum AbstractRenderTarget::drawBufferAttachment(size_t index) const +{ + return attachmentRequiresUserDefinedFramebuffer() + ? gl::GL_COLOR_ATTACHMENT0 + index + : m_defaultFBOAttachment; +} + } // namespace gloperate diff --git a/source/gloperate/source/stages/base/BlitStage.cpp b/source/gloperate/source/stages/base/BlitStage.cpp index e4dd17d6..21d3bece 100644 --- a/source/gloperate/source/stages/base/BlitStage.cpp +++ b/source/gloperate/source/stages/base/BlitStage.cpp @@ -63,8 +63,8 @@ void BlitStage::onProcess() globjects::Framebuffer * sourceFBO = RenderInterface::configureFBO(0, *source, m_sourceFBO.get(), m_defaultFBO.get()); globjects::Framebuffer * targetFBO = RenderInterface::configureFBO(0, *target, m_targetFBO.get(), m_defaultFBO.get()); - auto sourceAttachment = source->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : source->defaultFramebufferAttachment(); - auto targetAttachment = target->attachmentRequiresUserDefinedFramebuffer() ? gl::GL_COLOR_ATTACHMENT0 : target->defaultFramebufferAttachment(); + auto sourceAttachment = source->drawBufferAttachment(0); + auto targetAttachment = target->drawBufferAttachment(0); if (sourceRect[2] <= targetRect[2] && sourceRect[3] <= targetRect[3]) { diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 1c29ed35..5b778a3f 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -144,21 +144,21 @@ Input * RenderInterface::stencilRenderTargetInput(size_t return m_stencilRenderTargetInputs.size() > index ? m_stencilRenderTargetInputs.at(index) : nullptr; } -ColorRenderTarget * RenderInterface::inputColorRenderTarget(size_t index) const +ColorRenderTarget * RenderInterface::colorRenderTarget(size_t index) const { const auto input = colorRenderTargetInput(index); return input ? **input : nullptr; } -DepthRenderTarget * RenderInterface::inputDepthRenderTarget(size_t index) const +DepthRenderTarget * RenderInterface::depthRenderTarget(size_t index) const { const auto input = depthRenderTargetInput(index); return input ? **input : nullptr; } -StencilRenderTarget * RenderInterface::inputStencilRenderTarget(size_t index) const +StencilRenderTarget * RenderInterface::stencilRenderTarget(size_t index) const { const auto input = stencilRenderTargetInput(index); From a7693c8a7e5eaa31704837c1374b77ba900f3fef Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 28 Jun 2017 17:34:23 +0200 Subject: [PATCH 25/33] Revert ShapeDemo behavior, fix Canvas to RenderInterface connection --- .../demo-stages-plugins/ShapeDemo.cpp | 4 +- source/gloperate/source/base/Canvas.cpp | 21 ---- ...TextureFromRenderTargetExtractionStage.cpp | 7 ++ .../stages/interfaces/RenderInterface.cpp | 100 +++++++++++++++--- 4 files changed, 97 insertions(+), 35 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 00427a6d..b5abf6f0 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -170,8 +170,8 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; // Outputs - //*createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); - *createOutput("ColorOut") << *shapeColorOutput; + *createOutput("ColorOut") << *m_colorizeRasterization->createOutput("ColorOut"); + //*createOutput("ColorOut") << *shapeColorOutput; //*createOutput("ViewportOut") = glm::vec4(0, 0, 700, 700); // Start rotation diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 79c19e32..eb9b26a0 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -334,33 +334,12 @@ void Canvas::render(globjects::Framebuffer * targetFBO) // Update render stage input render targets m_renderStage->forAllInputs([this](Input * input) { - const auto renderTarget = **input; - - if (renderTarget == nullptr) - { - return; - } - input->setValue(m_colorTarget.get()); }); m_renderStage->forAllInputs([this](Input * input) { - const auto renderTarget = **input; - - if (renderTarget == nullptr) - { - return; - } - input->setValue(m_depthTarget.get()); }); m_renderStage->forAllInputs([this](Input * input) { - const auto renderTarget = **input; - - if (renderTarget == nullptr) - { - return; - } - input->setValue(m_stencilTarget.get()); }); diff --git a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp index 8653ee4b..dd6e8b25 100644 --- a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp +++ b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp @@ -26,6 +26,13 @@ TextureFromRenderTargetExtractionStage::~TextureFromRenderTargetExtractionStage( void TextureFromRenderTargetExtractionStage::onProcess() { + if (*colorRenderTarget == nullptr) + { + texture.setValue(nullptr); + + return; + } + switch (colorRenderTarget->currentTargetType()) { case RenderTargetType::Texture: diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 5b778a3f..8350b87d 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -96,19 +96,95 @@ bool RenderInterface::allRenderTargetsCompatible() const auto allDefaultFramebufferAttachments = std::all_of(m_colorRenderTargetInputs.begin(), m_colorRenderTargetInputs.end(), [](Input * input) { - return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }) && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { - return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }) && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { - return input ? (**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }); + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return !renderTarget->attachmentRequiresUserDefinedFramebuffer(); + }) + && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return !renderTarget->attachmentRequiresUserDefinedFramebuffer(); + }) + && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return !renderTarget->attachmentRequiresUserDefinedFramebuffer(); + }); auto allUserDefinedFramebufferAttachments = std::all_of(m_colorRenderTargetInputs.begin(), m_colorRenderTargetInputs.end(), [](Input * input) { - return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }) && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { - return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; - }) && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { - return input ? !(**input)->attachmentRequiresUserDefinedFramebuffer() : true; + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return renderTarget->attachmentRequiresUserDefinedFramebuffer(); + }) + && std::all_of(m_depthRenderTargetInputs.begin(), m_depthRenderTargetInputs.end(), [](Input * input) { + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return renderTarget->attachmentRequiresUserDefinedFramebuffer(); + }) + && std::all_of(m_stencilRenderTargetInputs.begin(), m_stencilRenderTargetInputs.end(), [](Input * input) { + if (input == nullptr) + { + return true; + } + + auto renderTarget = **input; + + if (renderTarget == nullptr) + { + return true; + } + + return renderTarget->attachmentRequiresUserDefinedFramebuffer(); }); return allDefaultFramebufferAttachments != allUserDefinedFramebufferAttachments && numberOfDepthAttachments <= 1; @@ -284,7 +360,7 @@ globjects::Framebuffer * RenderInterface::configureFBO(globjects::Framebuffer * if (**input) { - drawBuffers.push_back((**input)->currentTargetType() == RenderTargetType::DefaultFBOAttachment ? (**input)->defaultFramebufferAttachment() : gl::GL_COLOR_ATTACHMENT0 + colorAttachmentIndex); + drawBuffers.push_back((**input)->drawBufferAttachment(colorAttachmentIndex)); } else { From c6dbf2db7bf277415d6280ac88874d32de9d3b2c Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 28 Jun 2017 17:53:14 +0200 Subject: [PATCH 26/33] Move fbo and default fbo management to RenderInterface --- .../IntermediateFramePreparationStage.h | 2 - .../stages/MultiFrameAggregationStage.h | 2 - .../IntermediateFramePreparationStage.cpp | 10 ++--- .../stages/MultiFrameAggregationStage.cpp | 10 ++--- .../gloperate/stages/base/ClearStage.h | 2 - .../stages/base/RasterizationStage.h | 5 --- .../stages/interfaces/RenderInterface.h | 45 ++++++++++++++++--- .../source/stages/base/BlitStage.cpp | 4 +- .../source/stages/base/ClearStage.cpp | 16 +++---- .../source/stages/base/RasterizationStage.cpp | 8 ++-- .../stages/interfaces/RenderInterface.cpp | 27 ++++++++--- 11 files changed, 83 insertions(+), 48 deletions(-) diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h index 335e1ec6..7591de72 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/IntermediateFramePreparationStage.h @@ -75,8 +75,6 @@ class GLOPERATE_GLKERNEL_API IntermediateFramePreparationStage : public gloperat protected: // Data - std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets - std::unique_ptr m_fbo; ///< Framebuffer for render targets std::unique_ptr m_targetFBO; ///< Framebuffer for blitting target }; diff --git a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h index 5c2bd1b4..4677aa22 100644 --- a/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h +++ b/source/gloperate-glkernel/include/gloperate-glkernel/stages/MultiFrameAggregationStage.h @@ -74,8 +74,6 @@ class GLOPERATE_GLKERNEL_API MultiFrameAggregationStage : public gloperate::Stag protected: // Data std::unique_ptr m_triangle; ///< Screen-aligned Triangle for 'blitting' - std::unique_ptr m_defaultFBO; ///< Default framebuffer for render targets - std::unique_ptr m_fbo; ///< Framebuffer for render targets }; diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index 8a89907f..79a06167 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -35,16 +35,16 @@ IntermediateFramePreparationStage::~IntermediateFramePreparationStage() void IntermediateFramePreparationStage::onContextInit(gloperate::AbstractGLContext * /*context*/) { - m_defaultFBO = globjects::Framebuffer::defaultFBO(); - m_fbo = cppassist::make_unique(); m_targetFBO = cppassist::make_unique(); + + renderInterface.onContextInit(); } void IntermediateFramePreparationStage::onContextDeinit(gloperate::AbstractGLContext * /*context*/) { - m_defaultFBO = nullptr; - m_fbo = nullptr; m_targetFBO = nullptr; + + renderInterface.onContextDeinit(); } void IntermediateFramePreparationStage::onProcess() @@ -66,7 +66,7 @@ void IntermediateFramePreparationStage::onProcess() static_cast(renderInterface.viewport->w) }}; - auto sourceFBO = renderInterface.configureFBO(0, *intermediateRenderTarget, m_fbo.get(), m_defaultFBO.get()); + auto sourceFBO = renderInterface.obtainFBO(0, *intermediateRenderTarget); auto sourceAttachment = (*intermediateRenderTarget)->drawBufferAttachment(0); auto targetFBO = m_targetFBO.get(); diff --git a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp index a03fc65d..6f319ffe 100644 --- a/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp +++ b/source/gloperate-glkernel/source/stages/MultiFrameAggregationStage.cpp @@ -34,15 +34,15 @@ MultiFrameAggregationStage::~MultiFrameAggregationStage() void MultiFrameAggregationStage::onContextInit(gloperate::AbstractGLContext * /*context*/) { m_triangle = cppassist::make_unique(); - m_defaultFBO = globjects::Framebuffer::defaultFBO(); - m_fbo = cppassist::make_unique(); + + renderInterface.onContextInit(); } void MultiFrameAggregationStage::onContextDeinit(gloperate::AbstractGLContext * /*context*/) { m_triangle = nullptr; - m_defaultFBO = nullptr; - m_fbo = nullptr; + + renderInterface.onContextDeinit(); } void MultiFrameAggregationStage::onProcess() @@ -54,7 +54,7 @@ void MultiFrameAggregationStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(); gl::glViewport( renderInterface.viewport->x, diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index e2fd33ad..d840b6d5 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -82,8 +82,6 @@ class GLOPERATE_API ClearStage : public Stage std::vector *> m_depthValueInputs; ///< Depth clear values std::vector *> m_stencilValueInputs; ///< Stencil clear values std::vector> *> m_depthStencilValueInputs; ///< Depth-stencil clear values - std::unique_ptr m_defaultFBO; ///< Default FBO for clearing - std::unique_ptr m_fbo; ///< Intermediate FBO for clearing }; diff --git a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h index 93bf3aa3..1154efb6 100644 --- a/source/gloperate/include/gloperate/stages/base/RasterizationStage.h +++ b/source/gloperate/include/gloperate/stages/base/RasterizationStage.h @@ -75,11 +75,6 @@ class GLOPERATE_API RasterizationStage : public Stage virtual void onProcess() override; virtual void onContextInit(AbstractGLContext * content) override; virtual void onContextDeinit(AbstractGLContext * content) override; - - -protected: - std::unique_ptr m_defaultFBO; ///< Default FBO for rasterization - std::unique_ptr m_fbo; ///< Intermediate FBO for rasterization }; diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index c05e3468..cc665e2b 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -85,7 +85,7 @@ class GLOPERATE_API RenderInterface /** * @brief - * Configures all render targets as attachments for a framebuffer + * Get a configured framebuffer containing all render targets as attachments * * Further, the draw buffers are updated on the framebuffer. * @@ -100,11 +100,25 @@ class GLOPERATE_API RenderInterface * @remarks * allRenderTargetsCompatible() is expected to return 'true'. */ - globjects::Framebuffer * configureFBO(globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO) const; + globjects::Framebuffer * obtainFBO() const; /** * @brief - * Configures one render target as attachment for a framebuffer + * Get a configured framebuffer containing one render target as attachment + * + * @param[in] index + * The next color attachment index + * @param[in] renderTarget + * The render target to attach + * + * @return + * The matching framebuffer; either a user-defined FBO or an default FBO, depending on the type of the render target attachment + */ + globjects::Framebuffer * obtainFBO(size_t index, AbstractRenderTarget * renderTarget) const; + + /** + * @brief + * Get a configured framebuffer containing one render target as attachment * * @param[in] index * The next color attachment index @@ -112,13 +126,11 @@ class GLOPERATE_API RenderInterface * The render target to attach * @param[in] fbo * The user-defined framebuffer used for user-defined attachments - * @param[in] defaultFBO - * The default framebuffer used for default framebuffer attachments * * @return * The matching framebuffer; either fbo or defaultFBO, depending on the type of the render target attachment */ - static globjects::Framebuffer * configureFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); + static globjects::Framebuffer * obtainFBO(size_t index, AbstractRenderTarget * renderTarget, globjects::Framebuffer * fbo, globjects::Framebuffer * defaultFBO); /** * @brief @@ -369,7 +381,28 @@ class GLOPERATE_API RenderInterface */ void pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs = false); + +public: + /** + * @brief + * Initialize in OpenGL context + * + * @see Stage::onContextInit + */ + void onContextInit(); + + /** + * @brief + * De-Initialize in OpenGL context + * + * @see Stage::onContextDeinit() + */ + void onContextDeinit(); + + protected: + std::unique_ptr m_defaultFBO; ///< Default FBO for configuration + std::unique_ptr m_fbo; ///< Intermediate FBO for configuration std::vector *> m_colorRenderTargetInputs; ///< List of input color render targets std::vector *> m_depthRenderTargetInputs; ///< List of input depth render targets std::vector *> m_stencilRenderTargetInputs; ///< List of input depth-stencil render targets diff --git a/source/gloperate/source/stages/base/BlitStage.cpp b/source/gloperate/source/stages/base/BlitStage.cpp index 21d3bece..62c7bdae 100644 --- a/source/gloperate/source/stages/base/BlitStage.cpp +++ b/source/gloperate/source/stages/base/BlitStage.cpp @@ -60,8 +60,8 @@ void BlitStage::onProcess() static_cast((*targetViewport).w) }}; - globjects::Framebuffer * sourceFBO = RenderInterface::configureFBO(0, *source, m_sourceFBO.get(), m_defaultFBO.get()); - globjects::Framebuffer * targetFBO = RenderInterface::configureFBO(0, *target, m_targetFBO.get(), m_defaultFBO.get()); + globjects::Framebuffer * sourceFBO = RenderInterface::obtainFBO(0, *source, m_sourceFBO.get(), m_defaultFBO.get()); + globjects::Framebuffer * targetFBO = RenderInterface::obtainFBO(0, *target, m_targetFBO.get(), m_defaultFBO.get()); auto sourceAttachment = source->drawBufferAttachment(0); auto targetAttachment = target->drawBufferAttachment(0); diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index 12e79eef..a31b4901 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -59,14 +59,12 @@ ClearStage::~ClearStage() void ClearStage::onContextInit(AbstractGLContext *) { - m_defaultFBO = globjects::Framebuffer::defaultFBO(); - m_fbo = cppassist::make_unique(); + renderInterface.onContextInit(); } void ClearStage::onContextDeinit(AbstractGLContext *) { - m_defaultFBO = nullptr; - m_fbo = nullptr; + renderInterface.onContextDeinit(); } void ClearStage::onProcess() @@ -101,7 +99,7 @@ void ClearStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(colorAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(colorAttachmentIndex, **input); const auto attachmentBuffer = (**input)->clearBufferAttachment(); const auto attachmentDrawBuffer = (**input)->clearBufferDrawBuffer(colorAttachmentIndex); @@ -125,7 +123,7 @@ void ClearStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(depthAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(depthAttachmentIndex, **input); fbo->clearBuffer(gl::GL_DEPTH, (**input)->clearBufferDrawBuffer(depthAttachmentIndex), **m_depthValueInputs.at(depthAttachmentIndex)); @@ -138,7 +136,7 @@ void ClearStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(depthStencilAttachmentIndex, **input); fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->clearBufferDrawBuffer(depthStencilAttachmentIndex)); @@ -160,7 +158,7 @@ void ClearStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(stencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(stencilAttachmentIndex, **input); fbo->clearBuffer(gl::GL_STENCIL, (**input)->clearBufferDrawBuffer(stencilAttachmentIndex), **m_stencilValueInputs.at(stencilAttachmentIndex)); @@ -178,7 +176,7 @@ void ClearStage::onProcess() return; } - auto fbo = renderInterface.configureFBO(depthStencilAttachmentIndex, **input, m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(depthStencilAttachmentIndex, **input); fbo->clearBuffer(gl::GL_DEPTH_STENCIL, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).first, (**m_depthStencilValueInputs.at(depthStencilAttachmentIndex)).second, (**input)->clearBufferDrawBuffer(depthStencilAttachmentIndex)); diff --git a/source/gloperate/source/stages/base/RasterizationStage.cpp b/source/gloperate/source/stages/base/RasterizationStage.cpp index 61ddfd6e..176b73a5 100644 --- a/source/gloperate/source/stages/base/RasterizationStage.cpp +++ b/source/gloperate/source/stages/base/RasterizationStage.cpp @@ -29,14 +29,12 @@ RasterizationStage::~RasterizationStage() void RasterizationStage::onContextInit(AbstractGLContext *) { - m_defaultFBO = globjects::Framebuffer::defaultFBO(); - m_fbo = cppassist::make_unique(); + renderInterface.onContextInit(); } void RasterizationStage::onContextDeinit(AbstractGLContext *) { - m_defaultFBO = nullptr; - m_fbo = nullptr; + renderInterface.onContextDeinit(); } void RasterizationStage::onProcess() @@ -56,7 +54,7 @@ void RasterizationStage::onProcess() gl::glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); // Configure FBO - auto fbo = renderInterface.configureFBO(m_fbo.get(), m_defaultFBO.get()); + auto fbo = renderInterface.obtainFBO(); // Bind FBO fbo->bind(gl::GL_FRAMEBUFFER); diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 8350b87d..e390ee72 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -337,7 +337,7 @@ void RenderInterface::pairwiseRenderTargetsDo(std::function(); +} + +void RenderInterface::onContextDeinit() +{ + m_defaultFBO = nullptr; + m_fbo = nullptr; +} + } // namespace gloperate From 5e6282283fe86093dcb1f9ac90470f502eb2f18c Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 28 Jun 2017 19:27:39 +0200 Subject: [PATCH 27/33] Small consolidation of IntermediateFramePreparation logic --- .../source/stages/IntermediateFramePreparationStage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp index 79a06167..01d2c718 100644 --- a/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp +++ b/source/gloperate-glkernel/source/stages/IntermediateFramePreparationStage.cpp @@ -72,7 +72,7 @@ void IntermediateFramePreparationStage::onProcess() auto targetFBO = m_targetFBO.get(); auto targetAttachment = gl::GL_COLOR_ATTACHMENT0; - targetFBO->attachTexture(gl::GL_COLOR_ATTACHMENT0, *intermediateFrameTexture); + targetFBO->attachTexture(targetAttachment, *intermediateFrameTexture); sourceFBO->blit(sourceAttachment, rect, targetFBO, targetAttachment, rect, gl::GL_COLOR_BUFFER_BIT, gl::GL_NEAREST); } From 3b592786aa7c4e8befb0a1e171af27a26858aac7 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Thu, 29 Jun 2017 14:47:08 +0200 Subject: [PATCH 28/33] Intermediate commit for DepthStencilRenderTarget subclass --- source/gloperate/CMakeLists.txt | 2 + .../gloperate/include/gloperate/base/Canvas.h | 44 +++++++++-------- .../rendering/AbstractRenderTarget.h | 48 ++++++++----------- .../gloperate/rendering/ColorRenderTarget.h | 4 ++ .../gloperate/rendering/DepthRenderTarget.h | 4 ++ .../rendering/DepthStencilRenderTarget.h | 33 +++++++++++++ .../gloperate/rendering/StencilRenderTarget.h | 4 ++ source/gloperate/source/base/Canvas.cpp | 6 +-- .../source/rendering/AbstractRenderTarget.cpp | 26 ---------- .../source/rendering/ColorRenderTarget.cpp | 8 ++++ .../source/rendering/DepthRenderTarget.cpp | 8 ++++ .../rendering/DepthStencilRenderTarget.cpp | 17 +++++++ .../source/rendering/StencilRenderTarget.cpp | 15 ++++++ 13 files changed, 140 insertions(+), 79 deletions(-) create mode 100644 source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h create mode 100644 source/gloperate/source/rendering/DepthStencilRenderTarget.cpp diff --git a/source/gloperate/CMakeLists.txt b/source/gloperate/CMakeLists.txt index bdc1d6f8..222deb63 100644 --- a/source/gloperate/CMakeLists.txt +++ b/source/gloperate/CMakeLists.txt @@ -96,6 +96,7 @@ set(headers ${include_path}/rendering/AbstractRenderTarget.h ${include_path}/rendering/ColorRenderTarget.h ${include_path}/rendering/DepthRenderTarget.h + ${include_path}/rendering/DepthStencilRenderTarget.h ${include_path}/rendering/StencilRenderTarget.h ${include_path}/rendering/RenderTargetType.h ${include_path}/rendering/TransparencyMasksGenerator.h @@ -199,6 +200,7 @@ set(sources ${source_path}/rendering/AbstractRenderTarget.cpp ${source_path}/rendering/ColorRenderTarget.cpp ${source_path}/rendering/DepthRenderTarget.cpp + ${source_path}/rendering/DepthStencilRenderTarget.cpp ${source_path}/rendering/StencilRenderTarget.cpp ${source_path}/rendering/TransparencyMasksGenerator.cpp ${source_path}/rendering/ScreenAlignedQuad.cpp diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 0b79c24b..74ce700e 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -34,6 +34,7 @@ class MouseDevice; class KeyboardDevice; class ColorRenderTarget; class DepthRenderTarget; +class DepthStencilRenderTarget; class StencilRenderTarget; class BlitStage; @@ -314,27 +315,28 @@ class GLOPERATE_API Canvas : public cppexpose::Object protected: - Environment * m_environment; ///< Gloperate environment to which the canvas belongs - AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas - bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' - gloperate::ChronoTimer m_clock; ///< Time measurement - glm::vec4 m_viewport; ///< Viewport (in real device coordinates) - float m_timeDelta; ///< Time delta since the last update (in seconds) - std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas - std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call - std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets - std::unique_ptr m_mouseDevice; ///< Device for Mouse Events - std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events - bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' - std::mutex m_mutex; ///< Mutex for separating main and render thread - cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage - cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) - std::vector m_changedInputs; ///< List of changed input slots - std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs - - std::unique_ptr m_colorTarget; ///< Input render target for color attachment - std::unique_ptr m_depthTarget; ///< Input render target for depth attachment - std::unique_ptr m_stencilTarget; ///< Input render target for stencil attachment + Environment * m_environment; ///< Gloperate environment to which the canvas belongs + AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas + bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' + gloperate::ChronoTimer m_clock; ///< Time measurement + glm::vec4 m_viewport; ///< Viewport (in real device coordinates) + float m_timeDelta; ///< Time delta since the last update (in seconds) + std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas + std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call + std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets + std::unique_ptr m_mouseDevice; ///< Device for Mouse Events + std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events + bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' + std::mutex m_mutex; ///< Mutex for separating main and render thread + cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage + cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) + std::vector m_changedInputs; ///< List of changed input slots + std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs + + std::unique_ptr m_colorTarget; ///< Input render target for color attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth attachment + std::unique_ptr m_depthStencilTarget; ///< Input render target for combined depth stencil attachment + std::unique_ptr m_stencilTarget; ///< Input render target for stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h index 29e229b8..87964b2c 100644 --- a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h @@ -56,33 +56,6 @@ class GLOPERATE_API AbstractRenderTarget */ void releaseTarget(); - /** - * @brief - * Get attachment type - * - * @return - * The attachment type - */ - AttachmentType underlyingAttachmentType() const; - - /** - * @brief - * Set attachment type - * - * @param[in] type - * The attachment type - */ - void setUnderlyingAttachmentType(AttachmentType underlyingAttachmentType); - - /** - * @brief - * Get attachment type as GLenum - * - * @return - * The attachment type as GLenum - */ - gl::GLenum attachmentGLType() const; - /** * @brief * Set desired target @@ -226,9 +199,28 @@ class GLOPERATE_API AbstractRenderTarget gl::GLenum drawBufferAttachment(size_t index) const; +public: + /** + * @brief + * Get attachment type + * + * @return + * The attachment type + */ + virtual AttachmentType underlyingAttachmentType() const = 0; + + /** + * @brief + * Get attachment type as GLenum + * + * @return + * The attachment type as GLenum + */ + virtual gl::GLenum attachmentGLType() const = 0; + + protected: RenderTargetType m_currentTargetType; ///< Target type - AttachmentType m_internalAttachmentType; ///< Internal OpenGL attachment type gl::GLenum m_defaultFBOAttachment; ///< Default framebuffer attachment target globjects::Texture * m_texture; ///< Texture target globjects::Renderbuffer * m_renderbuffer; ///< Renderbuffer target diff --git a/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h b/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h index a56bc7cc..60162e06 100644 --- a/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/ColorRenderTarget.h @@ -23,6 +23,10 @@ class GLOPERATE_API ColorRenderTarget : public AbstractRenderTarget { public: using AbstractRenderTarget::AbstractRenderTarget; + + // Virtual AbstractRenderTarget interface + virtual AttachmentType underlyingAttachmentType() const override; + virtual gl::GLenum attachmentGLType() const override; }; diff --git a/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h b/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h index f8b4d744..f19ba733 100644 --- a/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/DepthRenderTarget.h @@ -23,6 +23,10 @@ class GLOPERATE_API DepthRenderTarget : public AbstractRenderTarget { public: using AbstractRenderTarget::AbstractRenderTarget; + + // Virtual AbstractRenderTarget interface + virtual AttachmentType underlyingAttachmentType() const override; + virtual gl::GLenum attachmentGLType() const override; }; diff --git a/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h b/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h new file mode 100644 index 00000000..58ecc207 --- /dev/null +++ b/source/gloperate/include/gloperate/rendering/DepthStencilRenderTarget.h @@ -0,0 +1,33 @@ + +#pragma once + + +#include + +#include + + +namespace gloperate +{ + + +/** +* @brief +* Combined depth stencil render target that represents one depth stencil target for depth and stencil tests during rasterization +* +* A render target can internally be: a texture, a renderbuffer, +* a symbolic attachment of the default renderbuffer, or a user-defined +* renderbuffer with attachment specification. +*/ +class GLOPERATE_API DepthStencilRenderTarget : public AbstractRenderTarget +{ +public: + using AbstractRenderTarget::AbstractRenderTarget; + + // Virtual AbstractRenderTarget interface + virtual AttachmentType underlyingAttachmentType() const override; + virtual gl::GLenum attachmentGLType() const override; +}; + + +} // namespace gloperate diff --git a/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h b/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h index c9366529..f21c4c48 100644 --- a/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/StencilRenderTarget.h @@ -24,6 +24,10 @@ class GLOPERATE_API StencilRenderTarget : public AbstractRenderTarget { public: using AbstractRenderTarget::AbstractRenderTarget; + + // Virtual AbstractRenderTarget interface + virtual AttachmentType underlyingAttachmentType() const override; + virtual gl::GLenum attachmentGLType() const override; }; diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index eb9b26a0..91c85800 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ Canvas::Canvas(Environment * environment) , m_replaceStage(false) , m_colorTarget(cppassist::make_unique()) , m_depthTarget(cppassist::make_unique()) +, m_depthStencilTarget(cppassist::make_unique()) , m_stencilTarget(cppassist::make_unique()) { // Register functions @@ -77,10 +79,6 @@ Canvas::Canvas(Environment * environment) // Register canvas m_environment->registerCanvas(this); - - m_colorTarget->setUnderlyingAttachmentType(AttachmentType::Color); - m_depthTarget->setUnderlyingAttachmentType(AttachmentType::Depth); - m_stencilTarget->setUnderlyingAttachmentType(AttachmentType::Stencil); } Canvas::~Canvas() diff --git a/source/gloperate/source/rendering/AbstractRenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp index ff53f660..5521989a 100644 --- a/source/gloperate/source/rendering/AbstractRenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -52,32 +52,6 @@ void AbstractRenderTarget::releaseTarget() m_currentTargetType = RenderTargetType::Invalid; } -AttachmentType AbstractRenderTarget::underlyingAttachmentType() const -{ - return m_internalAttachmentType; -} - -gl::GLenum AbstractRenderTarget::attachmentGLType() const -{ - switch (m_internalAttachmentType) - { - case AttachmentType::Depth: - return gl::GL_DEPTH; - case AttachmentType::Stencil: - return gl::GL_STENCIL; - case AttachmentType::DepthStencil: - return gl::GL_DEPTH_STENCIL; - case AttachmentType::Color: - default: - return gl::GL_COLOR; - } -} - -void AbstractRenderTarget::setUnderlyingAttachmentType(AttachmentType attachmentType) -{ - m_internalAttachmentType = attachmentType; -} - void AbstractRenderTarget::setTarget(globjects::Texture * texture) { releaseTarget(); diff --git a/source/gloperate/source/rendering/ColorRenderTarget.cpp b/source/gloperate/source/rendering/ColorRenderTarget.cpp index 8cca1df6..c1bc3ca9 100644 --- a/source/gloperate/source/rendering/ColorRenderTarget.cpp +++ b/source/gloperate/source/rendering/ColorRenderTarget.cpp @@ -1,9 +1,17 @@ #include +#include + namespace gloperate { +AttachmentType ColorRenderTarget::underlyingAttachmentType() const +{ + return AttachmentType::Color; +} + + } // namespace gloperate diff --git a/source/gloperate/source/rendering/DepthRenderTarget.cpp b/source/gloperate/source/rendering/DepthRenderTarget.cpp index b907c7cf..3b8b3526 100644 --- a/source/gloperate/source/rendering/DepthRenderTarget.cpp +++ b/source/gloperate/source/rendering/DepthRenderTarget.cpp @@ -1,9 +1,17 @@ #include +#include + namespace gloperate { +AttachmentType DepthRenderTarget::underlyingAttachmentType() const +{ + return AttachmentType::Depth; +} + + } // namespace gloperate diff --git a/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp b/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp new file mode 100644 index 00000000..1ddb4956 --- /dev/null +++ b/source/gloperate/source/rendering/DepthStencilRenderTarget.cpp @@ -0,0 +1,17 @@ + +#include + +#include + + +namespace gloperate +{ + + +AttachmentType DepthStencilRenderTarget::underlyingAttachmentType() const +{ + return AttachmentType::DepthStencil; +} + + +} // namespace gloperate diff --git a/source/gloperate/source/rendering/StencilRenderTarget.cpp b/source/gloperate/source/rendering/StencilRenderTarget.cpp index 482ccb2b..8a445782 100644 --- a/source/gloperate/source/rendering/StencilRenderTarget.cpp +++ b/source/gloperate/source/rendering/StencilRenderTarget.cpp @@ -1,9 +1,24 @@ #include +#include + +#include + namespace gloperate { +AttachmentType StencilRenderTarget::underlyingAttachmentType() const +{ + return AttachmentType::Stencil; +} + +gl::GLenum StencilRenderTarget::attachmentGLType() const +{ + return gl::GL_STENCIL; +} + + } // namespace gloperate From 6a29d7c13eefcfee1a97e1ed3609e045efee5679 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 30 Jun 2017 15:13:30 +0200 Subject: [PATCH 29/33] Fix unchecked usages of empty render stage in canvas --- .../stages/interfaces/RenderInterface.h | 2 +- source/gloperate/source/base/Canvas.cpp | 60 ++++++++++------ .../stages/interfaces/RenderInterface.cpp | 69 +++++++++++++++++-- 3 files changed, 106 insertions(+), 25 deletions(-) diff --git a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h index 45d1fe71..9c6cc506 100644 --- a/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h +++ b/source/gloperate/include/gloperate/stages/interfaces/RenderInterface.h @@ -158,7 +158,7 @@ class GLOPERATE_API RenderInterface * @return * The vector of depth-stencil render target inputs */ - const std::vector *> & depthRenderTargetInputs() const; + const std::vector *> & depthStencilRenderTargetInputs() const; /** * @brief diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index 91c85800..d63273b4 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -198,6 +198,11 @@ void Canvas::updateTime() float timeDelta = std::chrono::duration_cast>(duration).count(); m_timeDelta += timeDelta; + if (!m_renderStage) + { + return; + } + // Update timing auto slotTimeDelta = m_renderStage->findInput([](Input* input) { return input->name() == "timeDelta"; }); if (slotTimeDelta) @@ -220,6 +225,11 @@ void Canvas::setViewport(const glm::vec4 & deviceViewport) m_viewport = deviceViewport; m_initialized = true; + if (!m_renderStage) + { + return; + } + // Promote new viewport auto slotViewport = m_renderStage->findInput([](Input* input) { return input->name() == "viewport"; }); if (slotViewport) slotViewport->setValue(m_viewport); @@ -244,7 +254,10 @@ void Canvas::render(globjects::Framebuffer * targetFBO) debug(2, "gloperate") << "render(); " << "targetFBO: " << fboName; // Abort if not initialized - if (!m_initialized || !m_renderStage) return; + if (!m_initialized || !m_renderStage) + { + return; + } // Check if the render stage is to be replaced if (m_replaceStage) @@ -302,31 +315,30 @@ void Canvas::render(globjects::Framebuffer * targetFBO) { m_colorTarget->releaseTarget(); } + if (depthAttachment) + { + m_depthTarget->setTarget(depthAttachment); + } + else + { + m_depthTarget->releaseTarget(); + } + if (stencilAttachment) + { + m_stencilTarget->setTarget(stencilAttachment); + } + else + { + m_stencilTarget->releaseTarget(); + } if (depthStencilAttachment) { - m_depthTarget->setTarget(depthStencilAttachment); - m_stencilTarget->setTarget(depthStencilAttachment); + m_depthStencilTarget->setTarget(depthStencilAttachment); } else { - if (depthAttachment) - { - m_depthTarget->setTarget(depthAttachment); - } - else - { - m_depthTarget->releaseTarget(); - } - - if (stencilAttachment) - { - m_stencilTarget->setTarget(stencilAttachment); - } - else - { - m_stencilTarget->releaseTarget(); - } + m_depthStencilTarget->releaseTarget(); } } @@ -337,6 +349,9 @@ void Canvas::render(globjects::Framebuffer * targetFBO) m_renderStage->forAllInputs([this](Input * input) { input->setValue(m_depthTarget.get()); }); + m_renderStage->forAllInputs([this](Input * input) { + input->setValue(m_depthStencilTarget.get()); + }); m_renderStage->forAllInputs([this](Input * input) { input->setValue(m_stencilTarget.get()); }); @@ -449,6 +464,11 @@ void Canvas::promoteMouseWheel(const glm::vec2 & delta, const glm::ivec2 & pos) void Canvas::checkRedraw() { + if (!m_renderStage) + { + return; + } + bool redraw = false; m_renderStage->forAllOutputs([& redraw](Output * output) { if (**output && !output->isValid()) diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 0801aa34..2a2f5295 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -102,12 +103,13 @@ void RenderInterface::updateRenderTargetOutputs() { bool RenderInterface::allRenderTargetsCompatible() const { - if (m_colorRenderTargetOutputs.empty() && m_depthRenderTargetOutputs.empty() && m_stencilRenderTargetOutputs.empty()) + if (m_colorRenderTargetInputs.empty() && m_depthRenderTargetInputs.empty() && m_depthStencilRenderTargetInputs.empty() && m_stencilRenderTargetInputs.empty()) { return true; } - auto numberOfDepthAttachments = m_depthRenderTargetOutputs.size() + m_stencilRenderTargetOutputs.size(); + auto numberOfDepthAttachments = m_depthRenderTargetOutputs.size() + m_depthStencilRenderTargetOutputs.size(); + auto numberOfStencilAttachments = m_depthStencilRenderTargetOutputs.size() + m_stencilRenderTargetOutputs.size(); auto allDefaultFramebufferAttachments = std::all_of(m_colorRenderTargetInputs.begin(), m_colorRenderTargetInputs.end(), [](Input * input) { @@ -232,7 +234,7 @@ bool RenderInterface::allRenderTargetsCompatible() const return renderTarget->attachmentRequiresUserDefinedFramebuffer(); }); - return allDefaultFramebufferAttachments != allUserDefinedFramebufferAttachments && numberOfDepthAttachments <= 1; + return allDefaultFramebufferAttachments != allUserDefinedFramebufferAttachments && numberOfDepthAttachments <= 1 && numberOfStencilAttachments <= 1; } const std::vector *> & RenderInterface::colorRenderTargetInputs() const @@ -247,7 +249,7 @@ const std::vector *> & RenderInterface::depthRenderTa const std::vector *> & RenderInterface::depthStencilRenderTargetInputs() const { - return m_depthRenderTargetInputs; + return m_depthStencilRenderTargetInputs; } const std::vector *> & RenderInterface::stencilRenderTargetInputs() const @@ -265,6 +267,11 @@ Input * RenderInterface::depthRenderTargetInput(size_t inde return m_depthRenderTargetInputs.size() > index ? m_depthRenderTargetInputs.at(index) : nullptr; } +Input * RenderInterface::depthStencilRenderTargetInput(size_t index) const +{ + return m_depthStencilRenderTargetInputs.size() > index ? m_depthStencilRenderTargetInputs.at(index) : nullptr; +} + Input * RenderInterface::stencilRenderTargetInput(size_t index) const { return m_stencilRenderTargetInputs.size() > index ? m_stencilRenderTargetInputs.at(index) : nullptr; @@ -284,6 +291,13 @@ DepthRenderTarget * RenderInterface::depthRenderTarget(size_t index) const return input ? **input : nullptr; } +DepthStencilRenderTarget * RenderInterface::depthStencilRenderTarget(size_t index) const +{ + const auto input = depthStencilRenderTargetInput(index); + + return input ? **input : nullptr; +} + StencilRenderTarget * RenderInterface::stencilRenderTarget(size_t index) const { const auto input = stencilRenderTargetInput(index); @@ -301,6 +315,11 @@ const std::vector *> & RenderInterface::depthRenderT return m_depthRenderTargetOutputs; } +const std::vector *> & RenderInterface::depthStencilRenderTargetOutputs() const +{ + return m_depthStencilRenderTargetOutputs; +} + const std::vector *> & RenderInterface::stencilRenderTargetOutputs() const { return m_stencilRenderTargetOutputs; @@ -316,6 +335,11 @@ Output * RenderInterface::depthRenderTargetOutput(size_t in return m_depthRenderTargetOutputs.size() > index ? m_depthRenderTargetOutputs.at(index) : nullptr; } +Output * RenderInterface::depthStencilRenderTargetOutput(size_t index) const +{ + return m_depthStencilRenderTargetOutputs.size() > index ? m_depthStencilRenderTargetOutputs.at(index) : nullptr; +} + Output * RenderInterface::stencilRenderTargetOutput(size_t index) const { return m_stencilRenderTargetOutputs.size() > index ? m_stencilRenderTargetOutputs.at(index) : nullptr; @@ -331,6 +355,11 @@ void RenderInterface::addRenderTargetInput(Input * input) m_depthRenderTargetInputs.push_back(input); } +void RenderInterface::addRenderTargetInput(Input * input) +{ + m_depthStencilRenderTargetInputs.push_back(input); +} + void RenderInterface::addRenderTargetInput(Input * input) { m_stencilRenderTargetInputs.push_back(input); @@ -346,6 +375,11 @@ void RenderInterface::addRenderTargetOutput(Output * input) m_depthRenderTargetOutputs.push_back(input); } +void RenderInterface::addRenderTargetOutput(Output * input) +{ + m_depthStencilRenderTargetOutputs.push_back(input); +} + void RenderInterface::addRenderTargetOutput(Output * input) { m_stencilRenderTargetOutputs.push_back(input); @@ -375,6 +409,18 @@ void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) +{ + const auto end = includeIncompletePairs + ? std::max(m_depthStencilRenderTargetInputs.size(), m_depthStencilRenderTargetOutputs.size()) + : std::min(m_depthStencilRenderTargetInputs.size(), m_depthStencilRenderTargetOutputs.size()); + + for (auto i = size_t(0); i < end; ++i) + { + callback(depthStencilRenderTargetInput(i), depthStencilRenderTargetOutput(i)); + } +} + void RenderInterface::pairwiseRenderTargetsDo(std::function *, Output *)> callback, bool includeIncompletePairs) { const auto end = includeIncompletePairs @@ -435,6 +481,21 @@ globjects::Framebuffer * RenderInterface::obtainFBO() const } } + for (auto input : m_depthStencilRenderTargetInputs) + { + auto nextFBO = obtainFBO(0, **input); + + if (!currentFBO) + { + currentFBO = nextFBO; + } + + if (nextFBO != currentFBO) + { + return nullptr; + } + } + for (auto input : m_stencilRenderTargetInputs) { auto nextFBO = obtainFBO(0, **input); From a64e098c9ab76e51434ffd3de70643120dc3f33e Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 30 Jun 2017 15:22:30 +0200 Subject: [PATCH 30/33] Add scanPlugins to initialization of viewer --- data/gloperate/qml/Viewer.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index 7daf7a25..b10e9dce 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -436,6 +436,8 @@ ApplicationWindow // Load settings settings.load(); } + + gloperate.components.scanPlugins(); // Set render stage window.stage = settings.stage; From 96bcc442784124b02f8037bdd3bccd0a12e474f0 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Fri, 30 Jun 2017 17:17:48 +0200 Subject: [PATCH 31/33] Restore black background color --- source/examples/demo-stages-plugins/ColorGradientDemo.cpp | 2 +- source/examples/demo-stages-plugins/ShapeDemo.cpp | 2 +- source/gloperate/include/gloperate/stages/base/ClearStage.h | 2 +- source/gloperate/source/stages/base/ClearStage.cpp | 5 +++-- .../gloperate/source/stages/interfaces/CanvasInterface.cpp | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/examples/demo-stages-plugins/ColorGradientDemo.cpp b/source/examples/demo-stages-plugins/ColorGradientDemo.cpp index cb838600..be57a405 100644 --- a/source/examples/demo-stages-plugins/ColorGradientDemo.cpp +++ b/source/examples/demo-stages-plugins/ColorGradientDemo.cpp @@ -110,7 +110,7 @@ ColorGradientDemo::ColorGradientDemo(Environment * environment, const std::strin addStage(m_clear.get()); m_clear->createInput("ColorAttachment") << *createInput("Color"); m_clear->createInput("DepthAttachment") << *createInput("Depth"); - m_clear->createInput("ColorValue") = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + m_clear->createInput("ColorValue") << canvasInterface.backgroundColor; m_clear->createInput("DepthValue") = 1.0f; // Rasterization stage for shape diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index b5abf6f0..ac6e0720 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -123,7 +123,7 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) addStage(m_clear.get()); m_clear->createInput("ColorAttachment") << m_framebuffer->colorBuffer; m_clear->createInput("DepthAttachment") << m_framebuffer->depthBuffer; - m_clear->createInput("ColorValue") = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + m_clear->createInput("ColorValue") << canvasInterface.backgroundColor; m_clear->createInput("DepthValue") = 1.0f; m_clear->renderInterface.viewport << canvasInterface.viewport; diff --git a/source/gloperate/include/gloperate/stages/base/ClearStage.h b/source/gloperate/include/gloperate/stages/base/ClearStage.h index d840b6d5..d31c5b5b 100644 --- a/source/gloperate/include/gloperate/stages/base/ClearStage.h +++ b/source/gloperate/include/gloperate/stages/base/ClearStage.h @@ -78,7 +78,7 @@ class GLOPERATE_API ClearStage : public Stage protected: - std::vector *> m_colorValueInputs; ///< Color clear values + std::vector *> m_colorValueInputs; ///< Color clear values std::vector *> m_depthValueInputs; ///< Depth clear values std::vector *> m_stencilValueInputs; ///< Stencil clear values std::vector> *> m_depthStencilValueInputs; ///< Depth-stencil clear values diff --git a/source/gloperate/source/stages/base/ClearStage.cpp b/source/gloperate/source/stages/base/ClearStage.cpp index a31b4901..b9863198 100644 --- a/source/gloperate/source/stages/base/ClearStage.cpp +++ b/source/gloperate/source/stages/base/ClearStage.cpp @@ -26,7 +26,7 @@ ClearStage::ClearStage(Environment * environment, const std::string & name) , clear("clear", this, true) { inputAdded.connect( [this] (AbstractSlot * connectedInput) { - auto colorValueInput = dynamic_cast *>(connectedInput); + auto colorValueInput = dynamic_cast *>(connectedInput); auto depthValueInput = dynamic_cast *>(connectedInput); auto stencilValueInput = dynamic_cast *>(connectedInput); auto depthStencilValueInput = dynamic_cast> *>(connectedInput); @@ -105,7 +105,8 @@ void ClearStage::onProcess() const auto attachmentDrawBuffer = (**input)->clearBufferDrawBuffer(colorAttachmentIndex); const auto clearColor = **m_colorValueInputs.at(colorAttachmentIndex); - fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColor); + auto clearColorF = clearColor.toVec4(); + fbo->clearBuffer(attachmentBuffer, attachmentDrawBuffer, clearColorF); ++colorAttachmentIndex; }); diff --git a/source/gloperate/source/stages/interfaces/CanvasInterface.cpp b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp index e3ab1949..bf0cb5f0 100644 --- a/source/gloperate/source/stages/interfaces/CanvasInterface.cpp +++ b/source/gloperate/source/stages/interfaces/CanvasInterface.cpp @@ -8,7 +8,7 @@ namespace gloperate CanvasInterface::CanvasInterface(Stage * stage) : RenderInterface(stage) -, backgroundColor("backgroundColor", stage) +, backgroundColor("backgroundColor", stage, Color(0, 0, 0, 255)) , frameCounter ("frameCounter", stage) , timeDelta ("timeDelta", stage) { From 89e2f31232be8440d613adbd7dd220496eb848c8 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Tue, 4 Jul 2017 23:37:27 +0200 Subject: [PATCH 32/33] Somehow finish merge --- .../MultiFramePostprocessingStage.cpp | 1 - .../MultiFramePostprocessingStage.h | 2 - .../MultiFrameRenderingPipeline.cpp | 20 ++++-- .../MultiFrameRenderingPipeline.h | 4 ++ .../MultiFrameSceneRenderingStage.cpp | 2 +- .../SSAOApplicationStage.cpp | 18 ++--- .../SSAOApplicationStage.h | 2 - .../SSAORenderingPipeline.cpp | 66 ++++++++++--------- .../SSAORenderingPipeline.h | 26 ++++---- .../SSAOSceneRenderingStage.cpp | 10 +-- .../SSAOSceneRenderingStage.h | 4 +- .../ShaderDemoPipeline.cpp | 21 +++--- .../demo-stages-plugins/ShaderDemoPipeline.h | 29 ++++---- .../TransparencyRenderingPipeline.cpp | 15 ++--- .../TransparencyRenderingPipeline.h | 4 +- .../TransparentCirclesStage.cpp | 10 +-- .../TransparentCirclesStage.h | 4 +- .../include/gloperate-glfw/Window.h | 8 ++- .../TextureFromRenderTargetExtractionStage.h | 15 ++++- .../gloperate/source/loaders/ShaderLoader.cpp | 2 +- ...TextureFromRenderTargetExtractionStage.cpp | 32 +++++++-- 21 files changed, 172 insertions(+), 123 deletions(-) diff --git a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp index f4884063..58fbceba 100644 --- a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp +++ b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp @@ -46,7 +46,6 @@ MultiFramePostprocessingStage::MultiFramePostprocessingStage(gloperate::Environm , ssaoNoise("ssaoNoise", this, nullptr) , projectionMatrix("projectionMatrix", this) , normalMatrix("normalMatrix", this) -, sceneRendered("sceneRendered", this, false) { } diff --git a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.h b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.h index 5e09ef7d..bd352609 100644 --- a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.h +++ b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.h @@ -51,8 +51,6 @@ class MultiFramePostprocessingStage : public gloperate::Stage Input projectionMatrix; ///< Projection matrix used for rendering the scene Input normalMatrix; ///< Normal matrix from scene rendering - Input sceneRendered; ///< Scene rendering stage processed? - public: /** diff --git a/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.cpp b/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.cpp index 06f6ee23..8cf6b823 100644 --- a/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.cpp +++ b/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -33,6 +34,9 @@ MultiFrameRenderingPipeline::MultiFrameRenderingPipeline(gloperate::Environment , m_noiseStage(cppassist::make_unique(environment)) , m_transparencyKernelStage(cppassist::make_unique(environment)) , m_renderingStage(cppassist::make_unique(environment)) +, m_colorTextureExtractionStage(cppassist::make_unique(environment)) +, m_depthTextureExtractionStage(cppassist::make_unique(environment)) +, m_normalTextureExtractionStage(cppassist::make_unique(environment)) , m_postprocessingStage(cppassist::make_unique(environment)) { addStage(m_colorTextureStage.get()); @@ -82,7 +86,14 @@ MultiFrameRenderingPipeline::MultiFrameRenderingPipeline(gloperate::Environment m_renderingStage->noiseKernelTexture << m_noiseStage->texture; m_renderingStage->transparencyKernelTexture << m_transparencyKernelStage->texture; - // TODO: fix renderingStage <-> postprocessingStage interface + addStage(m_colorTextureExtractionStage.get()); + m_colorTextureExtractionStage->colorRenderTarget << *m_renderingStage->createOutput("ColorOut"); + + addStage(m_depthTextureExtractionStage.get()); + m_depthTextureExtractionStage->depthRenderTarget << *m_renderingStage->createOutput("DepthOut"); + + addStage(m_normalTextureExtractionStage.get()); + m_normalTextureExtractionStage->colorRenderTarget << *m_renderingStage->createOutput("NormalOut"); addStage(m_postprocessingStage.get()); m_postprocessingStage->canvasInterface.backgroundColor << canvasInterface.backgroundColor; @@ -90,14 +101,13 @@ MultiFrameRenderingPipeline::MultiFrameRenderingPipeline(gloperate::Environment m_postprocessingStage->canvasInterface.frameCounter << canvasInterface.frameCounter; m_postprocessingStage->canvasInterface.timeDelta << canvasInterface.timeDelta; m_postprocessingStage->createInput("Color") << *createInput("Color"); - m_postprocessingStage->colorTexture << m_colorTextureStage->texture; - m_postprocessingStage->normalTexture << m_normalTextureStage->texture; - m_postprocessingStage->depthTexture << m_depthTextureStage->texture; + m_postprocessingStage->colorTexture << m_colorTextureExtractionStage->texture; + m_postprocessingStage->normalTexture << m_normalTextureExtractionStage->texture; + m_postprocessingStage->depthTexture << m_depthTextureExtractionStage->texture; m_postprocessingStage->ssaoKernel << m_ssaoKernelStage->texture; m_postprocessingStage->ssaoNoise << m_noiseStage->texture; m_postprocessingStage->projectionMatrix << m_renderingStage->projectionMatrix; m_postprocessingStage->normalMatrix << m_renderingStage->normalMatrix; - m_postprocessingStage->sceneRendered << m_renderingStage->canvasInterface.rendered; *createOutput("ColorOut") << *m_postprocessingStage->createOutput("ColorOut"); } diff --git a/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.h b/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.h index 53fec88b..91ae1fee 100644 --- a/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.h +++ b/source/examples/demo-stages-plugins/MultiFrameRenderingPipeline.h @@ -12,6 +12,7 @@ namespace gloperate { class TextureRenderTargetStage; + class TextureFromRenderTargetExtractionStage; } @@ -89,5 +90,8 @@ class MultiFrameRenderingPipeline : public gloperate::Pipeline // Rendering std::unique_ptr m_renderingStage; + std::unique_ptr m_colorTextureExtractionStage; + std::unique_ptr m_depthTextureExtractionStage; + std::unique_ptr m_normalTextureExtractionStage; std::unique_ptr m_postprocessingStage; }; diff --git a/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp b/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp index 34419805..5f7244d7 100644 --- a/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp +++ b/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp @@ -110,7 +110,7 @@ void MultiFrameSceneRenderingStage::onProcess() globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); // Signal that output is valid - renderInterface.rendered.setValue(true); + canvasInterface.updateRenderTargetOutputs(); } void MultiFrameSceneRenderingStage::setupGeometry() diff --git a/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp b/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp index 6506fb95..a399f811 100644 --- a/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp +++ b/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp @@ -46,7 +46,6 @@ SSAOApplicationStage::SSAOApplicationStage(gloperate::Environment * environment, , ssaoNoise("ssaoNoise", this, nullptr) , projectionMatrix("projectionMatrix", this) , normalMatrix("normalMatrix", this) -, sceneRendered("sceneRendered", this, false) { } @@ -80,12 +79,13 @@ void SSAOApplicationStage::onProcess() { if (!(*colorTexture && *normalTexture && *depthTexture && *ssaoKernel && *ssaoNoise)) { - renderInterface.rendered.setValue(false); + renderInterface.updateRenderTargetOutputs(); + return; } // Get viewport - glm::vec4 viewport = *renderInterface.deviceViewport; + const glm::vec4 & viewport = *renderInterface.viewport; // Update viewport gl::glViewport( @@ -96,17 +96,9 @@ void SSAOApplicationStage::onProcess() ); // Bind FBO - globjects::Framebuffer * fbo = *renderInterface.targetFBO; + globjects::Framebuffer * fbo = renderInterface.obtainFBO(); fbo->bind(gl::GL_FRAMEBUFFER); - // Clear background - auto & color = *renderInterface.backgroundColor; - gl::glClearColor(color.redf(), color.greenf(), color.bluef(), 1.0f); - gl::glScissor(viewport.x, viewport.y, viewport.z, viewport.w); - gl::glEnable(gl::GL_SCISSOR_TEST); - gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT); - gl::glDisable(gl::GL_SCISSOR_TEST); - // Set uniforms m_program->setUniform("projectionMatrix", *projectionMatrix); m_program->setUniform("projectionInverseMatrix", glm::inverse(*projectionMatrix)); @@ -135,7 +127,7 @@ void SSAOApplicationStage::onProcess() globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); // Signal that output is valid - renderInterface.rendered.setValue(true); + renderInterface.updateRenderTargetOutputs(); } void SSAOApplicationStage::setupGeometry() diff --git a/source/examples/demo-stages-plugins/SSAOApplicationStage.h b/source/examples/demo-stages-plugins/SSAOApplicationStage.h index c33c8883..32614d4d 100644 --- a/source/examples/demo-stages-plugins/SSAOApplicationStage.h +++ b/source/examples/demo-stages-plugins/SSAOApplicationStage.h @@ -51,8 +51,6 @@ class SSAOApplicationStage : public gloperate::Stage Input projectionMatrix; ///< Projection matrix used for rendering the scene Input normalMatrix; ///< Normal matrix from scene rendering - Input sceneRendered; ///< Scene rendering stage processed? - public: /** diff --git a/source/examples/demo-stages-plugins/SSAORenderingPipeline.cpp b/source/examples/demo-stages-plugins/SSAORenderingPipeline.cpp index 04f96dc0..03dcbbcb 100644 --- a/source/examples/demo-stages-plugins/SSAORenderingPipeline.cpp +++ b/source/examples/demo-stages-plugins/SSAORenderingPipeline.cpp @@ -2,8 +2,8 @@ #include "SSAORenderingPipeline.h" #include -#include -#include +#include +#include #include #include @@ -19,38 +19,35 @@ CPPEXPOSE_COMPONENT(SSAORenderingPipeline, gloperate::Stage) SSAORenderingPipeline::SSAORenderingPipeline(gloperate::Environment * environment, const std::string & name) : Pipeline(environment, name) -, renderInterface(this) -, m_colorTextureStage(cppassist::make_unique(environment, "ColorTextureStage")) -, m_depthTextureStage(cppassist::make_unique(environment, "DepthTextureStage")) -, m_normalTextureStage(cppassist::make_unique(environment, "NormalTextureStage")) -, m_fboStage(cppassist::make_unique(environment)) +, canvasInterface(this) +, m_colorTextureStage(cppassist::make_unique(environment, "ColorTextureStage")) +, m_depthTextureStage(cppassist::make_unique(environment, "DepthTextureStage")) +, m_normalTextureStage(cppassist::make_unique(environment, "NormalTextureStage")) , m_kernelStage(cppassist::make_unique(environment)) , m_noiseStage(cppassist::make_unique(environment)) , m_renderingStage(cppassist::make_unique(environment)) +, m_colorTextureExtractionStage(cppassist::make_unique(environment)) +, m_depthTextureExtractionStage(cppassist::make_unique(environment)) +, m_normalTextureExtractionStage(cppassist::make_unique(environment)) , m_postprocessingStage(cppassist::make_unique(environment)) { addStage(m_colorTextureStage.get()); m_colorTextureStage->format.setValue(gl::GL_RGBA); m_colorTextureStage->type.setValue(gl::GL_UNSIGNED_BYTE); m_colorTextureStage->internalFormat.setValue(gl::GL_RGBA8); - m_colorTextureStage->size << renderInterface.deviceViewport; + m_colorTextureStage->size << canvasInterface.viewport; addStage(m_depthTextureStage.get()); m_depthTextureStage->format.setValue(gl::GL_DEPTH_COMPONENT); m_depthTextureStage->type.setValue(gl::GL_UNSIGNED_BYTE); m_depthTextureStage->internalFormat.setValue(gl::GL_DEPTH_COMPONENT); - m_depthTextureStage->size << renderInterface.deviceViewport; + m_depthTextureStage->size << canvasInterface.viewport; addStage(m_normalTextureStage.get()); m_normalTextureStage->format.setValue(gl::GL_RGB); m_normalTextureStage->type.setValue(gl::GL_UNSIGNED_BYTE); m_normalTextureStage->internalFormat.setValue(gl::GL_RGB8); - m_normalTextureStage->size << renderInterface.deviceViewport; - - addStage(m_fboStage.get()); - m_fboStage->colorTexture << m_colorTextureStage->renderTarget; - m_fboStage->depthTexture << m_depthTextureStage->renderTarget; - *(m_fboStage->createInput("Normal Texture")) << m_normalTextureStage->renderTarget; + m_normalTextureStage->size << canvasInterface.viewport; addStage(m_kernelStage.get()); m_kernelStage->kernelSize.setValue(16); @@ -59,30 +56,35 @@ SSAORenderingPipeline::SSAORenderingPipeline(gloperate::Environment * environmen m_noiseStage->dimensions.setValue(glm::ivec3(128, 128, 1)); addStage(m_renderingStage.get()); - m_renderingStage->renderInterface.backgroundColor << renderInterface.backgroundColor; - m_renderingStage->renderInterface.deviceViewport << renderInterface.deviceViewport; - m_renderingStage->renderInterface.virtualViewport << renderInterface.virtualViewport; - m_renderingStage->renderInterface.frameCounter << renderInterface.frameCounter; - m_renderingStage->renderInterface.timeDelta << renderInterface.timeDelta; - m_renderingStage->renderInterface.targetFBO << m_fboStage->fbo; + m_renderingStage->canvasInterface.backgroundColor << canvasInterface.backgroundColor; + m_renderingStage->canvasInterface.viewport << canvasInterface.viewport; + m_renderingStage->canvasInterface.frameCounter << canvasInterface.frameCounter; + m_renderingStage->canvasInterface.timeDelta << canvasInterface.timeDelta; + m_renderingStage->createInput("Color") << m_colorTextureStage->colorRenderTarget; + m_renderingStage->createInput("Normal") << m_normalTextureStage->colorRenderTarget; + m_renderingStage->createInput("Depth") << m_depthTextureStage->depthRenderTarget; + + addStage(m_colorTextureExtractionStage.get()); + m_colorTextureExtractionStage->colorRenderTarget << *m_renderingStage->createOutput("ColorOut"); + + addStage(m_depthTextureExtractionStage.get()); + m_depthTextureExtractionStage->depthRenderTarget << *m_renderingStage->createOutput("DepthOut"); + + addStage(m_normalTextureExtractionStage.get()); + m_normalTextureExtractionStage->colorRenderTarget << *m_renderingStage->createOutput("NormalOut"); addStage(m_postprocessingStage.get()); - m_postprocessingStage->renderInterface.backgroundColor << renderInterface.backgroundColor; - m_postprocessingStage->renderInterface.deviceViewport << renderInterface.deviceViewport; - m_postprocessingStage->renderInterface.virtualViewport << renderInterface.virtualViewport; - m_postprocessingStage->renderInterface.frameCounter << renderInterface.frameCounter; - m_postprocessingStage->renderInterface.targetFBO << renderInterface.targetFBO; - m_postprocessingStage->renderInterface.timeDelta << renderInterface.timeDelta; - m_postprocessingStage->colorTexture << m_colorTextureStage->texture; - m_postprocessingStage->normalTexture << m_normalTextureStage->texture; - m_postprocessingStage->depthTexture << m_depthTextureStage->texture; + m_postprocessingStage->renderInterface.viewport << canvasInterface.viewport; + m_postprocessingStage->colorTexture << m_colorTextureExtractionStage->texture; + m_postprocessingStage->normalTexture << m_normalTextureExtractionStage->texture; + m_postprocessingStage->depthTexture << m_depthTextureExtractionStage->texture; m_postprocessingStage->ssaoKernel << m_kernelStage->texture; m_postprocessingStage->ssaoNoise << m_noiseStage->texture; m_postprocessingStage->projectionMatrix << m_renderingStage->projectionMatrix; m_postprocessingStage->normalMatrix << m_renderingStage->normalMatrix; - m_postprocessingStage->sceneRendered << m_renderingStage->renderInterface.rendered; + m_postprocessingStage->createInput("Color") << *createInput("Color"); - renderInterface.rendered << m_postprocessingStage->renderInterface.rendered; + *createOutput("ColorOut") << *m_postprocessingStage->createOutput("ColorOut"); } SSAORenderingPipeline::~SSAORenderingPipeline() diff --git a/source/examples/demo-stages-plugins/SSAORenderingPipeline.h b/source/examples/demo-stages-plugins/SSAORenderingPipeline.h index 510e32a8..b4357f76 100644 --- a/source/examples/demo-stages-plugins/SSAORenderingPipeline.h +++ b/source/examples/demo-stages-plugins/SSAORenderingPipeline.h @@ -6,7 +6,14 @@ #include #include -#include +#include + + +namespace gloperate +{ + class TextureRenderTargetStage; + class TextureFromRenderTargetExtractionStage; +} namespace gloperate_glkernel @@ -15,11 +22,6 @@ namespace gloperate_glkernel class NoiseKernelStage; } -namespace gloperate -{ - class FramebufferStage; - class TextureStage; -} class SSAOSceneRenderingStage; class SSAOApplicationStage; @@ -45,7 +47,7 @@ class SSAORenderingPipeline : public gloperate::Pipeline public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer public: @@ -69,12 +71,14 @@ class SSAORenderingPipeline : public gloperate::Pipeline protected: // Stages - std::unique_ptr m_colorTextureStage; ///< Stage creating color texture for main rendering - std::unique_ptr m_depthTextureStage; ///< Stage creating depth texture for main rendering - std::unique_ptr m_normalTextureStage; ///< Stage creating normal texture for main rendering - std::unique_ptr m_fboStage; ///< Stage creating FBO for main rendering + std::unique_ptr m_colorTextureStage; ///< Stage creating color texture for main rendering + std::unique_ptr m_depthTextureStage; ///< Stage creating depth texture for main rendering + std::unique_ptr m_normalTextureStage; ///< Stage creating normal texture for main rendering std::unique_ptr m_kernelStage; ///< Stage generating SSAO kernel std::unique_ptr m_noiseStage; ///< Stage generating SSAO noise std::unique_ptr m_renderingStage; ///< Rendering stage + std::unique_ptr m_colorTextureExtractionStage; + std::unique_ptr m_depthTextureExtractionStage; + std::unique_ptr m_normalTextureExtractionStage; std::unique_ptr m_postprocessingStage; ///< Postprocessing stage (SSAO applied here) }; diff --git a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp index 5e801396..f77395f7 100644 --- a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp +++ b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp @@ -44,7 +44,7 @@ CPPEXPOSE_COMPONENT(SSAOSceneRenderingStage, gloperate::Stage) SSAOSceneRenderingStage::SSAOSceneRenderingStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, name) -, renderInterface(this) +, canvasInterface(this) , projectionMatrix("projectionMatrix", this) , normalMatrix("normalMatrix", this) { @@ -75,7 +75,7 @@ void SSAOSceneRenderingStage::onContextDeinit(gloperate::AbstractGLContext *) void SSAOSceneRenderingStage::onProcess() { // Get viewport - glm::vec4 viewport = *renderInterface.deviceViewport; + const glm::vec4 & viewport = *canvasInterface.viewport; // Update viewport gl::glViewport( @@ -96,11 +96,11 @@ void SSAOSceneRenderingStage::onProcess() m_program->setUniform("viewProjectionMatrix", viewProjectionMatrix); // Bind color FBO - globjects::Framebuffer * fbo = *renderInterface.targetFBO; + globjects::Framebuffer * fbo = canvasInterface.obtainFBO(); fbo->bind(gl::GL_FRAMEBUFFER); // Clear background - auto & color = *renderInterface.backgroundColor; + const auto & color = *canvasInterface.backgroundColor; gl::glClearColor(color.redf(), color.greenf(), color.bluef(), 1.0f); gl::glScissor(viewport.x, viewport.y, viewport.z, viewport.w); gl::glEnable(gl::GL_SCISSOR_TEST); @@ -117,7 +117,7 @@ void SSAOSceneRenderingStage::onProcess() globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); // Signal that output is valid - renderInterface.rendered.setValue(true); + canvasInterface.updateRenderTargetOutputs(); } void SSAOSceneRenderingStage::setupGeometry() diff --git a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.h b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.h index 0cdbf114..673c8139 100644 --- a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.h +++ b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.h @@ -12,7 +12,7 @@ #include #include -#include +#include /** @@ -35,7 +35,7 @@ class SSAOSceneRenderingStage : public gloperate::Stage public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Outputs Output projectionMatrix; ///< Projection matrix used for rendering diff --git a/source/examples/demo-stages-plugins/ShaderDemoPipeline.cpp b/source/examples/demo-stages-plugins/ShaderDemoPipeline.cpp index 6cb92e7b..8c91c784 100644 --- a/source/examples/demo-stages-plugins/ShaderDemoPipeline.cpp +++ b/source/examples/demo-stages-plugins/ShaderDemoPipeline.cpp @@ -20,7 +20,7 @@ CPPEXPOSE_COMPONENT(ShaderDemoPipeline, gloperate::Stage) ShaderDemoPipeline::ShaderDemoPipeline(gloperate::Environment * environment, const std::string & name) : Pipeline(environment, name) -, renderInterface(this) +, canvasInterface(this) , shader1("shader1", this) , shader2("shader2", this) , texture("texture", this) @@ -57,7 +57,7 @@ ShaderDemoPipeline::ShaderDemoPipeline(gloperate::Environment * environment, con // Framebuffer stage addStage(m_framebufferStage.get()); - m_framebufferStage->viewport << renderInterface.deviceViewport; + m_framebufferStage->viewport << canvasInterface.viewport; // Demo drawable stage (supplies demo drawable) addStage(m_demoDrawableStage.get()); @@ -73,21 +73,20 @@ ShaderDemoPipeline::ShaderDemoPipeline(gloperate::Environment * environment, con // Rasterization stage addStage(m_rasterizationStage.get()); - m_rasterizationStage->renderInterface.targetFBO << m_framebufferStage->fbo; - m_rasterizationStage->renderInterface.deviceViewport << renderInterface.deviceViewport; - m_rasterizationStage->renderInterface.backgroundColor << renderInterface.backgroundColor; + m_rasterizationStage->renderInterface.viewport << canvasInterface.viewport; m_rasterizationStage->drawable << m_renderPassStage->renderPass; - m_rasterizationStage->colorTexture << m_framebufferStage->colorTexture; + m_rasterizationStage->createInput("Color") << m_framebufferStage->colorBuffer; + m_rasterizationStage->createInput("Depth") << m_framebufferStage->depthBuffer; // Blit stage addStage(m_blitStage.get()); - m_blitStage->sourceFBO << m_rasterizationStage->fboOut; - m_blitStage->sourceViewport << renderInterface.deviceViewport; - m_blitStage->targetFBO << renderInterface.targetFBO; - m_blitStage->targetViewport << renderInterface.deviceViewport; + m_blitStage->source << *m_rasterizationStage->createOutput("ColorOut"); + m_blitStage->sourceViewport << canvasInterface.viewport; + m_blitStage->target << *createInput("Color"); + m_blitStage->targetViewport << canvasInterface.viewport; // Outputs - renderInterface.rendered << m_blitStage->rendered; + *createOutput("ColorOut") << *m_blitStage->createOutput("ColorOut"); } ShaderDemoPipeline::~ShaderDemoPipeline() diff --git a/source/examples/demo-stages-plugins/ShaderDemoPipeline.h b/source/examples/demo-stages-plugins/ShaderDemoPipeline.h index a1d09923..74f2f737 100644 --- a/source/examples/demo-stages-plugins/ShaderDemoPipeline.h +++ b/source/examples/demo-stages-plugins/ShaderDemoPipeline.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include namespace gloperate @@ -22,6 +22,7 @@ namespace gloperate class BlitStage; } + class DemoDrawableStage; @@ -45,13 +46,14 @@ class ShaderDemoPipeline : public gloperate::Pipeline public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs - Input shader1; ///< Shader 1 filename - Input shader2; ///< Shader 2 filename + Input shader1; ///< Shader 1 filename + Input shader2; ///< Shader 2 filename + + Input texture; ///< Texture filename - Input texture; ///< Texture filename public: /** @@ -71,19 +73,20 @@ class ShaderDemoPipeline : public gloperate::Pipeline */ virtual ~ShaderDemoPipeline(); + protected: // Stages - std::unique_ptr m_textureLoadStage; ///< Stage that loads a static picture + std::unique_ptr m_textureLoadStage; ///< Stage that loads a static picture - std::unique_ptr m_shaderStage; ///< Stage which loads one shader + std::unique_ptr m_shaderStage; ///< Stage which loads one shader - std::unique_ptr m_programStage; ///< Stage which creates the program + std::unique_ptr m_programStage; ///< Stage which creates the program - std::unique_ptr m_framebufferStage; ///< Stage which creates the framebuffer - std::unique_ptr m_demoDrawableStage; ///< Stage which creates the drawable + std::unique_ptr m_framebufferStage; ///< Stage which creates the framebuffer + std::unique_ptr m_demoDrawableStage; ///< Stage which creates the drawable - std::unique_ptr m_renderPassStage; ///< Stage which creates the render pass - std::unique_ptr m_rasterizationStage; ///< Stage which renders the scene + std::unique_ptr m_renderPassStage; ///< Stage which creates the render pass + std::unique_ptr m_rasterizationStage; ///< Stage which renders the scene - std::unique_ptr m_blitStage; ///< Stage that renders the output to the screen + std::unique_ptr m_blitStage; ///< Stage that renders the output to the screen }; diff --git a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp index 92e71cd3..061e88b2 100644 --- a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp +++ b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp @@ -13,7 +13,7 @@ CPPEXPOSE_COMPONENT(TransparencyRenderingPipeline, gloperate::Stage) TransparencyRenderingPipeline::TransparencyRenderingPipeline(gloperate::Environment * environment, const std::string & name) : Pipeline(environment, name) -, renderInterface(this) +, canvasInterface(this) , m_transparencyKernelStage(cppassist::make_unique(environment)) , m_noiseKernelStage(cppassist::make_unique(environment)) , m_transparencyRenderStage(cppassist::make_unique(environment)) @@ -25,16 +25,15 @@ TransparencyRenderingPipeline::TransparencyRenderingPipeline(gloperate::Environm m_noiseKernelStage->dimensions.setValue(glm::ivec3(64, 64, 64)); addStage(m_transparencyRenderStage.get()); - m_transparencyRenderStage->renderInterface.backgroundColor << renderInterface.backgroundColor; - m_transparencyRenderStage->renderInterface.deviceViewport << renderInterface.deviceViewport; - m_transparencyRenderStage->renderInterface.frameCounter << renderInterface.frameCounter; - m_transparencyRenderStage->renderInterface.targetFBO << renderInterface.targetFBO; - m_transparencyRenderStage->renderInterface.timeDelta << renderInterface.timeDelta; - m_transparencyRenderStage->renderInterface.virtualViewport << renderInterface.virtualViewport; + m_transparencyRenderStage->canvasInterface.backgroundColor << canvasInterface.backgroundColor; + m_transparencyRenderStage->canvasInterface.viewport << canvasInterface.viewport; + m_transparencyRenderStage->canvasInterface.frameCounter << canvasInterface.frameCounter; + m_transparencyRenderStage->canvasInterface.timeDelta << canvasInterface.timeDelta; m_transparencyRenderStage->transparencyKernel << m_transparencyKernelStage->texture; m_transparencyRenderStage->noiseKernel << m_noiseKernelStage->texture; + m_transparencyKernelStage->createInput("Color") << *createInput("Color"); - renderInterface.rendered << m_transparencyRenderStage->renderInterface.rendered; + *createOutput("ColorOut") << *m_transparencyRenderStage->createOutput("ColorOut"); } TransparencyRenderingPipeline::~TransparencyRenderingPipeline() diff --git a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.h b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.h index 1cb6d5c2..68a63c88 100644 --- a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.h +++ b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.h @@ -6,7 +6,7 @@ #include #include -#include +#include namespace gloperate_glkernel { @@ -38,7 +38,7 @@ class TransparencyRenderingPipeline : public gloperate::Pipeline public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer public: diff --git a/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp b/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp index 54d73ebf..966bfb33 100644 --- a/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp +++ b/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp @@ -38,7 +38,7 @@ CPPEXPOSE_COMPONENT(TransparentCirclesStage, gloperate::Stage) TransparentCirclesStage::TransparentCirclesStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, name) -, renderInterface(this) +, canvasInterface(this) , transparencyKernel("transparencyKernel", this, nullptr) , noiseKernel("noiseKernel", this, nullptr) { @@ -69,7 +69,7 @@ void TransparentCirclesStage::onContextDeinit(gloperate::AbstractGLContext *) void TransparentCirclesStage::onProcess() { // Get viewport - glm::vec4 viewport = *renderInterface.deviceViewport; + const glm::vec4 & viewport = *canvasInterface.viewport; // Update viewport gl::glViewport( @@ -80,11 +80,11 @@ void TransparentCirclesStage::onProcess() ); // Bind FBO - globjects::Framebuffer * fbo = *renderInterface.targetFBO; + globjects::Framebuffer * fbo = canvasInterface.obtainFBO(); fbo->bind(gl::GL_FRAMEBUFFER); // Clear background - auto & color = *renderInterface.backgroundColor; + auto & color = *canvasInterface.backgroundColor; gl::glClearColor(color.redf(), color.greenf(), color.bluef(), 1.0f); gl::glScissor(viewport.x, viewport.y, viewport.z, viewport.w); gl::glEnable(gl::GL_SCISSOR_TEST); @@ -152,7 +152,7 @@ void TransparentCirclesStage::onProcess() globjects::Framebuffer::unbind(gl::GL_FRAMEBUFFER); // Signal that output is valid - renderInterface.rendered.setValue(true); + canvasInterface.updateRenderTargetOutputs(); } void TransparentCirclesStage::setupGeometry() diff --git a/source/examples/demo-stages-plugins/TransparentCirclesStage.h b/source/examples/demo-stages-plugins/TransparentCirclesStage.h index 59aa91b0..d0adcbc9 100644 --- a/source/examples/demo-stages-plugins/TransparentCirclesStage.h +++ b/source/examples/demo-stages-plugins/TransparentCirclesStage.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include @@ -37,7 +37,7 @@ class TransparentCirclesStage : public gloperate::Stage public: // Interfaces - gloperate::RenderInterface renderInterface; ///< Interface for rendering into a viewer + gloperate::CanvasInterface canvasInterface; ///< Interface for rendering into a viewer // Inputs Input transparencyKernel; ///< Transparency kernel for multiframe rendering diff --git a/source/gloperate-glfw/include/gloperate-glfw/Window.h b/source/gloperate-glfw/include/gloperate-glfw/Window.h index 3878d297..734614df 100644 --- a/source/gloperate-glfw/include/gloperate-glfw/Window.h +++ b/source/gloperate-glfw/include/gloperate-glfw/Window.h @@ -236,7 +236,9 @@ class GLOPERATE_GLFW_API Window * Value of input mode * * @notes - * - [TODO] What modes and values are supported here?? + * Possible values include GLFW_CURSOR, GLFW_STICKY_KEYS, + * or GLFW_STICKY_MOUSE_BUTTONS. For more information, + * refer to GLFW docs to glfwGetInputMode. */ int inputMode(int mode) const; @@ -250,7 +252,9 @@ class GLOPERATE_GLFW_API Window * Input mode value * * @notes - * - [TODO] What modes and values are supported here?? + * Possible values include GLFW_CURSOR, GLFW_STICKY_KEYS, + * or GLFW_STICKY_MOUSE_BUTTONS. For more information, + * refer to GLFW docs to glfwGetInputMode. */ void setInputMode(int mode, int value); diff --git a/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h b/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h index 549367c8..e11c3526 100644 --- a/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h +++ b/source/gloperate/include/gloperate/stages/base/TextureFromRenderTargetExtractionStage.h @@ -22,7 +22,11 @@ namespace gloperate { +class AbstractRenderTarget; class ColorRenderTarget; +class DepthRenderTarget; +class StencilRenderTarget; +class DepthStencilRenderTarget; /** @@ -45,7 +49,10 @@ class GLOPERATE_API TextureFromRenderTargetExtractionStage : public gloperate::S public: // Inputs - Input colorRenderTarget; ///< Color render target + Input colorRenderTarget; ///< Color render target + Input depthRenderTarget; ///< Depth render target + Input stencilRenderTarget; ///< Stencil render target + Input depthStencilRenderTarget; ///< Depth stencil render target // Outputs Output texture; ///< Internal texture of render target @@ -73,6 +80,12 @@ class GLOPERATE_API TextureFromRenderTargetExtractionStage : public gloperate::S protected: // Virtual Stage interface virtual void onProcess() override; + + /** + * @brief + * Extract texture from RenderTarget and update output + */ + void extractTexture(AbstractRenderTarget * renderTarget); }; diff --git a/source/gloperate/source/loaders/ShaderLoader.cpp b/source/gloperate/source/loaders/ShaderLoader.cpp index 094e83fe..39acce07 100644 --- a/source/gloperate/source/loaders/ShaderLoader.cpp +++ b/source/gloperate/source/loaders/ShaderLoader.cpp @@ -81,7 +81,7 @@ globjects::Shader * ShaderLoader::load(const std::string & filename, const cppex auto it = m_extensionToType.find(cppassist::FilePath(filename).extension()); - // [TODO] Is this file a memory leak? + // [TODO] Remove file memory leak globjects::File * file = new globjects::File(filename, false); if (it == m_extensionToType.end() || file->string().empty()) { diff --git a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp index dd6e8b25..b0dfb8e2 100644 --- a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp +++ b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp @@ -4,6 +4,9 @@ #include #include +#include +#include +#include namespace gloperate @@ -16,6 +19,9 @@ CPPEXPOSE_COMPONENT(TextureFromRenderTargetExtractionStage, gloperate::Stage) TextureFromRenderTargetExtractionStage::TextureFromRenderTargetExtractionStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, "TextureFromRenderTargetExtractionStage", name) , colorRenderTarget("colorRenderTarget", this) +, depthRenderTarget("depthRenderTarget", this) +, stencilRenderTarget("stencilRenderTarget", this) +, depthStencilRenderTarget("depthStencilRenderTarget", this) , texture("texture", this) { } @@ -26,14 +32,32 @@ TextureFromRenderTargetExtractionStage::~TextureFromRenderTargetExtractionStage( void TextureFromRenderTargetExtractionStage::onProcess() { - if (*colorRenderTarget == nullptr) + if (*colorRenderTarget) { - texture.setValue(nullptr); + return extractTexture(*colorRenderTarget); + } + + if (*depthRenderTarget) + { + return extractTexture(*depthRenderTarget); + } + + if (*stencilRenderTarget) + { + return extractTexture(*stencilRenderTarget); + } - return; + if (*depthStencilRenderTarget) + { + return extractTexture(*depthStencilRenderTarget); } - switch (colorRenderTarget->currentTargetType()) + texture.setValue(nullptr); +} + +void TextureFromRenderTargetExtractionStage::extractTexture(AbstractRenderTarget * renderTarget) +{ + switch (renderTarget->currentTargetType()) { case RenderTargetType::Texture: texture.setValue(colorRenderTarget->textureAttachment()); From 07584191510edce283c14d9d06a9591cf6b5a440 Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 5 Jul 2017 00:10:47 +0200 Subject: [PATCH 33/33] Non-crashing demo plugins --- data/gloperate/qml/Viewer.qml | 2 -- .../AntialiasableTriangleStage.cpp | 3 +++ .../AntialiasableTriangleStage.h | 1 - .../examples/demo-stages-plugins/DOFCubeStage.cpp | 2 ++ .../DemoTextRenderingPipeline.cpp | 4 ++-- .../demo-stages-plugins/LightTestPipeline.cpp | 1 + .../examples/demo-stages-plugins/LightTestStage.cpp | 5 +++-- .../MultiFramePostprocessingStage.cpp | 5 +++-- .../MultiFrameSceneRenderingStage.cpp | 3 +++ .../demo-stages-plugins/SSAOApplicationStage.cpp | 5 +++-- .../demo-stages-plugins/SSAOSceneRenderingStage.cpp | 3 +++ .../TransparencyRenderingPipeline.cpp | 2 +- .../demo-stages-plugins/TransparentCirclesStage.cpp | 3 +++ .../gloperate-text/stages/GlyphRenderStage.h | 7 +++---- .../source/stages/GlyphRenderStage.cpp | 13 +++++++------ .../base/TextureFromRenderTargetExtractionStage.cpp | 4 ++-- 16 files changed, 39 insertions(+), 24 deletions(-) diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index 9a03c84a..70c3d1c0 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -436,8 +436,6 @@ ApplicationWindow // Load settings settings.load(); } - - gloperate.components.scanPlugins(); // Scan for plugins gloperate.components.scanPlugins(); diff --git a/source/examples/demo-stages-plugins/AntialiasableTriangleStage.cpp b/source/examples/demo-stages-plugins/AntialiasableTriangleStage.cpp index c7cdcfc6..17e6b66b 100644 --- a/source/examples/demo-stages-plugins/AntialiasableTriangleStage.cpp +++ b/source/examples/demo-stages-plugins/AntialiasableTriangleStage.cpp @@ -40,6 +40,7 @@ AntialiasableTriangleStage::~AntialiasableTriangleStage() void AntialiasableTriangleStage::onContextInit(gloperate::AbstractGLContext *) { + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); } @@ -54,6 +55,8 @@ void AntialiasableTriangleStage::onContextDeinit(gloperate::AbstractGLContext *) // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + canvasInterface.onContextDeinit(); } void AntialiasableTriangleStage::onProcess() diff --git a/source/examples/demo-stages-plugins/AntialiasableTriangleStage.h b/source/examples/demo-stages-plugins/AntialiasableTriangleStage.h index dd6f91fc..ee228aae 100644 --- a/source/examples/demo-stages-plugins/AntialiasableTriangleStage.h +++ b/source/examples/demo-stages-plugins/AntialiasableTriangleStage.h @@ -66,7 +66,6 @@ class AntialiasableTriangleStage : public gloperate::Stage virtual void onContextInit(gloperate::AbstractGLContext * context) override; virtual void onContextDeinit(gloperate::AbstractGLContext * context) override; virtual void onProcess() override; - virtual void onInputValueChanged(gloperate::AbstractSlot * slot) override; // Helper functions void setupGeometry(); diff --git a/source/examples/demo-stages-plugins/DOFCubeStage.cpp b/source/examples/demo-stages-plugins/DOFCubeStage.cpp index 11afe938..744ffaee 100644 --- a/source/examples/demo-stages-plugins/DOFCubeStage.cpp +++ b/source/examples/demo-stages-plugins/DOFCubeStage.cpp @@ -59,6 +59,7 @@ DOFCubeStage::~DOFCubeStage() void DOFCubeStage::onContextInit(gloperate::AbstractGLContext *) { + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); } @@ -69,6 +70,7 @@ void DOFCubeStage::onContextDeinit(gloperate::AbstractGLContext *) m_program.reset(); m_fragmentShader.reset(); m_vertexShader.reset(); + canvasInterface.onContextDeinit(); // deinitialize geometry m_vertexBuffer.reset(); diff --git a/source/examples/demo-stages-plugins/DemoTextRenderingPipeline.cpp b/source/examples/demo-stages-plugins/DemoTextRenderingPipeline.cpp index f216e1ec..a20577e8 100644 --- a/source/examples/demo-stages-plugins/DemoTextRenderingPipeline.cpp +++ b/source/examples/demo-stages-plugins/DemoTextRenderingPipeline.cpp @@ -64,8 +64,8 @@ DemoTextRenderingPipeline::DemoTextRenderingPipeline(gloperate::Environment * en glyphPreparation->optimized << optimized; auto glyphRendering = cppassist::make_unique(environment, "GlyphRendering"); - glyphRendering->vertexCloud << glyphPreparation->vertexCloud; - glyphRendering->viewport << renderInterface.viewport; + glyphRendering->vertexCloud << glyphPreparation->vertexCloud; + glyphRendering->renderInterface.viewport << renderInterface.viewport; glyphRendering->createInput("Color") << *createInput("Color"); *createOutput("ColorOut") << *glyphRendering->createOutput("ColorOut"); diff --git a/source/examples/demo-stages-plugins/LightTestPipeline.cpp b/source/examples/demo-stages-plugins/LightTestPipeline.cpp index 15a83f90..85f07796 100644 --- a/source/examples/demo-stages-plugins/LightTestPipeline.cpp +++ b/source/examples/demo-stages-plugins/LightTestPipeline.cpp @@ -84,6 +84,7 @@ LightTestPipeline::LightTestPipeline(gloperate::Environment * environment, const m_renderStage->canvasInterface.frameCounter << canvasInterface.frameCounter; m_renderStage->canvasInterface.timeDelta << canvasInterface.timeDelta; m_renderStage->createInput("Color") << *createInput("Color"); + //m_renderStage->createInput("Depth") << *createInput("Depth"); // TODO: fix depth m_renderStage->lightColorTypeData << m_lightAccumulationStage->colorTypeData; m_renderStage->lightPositionData << m_lightAccumulationStage->positionData; m_renderStage->lightAttenuationData << m_lightAccumulationStage->attenuationData; diff --git a/source/examples/demo-stages-plugins/LightTestStage.cpp b/source/examples/demo-stages-plugins/LightTestStage.cpp index bb7a0549..410ec3c2 100644 --- a/source/examples/demo-stages-plugins/LightTestStage.cpp +++ b/source/examples/demo-stages-plugins/LightTestStage.cpp @@ -66,8 +66,7 @@ LightTestStage::~LightTestStage() void LightTestStage::onContextInit(gloperate::AbstractGLContext *) { - if (m_vao) // protect against initializing twice - return; + canvasInterface.onContextInit(); // Setup Geometry m_vao = cppassist::make_unique(); @@ -121,6 +120,8 @@ void LightTestStage::onContextDeinit(gloperate::AbstractGLContext *) // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + canvasInterface.onContextDeinit(); } void LightTestStage::onProcess() diff --git a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp index 58fbceba..bb02ae0e 100644 --- a/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp +++ b/source/examples/demo-stages-plugins/MultiFramePostprocessingStage.cpp @@ -55,8 +55,7 @@ MultiFramePostprocessingStage::~MultiFramePostprocessingStage() void MultiFramePostprocessingStage::onContextInit(gloperate::AbstractGLContext *) { - if (m_vao) // protect against initializing twice - return; + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); @@ -73,6 +72,8 @@ void MultiFramePostprocessingStage::onContextDeinit(gloperate::AbstractGLContext // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + canvasInterface.onContextDeinit(); } void MultiFramePostprocessingStage::onProcess() diff --git a/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp b/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp index 5f7244d7..ae0ce0dc 100644 --- a/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp +++ b/source/examples/demo-stages-plugins/MultiFrameSceneRenderingStage.cpp @@ -41,6 +41,7 @@ MultiFrameSceneRenderingStage::~MultiFrameSceneRenderingStage() void MultiFrameSceneRenderingStage::onContextInit(gloperate::AbstractGLContext *) { + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); } @@ -60,6 +61,8 @@ void MultiFrameSceneRenderingStage::onContextDeinit(gloperate::AbstractGLContext } m_drawable.reset(); } + + canvasInterface.onContextDeinit(); } void MultiFrameSceneRenderingStage::onProcess() diff --git a/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp b/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp index a399f811..c8bc7022 100644 --- a/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp +++ b/source/examples/demo-stages-plugins/SSAOApplicationStage.cpp @@ -55,8 +55,7 @@ SSAOApplicationStage::~SSAOApplicationStage() void SSAOApplicationStage::onContextInit(gloperate::AbstractGLContext *) { - if (m_vao) // protect against initializing twice - return; + renderInterface.onContextInit(); setupGeometry(); setupProgram(); @@ -73,6 +72,8 @@ void SSAOApplicationStage::onContextDeinit(gloperate::AbstractGLContext *) // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + renderInterface.onContextDeinit(); } void SSAOApplicationStage::onProcess() diff --git a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp index f77395f7..1333be9b 100644 --- a/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp +++ b/source/examples/demo-stages-plugins/SSAOSceneRenderingStage.cpp @@ -56,6 +56,7 @@ SSAOSceneRenderingStage::~SSAOSceneRenderingStage() void SSAOSceneRenderingStage::onContextInit(gloperate::AbstractGLContext *) { + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); } @@ -70,6 +71,8 @@ void SSAOSceneRenderingStage::onContextDeinit(gloperate::AbstractGLContext *) // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + canvasInterface.onContextDeinit(); } void SSAOSceneRenderingStage::onProcess() diff --git a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp index 061e88b2..de442413 100644 --- a/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp +++ b/source/examples/demo-stages-plugins/TransparencyRenderingPipeline.cpp @@ -31,7 +31,7 @@ TransparencyRenderingPipeline::TransparencyRenderingPipeline(gloperate::Environm m_transparencyRenderStage->canvasInterface.timeDelta << canvasInterface.timeDelta; m_transparencyRenderStage->transparencyKernel << m_transparencyKernelStage->texture; m_transparencyRenderStage->noiseKernel << m_noiseKernelStage->texture; - m_transparencyKernelStage->createInput("Color") << *createInput("Color"); + m_transparencyRenderStage->createInput("Color") << *createInput("Color"); *createOutput("ColorOut") << *m_transparencyRenderStage->createOutput("ColorOut"); } diff --git a/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp b/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp index 966bfb33..0dc18f5c 100644 --- a/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp +++ b/source/examples/demo-stages-plugins/TransparentCirclesStage.cpp @@ -50,6 +50,7 @@ TransparentCirclesStage::~TransparentCirclesStage() void TransparentCirclesStage::onContextInit(gloperate::AbstractGLContext *) { + canvasInterface.onContextInit(); setupGeometry(); setupProgram(); } @@ -64,6 +65,8 @@ void TransparentCirclesStage::onContextDeinit(gloperate::AbstractGLContext *) // deinitialize geometry m_vertexBuffer.reset(); m_vao.reset(); + + canvasInterface.onContextDeinit(); } void TransparentCirclesStage::onProcess() diff --git a/source/gloperate-text/include/gloperate-text/stages/GlyphRenderStage.h b/source/gloperate-text/include/gloperate-text/stages/GlyphRenderStage.h index 5f82c3cd..805fa6f2 100644 --- a/source/gloperate-text/include/gloperate-text/stages/GlyphRenderStage.h +++ b/source/gloperate-text/include/gloperate-text/stages/GlyphRenderStage.h @@ -5,6 +5,7 @@ #include #include +#include #include @@ -29,11 +30,9 @@ class GlyphVertexCloud; class GLOPERATE_TEXT_API GlyphRenderStage : public gloperate::Stage { public: - Input vertexCloud; - Input viewport; - Input targetFramebuffer; + gloperate::RenderInterface renderInterface; ///< Interface to render into render targets - Output rendered; + Input vertexCloud; public: diff --git a/source/gloperate-text/source/stages/GlyphRenderStage.cpp b/source/gloperate-text/source/stages/GlyphRenderStage.cpp index 6aba3cf2..11246786 100644 --- a/source/gloperate-text/source/stages/GlyphRenderStage.cpp +++ b/source/gloperate-text/source/stages/GlyphRenderStage.cpp @@ -18,10 +18,8 @@ namespace gloperate_text GlyphRenderStage::GlyphRenderStage(gloperate::Environment * environment, const std::string & name) : Stage(environment, "GlyphRenderStage", name) +, renderInterface(this) , vertexCloud("vertexCloud", this) -, viewport("viewport", this) -, targetFramebuffer("targetFramebuffer", this) -, rendered("rendered", this) { } @@ -31,6 +29,8 @@ GlyphRenderStage::~GlyphRenderStage() void GlyphRenderStage::onContextInit(gloperate::AbstractGLContext *) { + renderInterface.onContextInit(); + m_vSource = GlyphRenderer::vertexShaderSource(); m_gSource = GlyphRenderer::geometryShaderSource(); m_fSource = GlyphRenderer::fragmentShaderSource(); @@ -49,13 +49,14 @@ void GlyphRenderStage::onContextInit(gloperate::AbstractGLContext *) void GlyphRenderStage::onContextDeinit(gloperate::AbstractGLContext *) { + renderInterface.onContextDeinit(); } void GlyphRenderStage::onProcess() { - gl::glViewport(viewport->x, viewport->y, viewport->z, viewport->w); + gl::glViewport(renderInterface.viewport->x, renderInterface.viewport->y, renderInterface.viewport->z, renderInterface.viewport->w); - auto fbo = targetFramebuffer.value(); + auto fbo = renderInterface.obtainFBO(); fbo->bind(); gl::glDepthMask(gl::GL_FALSE); @@ -72,7 +73,7 @@ void GlyphRenderStage::onProcess() fbo->unbind(); - rendered.setValue(true); + renderInterface.updateRenderTargetOutputs(); } diff --git a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp index b0dfb8e2..0c6a1841 100644 --- a/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp +++ b/source/gloperate/source/stages/base/TextureFromRenderTargetExtractionStage.cpp @@ -60,11 +60,11 @@ void TextureFromRenderTargetExtractionStage::extractTexture(AbstractRenderTarget switch (renderTarget->currentTargetType()) { case RenderTargetType::Texture: - texture.setValue(colorRenderTarget->textureAttachment()); + texture.setValue(renderTarget->textureAttachment()); break; case RenderTargetType::UserDefinedFBOAttachment: { - auto attachment = colorRenderTarget->framebufferAttachment()->asTextureAttachment(); + auto attachment = renderTarget->framebufferAttachment()->asTextureAttachment(); texture.setValue(attachment ? attachment->texture() : nullptr); }