diff --git a/src/DemoApp/main.cpp b/src/DemoApp/main.cpp index bdddcfba98bf0f1c7fec82b127b7d0d26c00258d..47090cdc1ce7ecb09ecc0ff459ea44167007b6c7 100644 --- a/src/DemoApp/main.cpp +++ b/src/DemoApp/main.cpp @@ -10,15 +10,12 @@ // Include the customizable renderer system (only the used part here) #include <RadiumNBR/NodeBasedRenderer.hpp> -#include <RadiumNBR/Passes/ClearPass.hpp> -#include <RadiumNBR/Passes/CustomAttribToColorPass.hpp> -#include <RadiumNBR/Passes/GeomPrepass.hpp> +#include <RadiumNBR/Renderer/Visualization.hpp> // To add attribs to loaded objects #include <Engine/Data/Mesh.hpp> #include <Engine/Rendering/RenderObject.hpp> #include <Engine/Rendering/RenderObjectManager.hpp> -#include <Engine/Scene/EntityManager.hpp> #include <Engine/Scene/SystemDisplay.hpp> #include <Core/Utils/Log.hpp> @@ -26,91 +23,24 @@ using namespace Ra::Core::Utils; // log /** * This class parameterize the renderer just after the OpenGL system was initialized. - * when a method of this controler is called, the OpenGL context of the drawing window is activated. + * when a method of this controller is called, the OpenGL context of the drawing window is + * activated. */ -class RendererController : public RadiumNBR::RenderControlFunctor +class RendererController : public RadiumNBR::VisualizationController { public: - /* - * Called once : configure the renderer by adding passes and allocating controler resources - */ void configure( RadiumNBR::NodeBasedRenderer* renderer, int w, int h ) override { - LOG( Ra::Core::Utils::logINFO ) - << "Customizing the renderer " << renderer->getRendererName(); - - //! [Caching some helpers and data from the Engine and the renderer] - auto resourcesCheck = Ra::Core::Resources::getResourcesPath( - reinterpret_cast<void*>( &RadiumNBR::NodeBasedRendererMagic ), - {"Resources/RadiumNBR"} ); - if ( !resourcesCheck ) - { - LOG( Ra::Core::Utils::logERROR ) << "Unable to find resources for NodeBasedRenderer!"; - return; - } - else - { - LOG( Ra::Core::Utils::logINFO ) - << "NodeBasedRenderer Resources are at " << *resourcesCheck; - } - auto resourcesPath{*resourcesCheck}; - auto shaderManager = Ra::Engine::RadiumEngine::getInstance()->getShaderProgramManager(); - auto colortexture = renderer->sharedTextures().find( "Linear RGB (RadiumNBR)" ); - auto depthtexture = renderer->sharedTextures().find( "Depth (RadiumNBR)" ); - //! [Caching some helpers and data from the Engine and the renderer] - - //! [Adding a clear-screen pass] - { - // pass that draw no object and is positioned at rank 0 - auto pass = std::make_shared<RadiumNBR::ClearPass>( nullptr, 0 ); - // set the output of the pass : clear the renderer Linear RGB output texture - pass->setOutput( *colortexture ); - // set the clear color (pass internal state) - pass->setBackground( renderer->getBackgroundColor() ); - pass->initializePass( w, h, shaderManager ); - // add the pass to the renderer and activate it - renderer->addPass( pass, pass->index() ); - pass->activate(); - } - //! [Adding a clear-screen pass] - - //! [Adding a Z-only pass] - { - // the z-only pass takes all the objects and draw them only on the shared depth buffer. - auto pass = std::make_shared<RadiumNBR::GeomPrePass>( renderer->allRenderObjects(), 1 ); - // set the output to the shared depth texture - pass->setOutput( *depthtexture ); - // configure access to shader/resources files and initialize the pass - pass->setResourcesDir( resourcesPath ); - pass->initializePass( w, h, shaderManager ); - // add the pass to the renderer and activate it - renderer->addPass( pass, pass->index() ); - pass->activate(); - } - //! [Adding a Z-only pass] - - //! [Adding a CustomAttribToColorPass pass] - { - // this pass draw all the objects using the custom color function, - // Rendering is done against the shared z-buffer for hidden line removal and - // into the shared color buffer. - m_customPass = std::make_shared<RadiumNBR::CustomAttribToColorPass>( - renderer->allRenderObjects(), 2 ); - // set the input/output textures - m_customPass->setInputs( *depthtexture ); - m_customPass->setOutput( *colortexture ); - m_customPass->setLightManager( renderer->getLightManager() ); - m_customPass->setAttribToColorFunc( m_vertexFunction, m_fragmentFunction ); - // configure access to shader/resources files and initialize the pass - m_customPass->setResourcesDir( resourcesPath ); - m_customPass->initializePass( w, h, shaderManager ); - // add the pass to the renderer and activate it - renderer->addPass( m_customPass, m_customPass->index() ); - m_customPass->activate(); - } - //! [Adding a CustomAttribToColorPass pass] + /* + * Called once : configure the renderer by adding passes and allocating controller resources + */ + RadiumNBR::VisualizationController::configure( renderer, w, h ); + /* add here your specific configure step : + * -- add more passes, allocate resources, ... + */ } - void update( const Ra::Engine::Data::ViewingParameters& ) override{ + void update( const Ra::Engine::Data::ViewingParameters& params ) override { + RadiumNBR::VisualizationController::update( params ); /* This function is called once before each frame. * You can use it to modify the scene, or modify the computation function of the renderer * For this, just call @@ -119,29 +49,12 @@ class RendererController : public RadiumNBR::RenderControlFunctor */ }; - void resize( int w, int h ) override{ + void resize( int w, int h ) override { + RadiumNBR::VisualizationController::resize( w, h ); /* if you have resizeable resources in your controller, this method is called each time the * viewer window is resized so that you can dimension your resources accordingly */ }; - - /// Set the custom glsl function for attrib management (vertex) and colorcomputation (fragment) - void setAttribToColorFunc( const std::string& vertex_source, - const std::string& fragment_source ) { - m_vertexFunction = vertex_source; - m_fragmentFunction = fragment_source; - if ( m_customPass ) - { m_customPass->setAttribToColorFunc( m_vertexFunction, m_fragmentFunction ); } - } - - private: - /// The custom pass if needed for modification - std::shared_ptr<RadiumNBR::CustomAttribToColorPass> m_customPass; - - /// - std::string m_vertexFunction{"void outputCustomAttribs() {}"}; - std::string m_fragmentFunction{"vec4 computeCustomColor(Material mat, vec3 lightDir, vec3 " - "viewDir) {return vec4(1, 0, 0, 1);}"}; }; /** @@ -197,22 +110,19 @@ void AddCustomAttributeToMeshes() { { addAttrib( "myCustomAttrib", Ra::Core::Vector4Array{displayMesh->getNumVertices(), - /*Ra::Core::Utils::Color::White()*/ { - 0.7_ra, 0.8_ra, 0.8_ra, 1_ra}} ); + {0.6_ra, 0.6_ra, 0.7_ra, 1_ra}} ); } else if ( meshTypeHash == typeid( Ra::Engine::Data::PolyMesh ).hash_code() ) { addAttrib( "myCustomAttrib", - Ra::Core::Vector4Array{ - displayMesh->getNumVertices(), - Ra::Core::Utils::Color{0.8_ra, 0.7_ra, 0.8_ra}} ); + Ra::Core::Vector4Array{displayMesh->getNumVertices(), + {0.6_ra, 0.7_ra, 0.6_ra, 1_ra}} ); } else if ( meshTypeHash == typeid( Ra::Engine::Data::PointCloud ).hash_code() ) { addAttrib( "myCustomAttrib", - Ra::Core::Vector4Array{ - displayMesh->getNumVertices(), - Ra::Core::Utils::Color{0.3_ra, 0.3_ra, 0.8_ra}} ); + Ra::Core::Vector4Array{displayMesh->getNumVertices(), + {0.7_ra, 0.6_ra, 0.6_ra, 1_ra}} ); } else { @@ -311,7 +221,7 @@ int main( int argc, char* argv[] ) { //! [Instatiating the renderer giving a customization functor] RendererController renderControl; auto renderer = std::make_shared<RadiumNBR::NodeBasedRenderer>( renderControl ); - + renderControl.setAttribToColorFunc( customVertexAttrib, customFragmentColor ); //! [Instatiating the renderer giving a customization functor] //! [Instatiating the application] diff --git a/src/Mara/RadiumPlayer.cpp b/src/Mara/RadiumPlayer.cpp index 72064268fdb4ddb07082a0a5c0d4fb69538f4f4d..6577cde30bcbe296967f8fbb16cd5ce88cb61bf7 100644 --- a/src/Mara/RadiumPlayer.cpp +++ b/src/Mara/RadiumPlayer.cpp @@ -14,9 +14,11 @@ using namespace Ra::Core::Utils; // for LOG( logLEVEL ) #include <QCommandLineParser> #include <QFileDialog> -#include <RadiumNBR/FullFeatureRenderer.hpp> #include <RadiumNBR/Gui/FullFeaturedRendererGui.hpp> +#include <RadiumNBR/Renderer/FullFeatureRenderer.hpp> +#include <RadiumNBR/Gui/VisualizationGui.hpp> +#include <RadiumNBR/Renderer/Visualization.hpp> #ifdef WITH_H3D_SUPPORT # include <RadiumH3D/h3DLoader.hpp> #endif @@ -141,6 +143,16 @@ void RadiumPlayer::addRenderers() { RadiumNBR::buildRadiumNBRGui( myRenderer.get(), [this]() { this->askForUpdate(); } ); mainWindow->addRenderer( rendererName, myRenderer, controlPanel ); } + // add visualization renderer + { + // TODO, this is a memory leak ... Who's owning the controller + auto renderControl = new RadiumNBR::VisualizationController; + auto myRenderer = std::make_shared<RadiumNBR::NodeBasedRenderer>( *renderControl ); + std::string rendererName = myRenderer->getRendererName(); + auto controlPanel = + RadiumNBR::buildControllerGui( myRenderer.get(), [this]() { this->askForUpdate(); } ); + mainWindow->addRenderer( rendererName, myRenderer, controlPanel ); + } } void RadiumPlayer::addApplicationExtension() { diff --git a/src/libRender/CMakeLists.txt b/src/libRender/CMakeLists.txt index 7853fffb0531828b15d8207ef6b25d1612603caf..7e0f3e8d89dccbc04115b9183835a98a66453ed0 100644 --- a/src/libRender/CMakeLists.txt +++ b/src/libRender/CMakeLists.txt @@ -31,7 +31,8 @@ set(markdowns set(sources RadiumNBR/NodeBasedRenderer.cpp RadiumNBR/EnvMap.cpp - RadiumNBR/FullFeatureRenderer.cpp + RadiumNBR/Renderer/FullFeatureRenderer.cpp + RadiumNBR/Renderer/Visualization.cpp RadiumNBR/SphereSampler.cpp RadiumNBR/Passes/ClearPass.cpp RadiumNBR/Passes/CustomAttribToColorPass.cpp @@ -50,7 +51,8 @@ set(public_headers RadiumNBR/NodeBasedRendererMacro.hpp RadiumNBR/NodeBasedRenderer.hpp RadiumNBR/EnvMap.hpp - RadiumNBR/FullFeatureRenderer.hpp + RadiumNBR/Renderer/FullFeatureRenderer.hpp + RadiumNBR/Renderer/Visualization.hpp RadiumNBR/RenderPass.hpp RadiumNBR/SphereSampler.hpp RadiumNBR/Passes/ClearPass.hpp @@ -131,11 +133,13 @@ set(gui_markdowns set(gui_sources RadiumNBR/Gui/FullFeaturedRendererGui.cpp + RadiumNBR/Gui/VisualizationGui.cpp RadiumNBR/Gui/RendererPanel.cpp ) set(gui_public_headers RadiumNBR/Gui/FullFeaturedRendererGui.hpp + RadiumNBR/Gui/VisualizationGui.hpp RadiumNBR/Gui/RendererPanel.hpp ) diff --git a/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.cpp b/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.cpp index 49fd5b04014777c0b188afb5903df41762c90018..c6b5f631f102362b529e5ce9428c6f2817472e46 100644 --- a/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.cpp +++ b/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.cpp @@ -1,5 +1,5 @@ -#include <RadiumNBR/FullFeatureRenderer.hpp> #include <RadiumNBR/Gui/FullFeaturedRendererGui.hpp> +#include <RadiumNBR/Renderer/FullFeatureRenderer.hpp> namespace RadiumNBR { using namespace Gui; @@ -10,22 +10,21 @@ RadiumNBR::Gui::RendererPanel* buildRadiumNBRGui( FullFeatureRenderer* renderer, auto defColor = Ra::Core::Utils::Color::linearRGBTosRGB( renderer->getBackgroundColor() ); auto clrClbck = [renderer, appUpdateCallback]( const Ra::Core::Utils::Color& clr ) { - // set the background color for all passes that need it - renderer->setBackgroundColor( clr ); - appUpdateCallback(); + // set the background color for all passes that need it + renderer->setBackgroundColor( clr ); + appUpdateCallback(); }; controlPanel->addColorInput( "Background Color", clrClbck, defColor ); controlPanel->addSeparator(); - controlPanel->beginLayout(QBoxLayout::LeftToRight); + controlPanel->beginLayout( QBoxLayout::LeftToRight ); controlPanel->addOption( " Wireframe rendering", [renderer, appUpdateCallback]( bool b ) { - renderer->wireframeMode( b ); - appUpdateCallback(); + renderer->wireframeMode( b ); + appUpdateCallback(); } ); - controlPanel->addOption( " Show Debug ", [renderer, appUpdateCallback]( bool b ) { @@ -43,17 +42,16 @@ RadiumNBR::Gui::RendererPanel* buildRadiumNBRGui( FullFeatureRenderer* renderer, false ); controlPanel->endLayout( true ); - auto envmpClbck = [renderer, appUpdateCallback]( const std::string& files ) { renderer->setEnvMap( files ); appUpdateCallback(); }; - controlPanel->beginLayout(QBoxLayout::LeftToRight); + controlPanel->beginLayout( QBoxLayout::LeftToRight ); controlPanel->addFileInput( "Environment map", envmpClbck, "../", "Images (*.png *.jpg *.pfm *.exr *hdr)" ); - controlPanel->beginLayout(QBoxLayout::TopToBottom ); + controlPanel->beginLayout( QBoxLayout::TopToBottom ); controlPanel->addOption( " Show envMap ", [renderer, appUpdateCallback]( bool b ) { @@ -70,10 +68,10 @@ RadiumNBR::Gui::RendererPanel* buildRadiumNBRGui( FullFeatureRenderer* renderer, }, 100 ); controlPanel->endLayout(); - controlPanel->endLayout(true); + controlPanel->endLayout( true ); // AO control - controlPanel->beginLayout(QBoxLayout::LeftToRight); + controlPanel->beginLayout( QBoxLayout::LeftToRight ); controlPanel->addScalarInput( "AO radius", [renderer, appUpdateCallback]( double r ) { diff --git a/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.hpp b/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.hpp index ccfd7c52e65d235cb75428aeebf984b9a44c7cf7..479b39ac9726b7f2dd1fff0ac475ad9b57ab097a 100644 --- a/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.hpp +++ b/src/libRender/RadiumNBR/Gui/FullFeaturedRendererGui.hpp @@ -1,7 +1,7 @@ #pragma once -#include <RadiumNBR/Gui/RendererPanel.hpp> #include <RadiumNBR/NodeBasedRendererMacro.hpp> +#include <RadiumNBR/Gui/RendererPanel.hpp> namespace RadiumNBR { class FullFeatureRenderer; diff --git a/src/libRender/RadiumNBR/Gui/RendererPanel.cpp b/src/libRender/RadiumNBR/Gui/RendererPanel.cpp index 4aa1a7f734f50cf4a01408f4466a15ae27cd9223..518fabb2caee7ecb547fa8a614dada5ed36ff22f 100644 --- a/src/libRender/RadiumNBR/Gui/RendererPanel.cpp +++ b/src/libRender/RadiumNBR/Gui/RendererPanel.cpp @@ -4,8 +4,11 @@ #include <QVBoxLayout> #include <QColorDialog> +#include <QDialog> +#include <QDialogButtonBox> #include <QDoubleSpinBox> #include <QFileDialog> +#include <QPlainTextEdit> #include <QPushButton> #include <QRadioButton> #include <QSlider> @@ -21,10 +24,9 @@ RendererPanel::RendererPanel( const std::string& name, QWidget* parent ) : QFram auto panelName = new QLabel( this ); panelName->setFrameStyle( QFrame::HLine ); m_currentLayout->addWidget( panelName ); - //addSeparator(); + // addSeparator(); setVisible( false ); m_layouts.push( m_currentLayout ); - } // Method to populate the panel @@ -132,37 +134,73 @@ void RendererPanel::addFileInput( const std::string& name, m_currentLayout->addWidget( button ); } -void RendererPanel::beginLayout(QBoxLayout::Direction dir) { - m_layouts.push(m_currentLayout); +void RendererPanel::beginLayout( QBoxLayout::Direction dir ) { + m_layouts.push( m_currentLayout ); m_currentLayout = new QBoxLayout( dir ); } void RendererPanel::endLayout( bool separator ) { m_layouts.top()->addLayout( m_currentLayout ); m_currentLayout = m_layouts.top(); - if ( separator ) { - addSeparator(); - } + if ( separator ) { addSeparator(); } m_layouts.pop(); } void RendererPanel::addSeparator() { QFrame* line = new QFrame(); - switch ( m_currentLayout->direction() ) { + switch ( m_currentLayout->direction() ) + { case QBoxLayout::LeftToRight: case QBoxLayout::RightToLeft: - line->setFrameShape(QFrame::VLine); + line->setFrameShape( QFrame::VLine ); break; case QBoxLayout::TopToBottom: case QBoxLayout::BottomToTop: - line->setFrameShape(QFrame::HLine); + line->setFrameShape( QFrame::HLine ); break; default: - line->setFrameShape(QFrame::HLine); + line->setFrameShape( QFrame::HLine ); } - line->setFrameShadow(QFrame::Sunken); + line->setFrameShadow( QFrame::Sunken ); m_currentLayout->addWidget( line ); } +void RendererPanel::addCodeEditor( const std::string& name, + std::function<void( std::string )> callback, + const std::string& initialText ) { + + auto button = new QPushButton( name.c_str(), this ); + QDialog* dialog = nullptr; + auto editDialog = [this, callback, initialText, dialog]() mutable { + if ( !dialog ) + { + dialog = new QDialog( this ); + + auto buttonBox = new QDialogButtonBox( + QDialogButtonBox::Save | QDialogButtonBox::Cancel | QDialogButtonBox::Ok ); + auto textEditor = new QPlainTextEdit(); + textEditor->setPlainText( QString::fromStdString( initialText ) ); + + connect( buttonBox, &QDialogButtonBox::accepted, [callback, textEditor]() { + callback( textEditor->toPlainText().toStdString() ); + } ); + + connect( buttonBox, &QDialogButtonBox::rejected, [callback, textEditor, initialText]() { + textEditor->setPlainText( QString::fromStdString( initialText ) ); + } ); + + QVBoxLayout* mainLayout = new QVBoxLayout; + mainLayout->addWidget( textEditor ); + mainLayout->addWidget( buttonBox ); + dialog->setLayout( mainLayout ); + } + dialog->show(); + dialog->raise(); + dialog->activateWindow(); + }; + connect( button, &QPushButton::clicked, editDialog ); + m_currentLayout->addWidget( button ); +} + } // namespace Gui } // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/Gui/RendererPanel.hpp b/src/libRender/RadiumNBR/Gui/RendererPanel.hpp index 62429724839ece517b7178e443a86c677bf2111b..f5c465c77e440dcb4e8dbb0955fa1f4f5bdfd68b 100644 --- a/src/libRender/RadiumNBR/Gui/RendererPanel.hpp +++ b/src/libRender/RadiumNBR/Gui/RendererPanel.hpp @@ -5,8 +5,8 @@ #include <QVBoxLayout> #include <functional> -#include <string> #include <stack> +#include <string> #include <Core/Utils/Color.hpp> @@ -48,7 +48,7 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame * - QBoxLayout::TopToBottom * - QBoxLayout::BottomToTop */ - void beginLayout(QBoxLayout::Direction dir = QBoxLayout::LeftToRight); + void beginLayout( QBoxLayout::Direction dir = QBoxLayout::LeftToRight ); /** * Close the current layout. @@ -59,7 +59,7 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame /** * Add a separator */ - void addSeparator(); + void addSeparator(); /** Add an option to the panel * An option is an on/off checkbox to activate a state of the renderer. @@ -123,6 +123,16 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame std::function<void( std::string )> callback, const std::string& rootDirectory, const std::string& filters ); + + /** + * + * @param name + * @param callback + * @param initialText + */ + void addCodeEditor( const std::string& name, + std::function<void( std::string )> callback, + const std::string& initialText ); /**@}*/ private: @@ -130,10 +140,10 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame QVBoxLayout* m_contentLayout; /// The current layout where UI element will be added - QBoxLayout *m_currentLayout; + QBoxLayout* m_currentLayout; /// The stack of layouts - std::stack<QBoxLayout *> m_layouts; + std::stack<QBoxLayout*> m_layouts; }; } // namespace Gui } // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp b/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47a694a83232720e3411d6b649709603b41990b7 --- /dev/null +++ b/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp @@ -0,0 +1,71 @@ +#include <RadiumNBR/Gui/VisualizationGui.hpp> +#include <RadiumNBR/NodeBasedRenderer.hpp> +#include <RadiumNBR/Renderer/Visualization.hpp> + +namespace RadiumNBR { +using namespace Gui; + +RadiumNBR::Gui::RendererPanel* +buildControllerGui( NodeBasedRenderer* renderer, const std::function<void()>& appUpdateCallback ) { + auto& controller = dynamic_cast<VisualizationController&>( renderer->getController() ); + + auto controlPanel = new RendererPanel( renderer->getRendererName() ); + + auto defColor = Ra::Core::Utils::Color::linearRGBTosRGB( renderer->getBackgroundColor() ); + auto clrClbck = [renderer, appUpdateCallback]( const Ra::Core::Utils::Color& clr ) { + // set the background color for all passes that need it + renderer->setBackgroundColor( clr ); + appUpdateCallback(); + }; + controlPanel->addColorInput( "Background Color", clrClbck, defColor ); + + controlPanel->addSeparator(); + + controlPanel->beginLayout( QBoxLayout::LeftToRight ); + + controlPanel->addOption( + " Post processing", + [&controller, appUpdateCallback]( bool b ) { + controller.enablePostProcess( b ); + appUpdateCallback(); + }, + true ); + + controlPanel->addOption( + " Show Debug ", + [renderer, appUpdateCallback]( bool b ) { + renderer->showDebug( b ); + appUpdateCallback(); + }, + false ); + + controlPanel->addOption( + " Show UI ", + [renderer, appUpdateCallback]( bool b ) { + renderer->showUI( b ); + appUpdateCallback(); + }, + false ); + controlPanel->endLayout( true ); + + auto visualizationFunction = controller.getAttribToColorFunc(); + controlPanel->addCodeEditor( + "Attribute function", + [&controller, visualizationFunction, appUpdateCallback]( const std::string& s ) { + controller.setAttribToColorFunc( s, visualizationFunction.second ); + appUpdateCallback(); + }, + visualizationFunction.first ); + + controlPanel->addCodeEditor( + "Color function", + [&controller, visualizationFunction, appUpdateCallback]( const std::string& s ) { + controller.setAttribToColorFunc( visualizationFunction.first, s ); + appUpdateCallback(); + }, + visualizationFunction.second ); + + return controlPanel; +} + +} // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/Gui/VisualizationGui.hpp b/src/libRender/RadiumNBR/Gui/VisualizationGui.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e633c557d74546ca948591e8984ec7a7ced016d5 --- /dev/null +++ b/src/libRender/RadiumNBR/Gui/VisualizationGui.hpp @@ -0,0 +1,11 @@ +#pragma once +#include <RadiumNBR/NodeBasedRendererMacro.hpp> + +#include <RadiumNBR/Gui/RendererPanel.hpp> +namespace RadiumNBR { +class NodeBasedRenderer; + +NodeBasedRenderer_LIBRARY_API RadiumNBR::Gui::RendererPanel* +buildControllerGui( NodeBasedRenderer* renderer, const std::function<void()>& appUpdateCallback ); + +} // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/NodeBasedRenderer.cpp b/src/libRender/RadiumNBR/NodeBasedRenderer.cpp index c8bd4614c2f084272d80e01db25205c1a96115bd..e1cbe285f4331c0ad651a6146f89604a73b70cbc 100644 --- a/src/libRender/RadiumNBR/NodeBasedRenderer.cpp +++ b/src/libRender/RadiumNBR/NodeBasedRenderer.cpp @@ -289,7 +289,8 @@ void NodeBasedRenderer::postProcessInternal( const ViewingParameters& /* renderD GL_ASSERT( glDisable( GL_DEPTH_TEST ) ); GL_ASSERT( glDepthMask( GL_FALSE ) ); - auto shader = m_shaderProgramManager->getShaderProgram( "Hdr2Ldr" ); + auto shader = m_postProcessEnabled ? m_shaderProgramManager->getShaderProgram( "Hdr2Ldr" ) + : m_shaderProgramManager->getShaderProgram( "DrawScreen" ); shader->bind(); shader->setUniform( "screenTexture", m_sharedTextures["Linear RGB (RadiumNBR)"].get(), 0 ); m_quadMesh->render( shader ); diff --git a/src/libRender/RadiumNBR/NodeBasedRenderer.hpp b/src/libRender/RadiumNBR/NodeBasedRenderer.hpp index 0c7950d523ac90ebab6bf26186c0f7ed806a101c..ab3691b173197a4f98aedd0ea5f51508d888b21b 100644 --- a/src/libRender/RadiumNBR/NodeBasedRenderer.hpp +++ b/src/libRender/RadiumNBR/NodeBasedRenderer.hpp @@ -57,8 +57,7 @@ class NodeBasedRenderer_LIBRARY_API NodeBasedRenderer : public Ra::Engine::Rende public: // NodeBasedRenderer(); - // TODO : instead of an std::function, restrict to a ref to a functor (class with () operator - // Such a functor could then be used also during the update step. + explicit NodeBasedRenderer( RenderControlFunctor& controller ); ~NodeBasedRenderer() override; @@ -91,6 +90,9 @@ class NodeBasedRenderer_LIBRARY_API NodeBasedRenderer : public Ra::Engine::Rende /// Access the default light manager Ra::Engine::Scene::LightManager* getLightManager() { return m_lightmanagers[0]; } + /// Access the controler + RenderControlFunctor& getController() { return m_controller; } + protected: void initializeInternal() override; void resizeInternal() override; diff --git a/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.cpp b/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.cpp index b5c9150db6b7eb0cdfc3d7703ef137e2d0c13540..d85a293553b25b4191199de1bcff6df55d4f0b02 100644 --- a/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.cpp +++ b/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.cpp @@ -124,7 +124,6 @@ bool CustomAttribToColorPass::buildRenderTechnique( if ( m_needConfigRebuild ) { - m_needConfigRebuild = false; Ra::Engine::Data::ShaderConfigurationFactory::removeConfiguration( {"CustomAtt2ClrPass::CustomColorProgram" + mat->getMaterialName()} ); } @@ -233,10 +232,20 @@ void CustomAttribToColorPass::setAttribToColorFunc( const std::string& vertex_so const std::string& fragment_source ) { m_customVertexAttrib = vertex_source; m_customFragmentColor = fragment_source; - m_needConfigRebuild = true; + rebuildShaders(); } void CustomAttribToColorPass::setLightManager( const Ra::Engine::Scene::LightManager* lm ) { m_lightmanager = lm; } + +void CustomAttribToColorPass::rebuildShaders() { + m_needConfigRebuild = true; + for ( const auto& ro : *m_objectsToRender ) + { + auto rt = ro->getRenderTechnique(); + buildRenderTechnique( ro.get(), *rt ); + } + m_needConfigRebuild = false; +} } // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.hpp b/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.hpp index 493d7a822b085838d51c31fd8eea7e92e307005f..37bdfe432c60ef320c9fd3911a445707598fac6b 100644 --- a/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.hpp +++ b/src/libRender/RadiumNBR/Passes/CustomAttribToColorPass.hpp @@ -45,6 +45,8 @@ class CustomAttribToColorPass : public RenderPass void setAttribToColorFunc( const std::string& vertex_source, const std::string& fragment_source ); + void rebuildShaders(); + private: /// The framebuffer used to render this pass std::unique_ptr<globjects::Framebuffer> m_fbo{nullptr}; diff --git a/src/libRender/RadiumNBR/FullFeatureRenderer.cpp b/src/libRender/RadiumNBR/Renderer/FullFeatureRenderer.cpp similarity index 99% rename from src/libRender/RadiumNBR/FullFeatureRenderer.cpp rename to src/libRender/RadiumNBR/Renderer/FullFeatureRenderer.cpp index 03a0c24c40364e172802a27eb6ceaec209ac43bf..6a78926b3b518a66cc1267b8eda71ac6bfef40b3 100644 --- a/src/libRender/RadiumNBR/FullFeatureRenderer.cpp +++ b/src/libRender/RadiumNBR/Renderer/FullFeatureRenderer.cpp @@ -1,4 +1,4 @@ -#include <RadiumNBR/FullFeatureRenderer.hpp> +#include <RadiumNBR/Renderer/FullFeatureRenderer.hpp> #include <Core/Containers/MakeShared.hpp> #include <Core/Resources/Resources.hpp> diff --git a/src/libRender/RadiumNBR/FullFeatureRenderer.hpp b/src/libRender/RadiumNBR/Renderer/FullFeatureRenderer.hpp similarity index 100% rename from src/libRender/RadiumNBR/FullFeatureRenderer.hpp rename to src/libRender/RadiumNBR/Renderer/FullFeatureRenderer.hpp diff --git a/src/libRender/RadiumNBR/Renderer/Visualization.cpp b/src/libRender/RadiumNBR/Renderer/Visualization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5049658ce1f103876ea2fe607c5f6ae9cd59b88 --- /dev/null +++ b/src/libRender/RadiumNBR/Renderer/Visualization.cpp @@ -0,0 +1,120 @@ +#include <Engine/Data/ShaderProgramManager.hpp> +#include <Engine/RadiumEngine.hpp> +#include <RadiumNBR/Passes/ClearPass.hpp> +#include <RadiumNBR/Passes/CustomAttribToColorPass.hpp> +#include <RadiumNBR/Passes/GeomPrepass.hpp> +#include <RadiumNBR/Renderer/Visualization.hpp> + +#include <Core/Utils/Log.hpp> +using namespace Ra::Core::Utils; // log + +namespace RadiumNBR { + +void VisualizationController::configure( RadiumNBR::NodeBasedRenderer* renderer, int w, int h ) { + m_renderer = renderer; + + //! [Caching some helpers and data from the Engine and the renderer] + auto resourcesCheck = Ra::Core::Resources::getResourcesPath( + reinterpret_cast<void*>( &RadiumNBR::NodeBasedRendererMagic ), {"Resources/RadiumNBR"} ); + if ( !resourcesCheck ) + { + LOG( Ra::Core::Utils::logERROR ) << "Unable to find resources for NodeBasedRenderer!"; + return; + } + else + { LOG( Ra::Core::Utils::logINFO ) << "NodeBasedRenderer Resources are at " << *resourcesCheck; } + auto resourcesPath{*resourcesCheck}; + auto shaderManager = Ra::Engine::RadiumEngine::getInstance()->getShaderProgramManager(); + auto colortexture = renderer->sharedTextures().find( "Linear RGB (RadiumNBR)" ); + auto depthtexture = renderer->sharedTextures().find( "Depth (RadiumNBR)" ); + //! [Caching some helpers and data from the Engine and the renderer] + + //! [Adding a clear-screen pass] + { + // pass that draw no object and is positioned at rank 0 + m_clearPass = std::make_shared<RadiumNBR::ClearPass>( nullptr, 0 ); + // set the output of the pass : clear the renderer Linear RGB output texture + m_clearPass->setOutput( *colortexture ); + // set the clear color (pass internal state) + m_clearPass->setBackground( {0.5, 0.1, 0.1} /*renderer->getBackgroundColor()*/ ); + m_clearPass->initializePass( w, h, shaderManager ); + // add the pass to the renderer and activate it + renderer->addPass( m_clearPass, m_clearPass->index() ); + m_clearPass->activate(); + } + //! [Adding a clear-screen pass] + + //! [Adding a Z-only pass] + { + // the z-only pass takes all the objects and draw them only on the shared depth buffer. + auto pass = std::make_shared<RadiumNBR::GeomPrePass>( renderer->allRenderObjects(), 1 ); + // set the output to the shared depth texture + pass->setOutput( *depthtexture ); + // configure access to shader/resources files and initialize the pass + pass->setResourcesDir( resourcesPath ); + pass->initializePass( w, h, shaderManager ); + // add the pass to the renderer and activate it + renderer->addPass( pass, pass->index() ); + pass->activate(); + } + //! [Adding a Z-only pass] + + //! [Adding a CustomAttribToColorPass pass] + { + // this pass draw all the objects using the custom color function, + // Rendering is done against the shared z-buffer for hidden line removal and + // into the shared color buffer. + m_customPass = + std::make_shared<RadiumNBR::CustomAttribToColorPass>( renderer->allRenderObjects(), 2 ); + // set the input/output textures + m_customPass->setInputs( *depthtexture ); + m_customPass->setOutput( *colortexture ); + m_customPass->setLightManager( renderer->getLightManager() ); + m_customPass->setAttribToColorFunc( m_vertexFunction, m_fragmentFunction ); + // configure access to shader/resources files and initialize the pass + m_customPass->setResourcesDir( resourcesPath ); + m_customPass->initializePass( w, h, shaderManager ); + // add the pass to the renderer and activate it + renderer->addPass( m_customPass, m_customPass->index() ); + m_customPass->activate(); + } + //! [Adding a CustomAttribToColorPass pass] +} + +void VisualizationController::update( const Ra::Engine::Data::ViewingParameters& ) { + /* This function is called once before each frame. + * You can use it to modify the scene, or modify the computation function of the renderer + * For this, just call + * m_customPass->setAttribToColorFunc( customVertexAttrib, customFragmentColor ); + * with the wanted shader glsl source code. + */ + if ( m_postProcess ) { m_clearPass->setBackground( m_renderer->getBackgroundColor() ); } + else + { + auto defColor = Ra::Core::Utils::Color::linearRGBTosRGB( m_renderer->getBackgroundColor() ); + m_clearPass->setBackground( defColor ); + } +}; + +void VisualizationController::resize( int w, int h ){ + /* if you have resizeable resources in your controller, this method is called each time the + * viewer window is resized so that you can dimension your resources accordingly + */ +}; + +/// Set the custom glsl function for attrib management (vertex) and colorcomputation (fragment) +void VisualizationController::setAttribToColorFunc( const std::string& vertex_source, + const std::string& fragment_source ) { + m_vertexFunction = vertex_source; + m_fragmentFunction = fragment_source; + if ( m_customPass ) + { + m_customPass->setAttribToColorFunc( m_vertexFunction, m_fragmentFunction ); + m_customPass->rebuildShaders(); + } +} + +std::pair<std::string&, std::string&> VisualizationController::getAttribToColorFunc() { + return {m_vertexFunction, m_fragmentFunction}; +} +} // namespace RadiumNBR diff --git a/src/libRender/RadiumNBR/Renderer/Visualization.hpp b/src/libRender/RadiumNBR/Renderer/Visualization.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ecf18ae23528bd35253169463c1ef67a072966b4 --- /dev/null +++ b/src/libRender/RadiumNBR/Renderer/Visualization.hpp @@ -0,0 +1,53 @@ +#include <RadiumNBR/NodeBasedRenderer.hpp> + +namespace RadiumNBR { +class CustomAttribToColorPass; +class ClearPass; + +/** + * This class parameterize the renderer just after the OpenGL system was initialized. + * when a method of this controler is called, the OpenGL context of the drawing window is activated. + */ +class NodeBasedRenderer_LIBRARY_API VisualizationController : public RadiumNBR::RenderControlFunctor +{ + public: + /* + * Called once : configure the renderer by adding passes and allocating controler resources + */ + void configure( RadiumNBR::NodeBasedRenderer* renderer, int w, int h ) override; + + void update( const Ra::Engine::Data::ViewingParameters& ) override; + + void resize( int w, int h ) override; + + /// Set the custom glsl function for attrib management (vertex) and colorcomputation (fragment) + void setAttribToColorFunc( const std::string& vertex_source, + const std::string& fragment_source ); + + /// Get the glsl functions + std::pair<std::string&, std::string&> getAttribToColorFunc(); + + /// activate or deactivate the gamma-correction on the computed color + inline void enablePostProcess( bool b ) { + m_postProcess = b; + m_renderer->enablePostProcess( b ); + } + + private: + /// The custom pass if needed for modification + std::shared_ptr<RadiumNBR::CustomAttribToColorPass> m_customPass; + + /// The clear pass for the background + std::shared_ptr<RadiumNBR::ClearPass> m_clearPass; + /// + std::string m_vertexFunction{"void outputCustomAttribs() {\n}\n"}; + std::string m_fragmentFunction{ + "vec4 computeCustomColor(Material mat, vec3 lightDir, " + "vec3 viewDir, vec3 normal_world) {\n return vec4(normal_world*0.5+0.5, 1);\n}\n"}; + + RadiumNBR::NodeBasedRenderer* m_renderer; + + bool m_postProcess{true}; +}; + +} // namespace RadiumNBR