diff --git a/doc/HowToNodes-Developer.md b/doc/HowToNodes-Developer.md index 7ad1bb59f7f3e98397dd3b21688702b5bbfc0593..74efc3991c4b07430575326fe8ce1354e507518a 100644 --- a/doc/HowToNodes-Developer.md +++ b/doc/HowToNodes-Developer.md @@ -93,7 +93,6 @@ void NewNode::resize( uint32_t width, uint32_t height) { ``` - **buildRenderTechnique( const Ra::Engine::Rendering::RenderObject\* ro, Ra::Engine::Rendering::RenderTechnique& rt) const**: Called once per render object to create the render technique needed for this pass. - ```CPP void NewNode::buildRenderTechnique( const Ra::Engine::Rendering::RenderObject* ro, Ra::Engine::Rendering::RenderTechnique& rt) const { auto mat = const_cast<Ra::Engine::Rendering::RenderObject*>( ro )->getMaterial(); @@ -138,13 +137,13 @@ NodeFactory::registerNode<NewNode>( [] ( const nlohmann::json& data ) { ``` ## Adding the node to the Qt GUI (NodeEditor) -If you are using the Qt windowing system, you can add your node to NodeEditor in the ``openNodeEditor()`` function of ``RadiumPlayer.cpp``. +If you are using the Qt windowing system, you can add your node to NodeEditor by using the ``DataModelRegistry``. In the general case, you just want to use the already available ``NodeAdapterModel`` with your node. ```CPP ret->registerModel<NodeAdapterModel<NewNode>( NodeCreator<NodeAdapterModel<NewNode>( - renderer->getRenderGraph() ), "Premade Nodes" ); + renderer->getRenderGraph() ), "Premade Nodes" ); // ret is an instance of NodeEditor's DataModelRegistry ``` The widgets will be created according to the editable parameters defined in your node's constructor. The type of widget depends on the type of the editable parameter. If the type does not have a widget associated to it, you can add one yourself: diff --git a/src/libRender/CMakeLists.txt b/src/libRender/CMakeLists.txt index 5ebf3411c6a60e333834d466fa28f03956c54916..d8de08652cb070a7ca9ea4edac2713626177288e 100644 --- a/src/libRender/CMakeLists.txt +++ b/src/libRender/CMakeLists.txt @@ -42,6 +42,7 @@ set(sources RadiumNBR/NodeGraph/PremadeNodes/TransparencyNode.cpp RadiumNBR/NodeGraph/PremadeNodes/UINode.cpp RadiumNBR/NodeGraph/PremadeNodes/VolumeNode.cpp + RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.cpp RadiumNBR/NodeGraph/PremadeNodes/WireframeNode.cpp RadiumNBR/NodeGraph/PremadeNodes/ZGeomPrepassNode.cpp diff --git a/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.cpp b/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..491ff9bd55fce2276d846db8ab507fc8c187ecb2 --- /dev/null +++ b/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.cpp @@ -0,0 +1,254 @@ +#include <RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.hpp> + +VolumeVizualisationNode::VolumeVizualisationNode( const std::string& name ) : Node( name ) { + auto portInColor = new PortIn<NodeTypeTexture>( "inColorTexture", this ); + addInput( portInColor ); + portInColor->mustBeLinked(); + auto portInDepth = new PortIn<NodeTypeTexture>( "inDepthTexture", this ); + addInput( portInDepth ); + portInDepth->mustBeLinked(); + auto portInRO = new PortIn<std::vector<NodeTypeRenderObject>>( "inRenderObjects", this ); + addInput( portInRO ); + auto portInC = new PortIn<std::vector<NodeTypeCamera>>( "inCameras", this ); + addInput( portInC ); + portInC->mustBeLinked(); + auto portInL = new PortIn<std::vector<NodeTypeLight>>( "inLights", this ); + addInput( portInL ); + + auto portOutColorTex = new PortOut<NodeTypeTexture>( "outColorTexture", this ); + addOutput( portOutColorTex, m_colorTexture ); + + auto editableTransferFunction = new EditableParameter<std::array<float, 256 * 4>>( "transfer function", &m_editableTransferFunction); + addEditableParameter( editableTransferFunction ); +} + +void VolumeVizualisationNode::init() { + m_framebuffer = new globjects::Framebuffer(); + m_volumeFramebuffer = new globjects::Framebuffer(); + + Ra::Engine::Data::TextureParameters texParams; + texParams.target = gl::GL_TEXTURE_2D; + texParams.minFilter = gl::GL_LINEAR; + texParams.magFilter = gl::GL_LINEAR; + texParams.internalFormat = gl::GL_RGBA32F; + texParams.format = gl::GL_RGBA; + texParams.type = gl::GL_FLOAT; + texParams.name = "Volume"; + m_volumeTexture = new Ra::Engine::Data::Texture( texParams ); + + Ra::Core::Geometry::TriangleMesh mesh = + Ra::Core::Geometry::makeZNormalQuad( Ra::Core::Vector2( -1.f, 1.f ) ); + auto qm = std::make_unique<Ra::Engine::Data::Mesh>( "caller" ); + qm->loadGeometry( std::move( mesh ) ); + m_quadMesh = std::move( qm ); + m_quadMesh->updateGL(); + + const std::string vrtxSrc{"layout (location = 0) in vec3 in_position;\n" + "out vec2 varTexcoord;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(in_position, 1.0);\n" + " varTexcoord = (in_position.xy + 1.0) / 2.0;\n" + "}\n"}; + const std::string frgSrc{ + "out vec4 fragColor;\n" + "in vec2 varTexcoord;\n" + "uniform sampler2D volumeImage;\n" + "void main()\n" + "{\n" + " vec2 size = vec2(textureSize(volumeImage, 0));\n" + " vec4 volColor = texelFetch(volumeImage, ivec2(varTexcoord.xy * size), 0);\n" + " if (volColor.a < 1)\n" + " discard;\n" + " fragColor = vec4(volColor.rgb, 0);\n" + "}\n"}; + Ra::Engine::Data::ShaderConfiguration config{"ComposeVolumeVizualisation"}; + config.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_VERTEX, vrtxSrc ); + config.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT, frgSrc ); + auto added = m_shaderMngr->addShaderProgram( config ); + if ( added ) { m_shader = added.value(); } + + std::array<float, 256 * 4> transferInit; + for ( int i = 0; i < 256 * 4; i += 4 ) + { transferInit[i] = 1.f; } + Ra::Engine::Data::TextureParameters transferTexParams{ "Transfer function", + gl::GL_TEXTURE_2D, + 256, + 1, + 0, + gl::GL_RGBA, + gl::GL_RGBA8, + gl::GL_FLOAT, + gl::GL_CLAMP_TO_BORDER, + gl::GL_CLAMP_TO_BORDER, + gl::GL_CLAMP_TO_BORDER, + gl::GL_LINEAR, + gl::GL_LINEAR, + transferInit.data() }; + m_transferFunctionTexture = new Ra::Engine::Data::Texture( transferTexParams ); + m_transferFunctionTexture->initializeGL(); +#ifdef GRAPH_CALL_TRACE + std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": initialization." << std::endl; +#endif +} + +void VolumeVizualisationNode::update() { +#ifdef GRAPH_CALL_TRACE + std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": update." << std::endl; +#endif +} + +void VolumeVizualisationNode::execute() { + Ra::Engine::Data::RenderParameters inPassParams; + // Color + auto inputColor = dynamic_cast<PortIn<NodeTypeTexture>*>( m_inputs[0].get() ); + m_colorTexture = &inputColor->getData(); + auto outputColor = dynamic_cast<PortOut<NodeTypeTexture>*>( m_outputs[0].get() ); + outputColor->setData( m_colorTexture ); + + // Depth + auto inputDepth = dynamic_cast<PortIn<NodeTypeTexture>*>( m_inputs[1].get() ); + NodeTypeTexture* depthTexture = &inputDepth->getData(); + + // Render objects + auto inputRO = dynamic_cast<PortIn<std::vector<NodeTypeRenderObject>>*>( m_inputs[2].get() ); + std::vector<NodeTypeRenderObject> renderObjects; + if ( !inputRO->isLinked() ) + { std::cout << "RenderObjects port is not linked, no render object" << std::endl; } + else + { + renderObjects = inputRO->getData(); +#ifdef GRAPH_CALL_TRACE + std::cout << renderObjects.size() << " render objects" << std::endl; +#endif + } + + // Cameras + auto inputCamera = dynamic_cast<PortIn<std::vector<NodeTypeCamera>>*>( m_inputs[3].get() ); + std::vector<NodeTypeCamera> cameras = inputCamera->getData(); +#ifdef GRAPH_CALL_TRACE + std::cout << cameras.size() << " cameras" << std::endl; +#endif + + // Lights + auto inputLight = dynamic_cast<PortIn<std::vector<NodeTypeLight>>*>( m_inputs[4].get() ); + std::vector<NodeTypeLight> lights; + if ( !inputLight->isLinked() ) + { std::cout << "Lights port is not linked, 0 light" << std::endl; } + else + { + lights = inputLight->getData(); +#ifdef GRAPH_CALL_TRACE + std::cout << lights.size() << " lights" << std::endl; +#endif + } + + m_transferFunctionTexture->updateData( m_editableTransferFunction.data() ); + + static const float clearZeros[4] = {0.0, 0.0, 0.0, 0.0}; + const gl::GLenum buffers[] = {gl::GL_COLOR_ATTACHMENT0}; + m_volumeFramebuffer->bind(); + m_volumeFramebuffer->attachTexture( gl::GL_DEPTH_ATTACHMENT, depthTexture->texture() ); + + gl::glDrawBuffers( 1, buffers ); + gl::glClearBufferfv( gl::GL_COLOR, 0, clearZeros ); + gl::glDepthMask( gl::GL_FALSE ); + gl::glDisable( gl::GL_BLEND ); + gl::glDepthFunc( gl::GL_LEQUAL ); + gl::glEnable( gl::GL_DEPTH_TEST ); + gl::glDepthMask( gl::GL_FALSE ); + inPassParams.addParameter( "material.transferFunction", m_transferFunctionTexture ); + + for ( const auto& l : lights ) + { + inPassParams.addParameter( "imageColor", m_colorTexture ); + inPassParams.addParameter( "imageDepth", depthTexture ); + l->getRenderParameters( inPassParams ); + + for ( const auto& ro : renderObjects ) + { + ro->render( inPassParams, cameras[0], m_idx ); + } + } + + m_framebuffer->bind(); + m_framebuffer->attachTexture( gl::GL_COLOR_ATTACHMENT0, m_colorTexture->texture() ); + gl::glDrawBuffers( 1, buffers ); + gl::glDisable( gl::GL_DEPTH_TEST ); + gl::glEnable( gl::GL_BLEND ); + gl::glBlendFunc( gl::GL_ONE_MINUS_SRC_ALPHA, gl::GL_SRC_ALPHA ); + { + m_shader->bind(); + m_shader->setUniform( "volumeImage", m_volumeTexture, 0 ); + m_quadMesh->render( m_shader ); + } + + // Reset + gl::glDisable( gl::GL_BLEND ); + gl::glEnable( gl::GL_DEPTH_TEST ); + m_framebuffer->detach( gl::GL_COLOR_ATTACHMENT0 ); + m_framebuffer->unbind(); +#ifdef GRAPH_CALL_TRACE + std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": execute." << std::endl; +#endif +} + +void VolumeVizualisationNode::destroy() { + delete m_framebuffer; + + delete m_transferFunctionTexture; +#ifdef GRAPH_CALL_TRACE + std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": destroy." << std::endl; +#endif +} + +void VolumeVizualisationNode::resize( uint32_t width, uint32_t height ) { + m_volumeTexture->resize( width, height ); + + m_volumeFramebuffer->bind(); + m_volumeFramebuffer->attachTexture( gl::GL_COLOR_ATTACHMENT0, + m_volumeTexture->texture() ); + + globjects::Framebuffer::unbind(); +#ifdef GRAPH_CALL_TRACE + std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": resize: " << width << "x" + << height << "." << std::endl; +#endif +} + +void VolumeVizualisationNode::buildRenderTechnique( const Ra::Engine::Rendering::RenderObject* ro, + Ra::Engine::Rendering::RenderTechnique& rt ) const { + std::string resourcesRootDir = m_resourceDir; + auto mat = const_cast<Ra::Engine::Rendering::RenderObject*>( ro )->getMaterial(); + // Only volumes are used by this pass + if ( mat->getMaterialAspect() != Ra::Engine::Data::Material::MaterialAspect::MAT_DENSITY ) + { return; } + // Compute gradients + auto mro = const_cast<Ra::Engine::Rendering::RenderObject*>( ro ); + auto volume = + dynamic_cast<Ra::Core::Geometry::VolumeGrid&>( mro->getMesh()->getAbstractGeometry() ); + auto paramProvider = + std::make_shared<VolumeWithGradientParameterProvider>( mat, volume ); + + if ( auto cfg = Ra::Engine::Data::ShaderConfigurationFactory::getConfiguration( + {"VolumeLightingPass::" + mat->getMaterialName()} ) ) + { rt.setConfiguration( *cfg, m_idx ); } + else + { + // Build the shader configuration + Ra::Engine::Data::ShaderConfiguration theConfig{ + {"VolumeLightingPass::" + mat->getMaterialName()}, + resourcesRootDir + "Shaders/VolumeVisualization/volviz.vert.glsl", + resourcesRootDir + "Shaders/VolumeVisualization/volviz.frag.glsl"}; + /* + // add the material interface to the fragment shader + theConfig.addInclude( "\"" + mat->getMaterialName() + ".glsl\"", + Ra::Engine::ShaderType::ShaderType_FRAGMENT ); + */ + // Add to the ShaderConfigManager + Ra::Engine::Data::ShaderConfigurationFactory::addConfiguration( theConfig ); + // Add to the RenderTechniq + rt.setConfiguration( theConfig, m_idx ); + } + rt.setParametersProvider( paramProvider, m_idx ); +} \ No newline at end of file diff --git a/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.hpp b/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.hpp index dc29ec0c2d9e0107563db746deb841e7f5ecc20d..2f94508037f540726ad324c50306f63deaaffb1c 100644 --- a/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.hpp +++ b/src/libRender/RadiumNBR/NodeGraph/PremadeNodes/VolumeVizualisationNode.hpp @@ -5,9 +5,12 @@ #include <Core/Geometry/Volume.hpp> #include <Engine/Data/Material.hpp> +#include <Engine/Data/Texture.hpp> #include <Engine/Data/Mesh.hpp> #include <Engine/Data/ShaderConfigFactory.hpp> +#include <RadiumNBR/NodeGraph/Node.hpp> + #include <numeric> class VolumeWithGradientParameterProvider : public Ra::Engine::Data::ShaderParameterProvider { @@ -55,258 +58,16 @@ class VolumeWithGradientParameterProvider : public Ra::Engine::Data::ShaderParam class VolumeVizualisationNode : public Node { public: - explicit VolumeVizualisationNode( const std::string& name ) : Node( name ) { - auto portInColor = new PortIn<NodeTypeTexture>( "inColorTexture", this ); - addInput( portInColor ); - portInColor->mustBeLinked(); - auto portInDepth = new PortIn<NodeTypeTexture>( "inDepthTexture", this ); - addInput( portInDepth ); - portInDepth->mustBeLinked(); - auto portInRO = new PortIn<std::vector<NodeTypeRenderObject>>( "inRenderObjects", this ); - addInput( portInRO ); - auto portInC = new PortIn<std::vector<NodeTypeCamera>>( "inCameras", this ); - addInput( portInC ); - portInC->mustBeLinked(); - auto portInL = new PortIn<std::vector<NodeTypeLight>>( "inLights", this ); - addInput( portInL ); - - auto portOutColorTex = new PortOut<NodeTypeTexture>( "outColorTexture", this ); - addOutput( portOutColorTex, m_colorTexture ); - - auto editableTransferFunction = new EditableParameter<std::array<float, 256 * 4>>( "transfer function", &m_editableTransferFunction); - addEditableParameter( editableTransferFunction ); - } - - void init() override { - m_framebuffer = new globjects::Framebuffer(); - m_volumeFramebuffer = new globjects::Framebuffer(); - - Ra::Engine::Data::TextureParameters texParams; - texParams.target = gl::GL_TEXTURE_2D; - texParams.minFilter = gl::GL_LINEAR; - texParams.magFilter = gl::GL_LINEAR; - texParams.internalFormat = gl::GL_RGBA32F; - texParams.format = gl::GL_RGBA; - texParams.type = gl::GL_FLOAT; - texParams.name = "Volume"; - m_volumeTexture = new Ra::Engine::Data::Texture( texParams ); - - Ra::Core::Geometry::TriangleMesh mesh = - Ra::Core::Geometry::makeZNormalQuad( Ra::Core::Vector2( -1.f, 1.f ) ); - auto qm = std::make_unique<Ra::Engine::Data::Mesh>( "caller" ); - qm->loadGeometry( std::move( mesh ) ); - m_quadMesh = std::move( qm ); - m_quadMesh->updateGL(); - - const std::string vrtxSrc{"layout (location = 0) in vec3 in_position;\n" - "out vec2 varTexcoord;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(in_position, 1.0);\n" - " varTexcoord = (in_position.xy + 1.0) / 2.0;\n" - "}\n"}; - const std::string frgSrc{ - "out vec4 fragColor;\n" - "in vec2 varTexcoord;\n" - "uniform sampler2D volumeImage;\n" - "void main()\n" - "{\n" - " vec2 size = vec2(textureSize(volumeImage, 0));\n" - " vec4 volColor = texelFetch(volumeImage, ivec2(varTexcoord.xy * size), 0);\n" - " if (volColor.a < 1)\n" - " discard;\n" - " fragColor = vec4(volColor.rgb, 0);\n" - "}\n"}; - Ra::Engine::Data::ShaderConfiguration config{"ComposeVolumeVizualisation"}; - config.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_VERTEX, vrtxSrc ); - config.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT, frgSrc ); - auto added = m_shaderMngr->addShaderProgram( config ); - if ( added ) { m_shader = added.value(); } - - std::array<float, 256 * 4> transferInit; - for ( int i = 0; i < 256 * 4; i += 4 ) - { transferInit[i] = 1.f; } - Ra::Engine::Data::TextureParameters transferTexParams{ "Transfer function", - gl::GL_TEXTURE_2D, - 256, - 1, - 0, - gl::GL_RGBA, - gl::GL_RGBA8, - gl::GL_FLOAT, - gl::GL_CLAMP_TO_BORDER, - gl::GL_CLAMP_TO_BORDER, - gl::GL_CLAMP_TO_BORDER, - gl::GL_LINEAR, - gl::GL_LINEAR, - transferInit.data() }; - m_transferFunctionTexture = new Ra::Engine::Data::Texture( transferTexParams ); - m_transferFunctionTexture->initializeGL(); -#ifdef GRAPH_CALL_TRACE - std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": initialization." << std::endl; -#endif - } - - void update() override { -#ifdef GRAPH_CALL_TRACE - std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": update." << std::endl; -#endif - } - - void execute() override { - Ra::Engine::Data::RenderParameters inPassParams; - // Color - auto inputColor = dynamic_cast<PortIn<NodeTypeTexture>*>( m_inputs[0].get() ); - m_colorTexture = &inputColor->getData(); - auto outputColor = dynamic_cast<PortOut<NodeTypeTexture>*>( m_outputs[0].get() ); - outputColor->setData( m_colorTexture ); - - // Depth - auto inputDepth = dynamic_cast<PortIn<NodeTypeTexture>*>( m_inputs[1].get() ); - NodeTypeTexture* depthTexture = &inputDepth->getData(); - - // Render objects - auto inputRO = dynamic_cast<PortIn<std::vector<NodeTypeRenderObject>>*>( m_inputs[2].get() ); - std::vector<NodeTypeRenderObject> renderObjects; - if ( !inputRO->isLinked() ) - { std::cout << "RenderObjects port is not linked, no render object" << std::endl; } - else - { - renderObjects = inputRO->getData(); -#ifdef GRAPH_CALL_TRACE - std::cout << renderObjects.size() << " render objects" << std::endl; -#endif - } - - // Cameras - auto inputCamera = dynamic_cast<PortIn<std::vector<NodeTypeCamera>>*>( m_inputs[3].get() ); - std::vector<NodeTypeCamera> cameras = inputCamera->getData(); -#ifdef GRAPH_CALL_TRACE - std::cout << cameras.size() << " cameras" << std::endl; -#endif - - // Lights - auto inputLight = dynamic_cast<PortIn<std::vector<NodeTypeLight>>*>( m_inputs[4].get() ); - std::vector<NodeTypeLight> lights; - if ( !inputLight->isLinked() ) - { std::cout << "Lights port is not linked, 0 light" << std::endl; } - else - { - lights = inputLight->getData(); -#ifdef GRAPH_CALL_TRACE - std::cout << lights.size() << " lights" << std::endl; -#endif - } + explicit VolumeVizualisationNode( const std::string& name ); - m_transferFunctionTexture->updateData( m_editableTransferFunction.data() ); - - static const float clearZeros[4] = {0.0, 0.0, 0.0, 0.0}; - const gl::GLenum buffers[] = {gl::GL_COLOR_ATTACHMENT0}; - m_volumeFramebuffer->bind(); - m_volumeFramebuffer->attachTexture( gl::GL_DEPTH_ATTACHMENT, depthTexture->texture() ); - - gl::glDrawBuffers( 1, buffers ); - gl::glClearBufferfv( gl::GL_COLOR, 0, clearZeros ); - gl::glDepthMask( gl::GL_FALSE ); - gl::glDisable( gl::GL_BLEND ); - gl::glDepthFunc( gl::GL_LEQUAL ); - gl::glEnable( gl::GL_DEPTH_TEST ); - gl::glDepthMask( gl::GL_FALSE ); - inPassParams.addParameter( "material.transferFunction", m_transferFunctionTexture ); - - for ( const auto& l : lights ) - { - inPassParams.addParameter( "imageColor", m_colorTexture ); - inPassParams.addParameter( "imageDepth", depthTexture ); - l->getRenderParameters( inPassParams ); - - for ( const auto& ro : renderObjects ) - { - ro->render( inPassParams, cameras[0], m_idx ); - } - } - - m_framebuffer->bind(); - m_framebuffer->attachTexture( gl::GL_COLOR_ATTACHMENT0, m_colorTexture->texture() ); - gl::glDrawBuffers( 1, buffers ); - gl::glDisable( gl::GL_DEPTH_TEST ); - gl::glEnable( gl::GL_BLEND ); - gl::glBlendFunc( gl::GL_ONE_MINUS_SRC_ALPHA, gl::GL_SRC_ALPHA ); - { - m_shader->bind(); - m_shader->setUniform( "volumeImage", m_volumeTexture, 0 ); - m_quadMesh->render( m_shader ); - } - - // Reset - gl::glDisable( gl::GL_BLEND ); - gl::glEnable( gl::GL_DEPTH_TEST ); - m_framebuffer->detach( gl::GL_COLOR_ATTACHMENT0 ); - m_framebuffer->unbind(); -#ifdef GRAPH_CALL_TRACE - std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": execute." << std::endl; -#endif - } - - void destroy() override { - delete m_framebuffer; - - delete m_transferFunctionTexture; -#ifdef GRAPH_CALL_TRACE - std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": destroy." << std::endl; -#endif - } - - void resize( uint32_t width, uint32_t height ) override { - m_volumeTexture->resize( width, height ); - - m_volumeFramebuffer->bind(); - m_volumeFramebuffer->attachTexture( gl::GL_COLOR_ATTACHMENT0, - m_volumeTexture->texture() ); - - globjects::Framebuffer::unbind(); -#ifdef GRAPH_CALL_TRACE - std::cout << "\e[33m\e[1mVolumeVizualisationNode\e[0m \"" << m_name << "\": resize: " << width << "x" - << height << "." << std::endl; -#endif - } + void init() override; + void update() override; + void execute() override; + void destroy() override; + void resize( uint32_t width, uint32_t height ) override; void buildRenderTechnique( const Ra::Engine::Rendering::RenderObject* ro, - Ra::Engine::Rendering::RenderTechnique& rt ) const override { - std::string resourcesRootDir = m_resourceDir; - auto mat = const_cast<Ra::Engine::Rendering::RenderObject*>( ro )->getMaterial(); - // Only volumes are used by this pass - if ( mat->getMaterialAspect() != Ra::Engine::Data::Material::MaterialAspect::MAT_DENSITY ) - { return; } - // Compute gradients - auto mro = const_cast<Ra::Engine::Rendering::RenderObject*>( ro ); - auto volume = - dynamic_cast<Ra::Core::Geometry::VolumeGrid&>( mro->getMesh()->getAbstractGeometry() ); - auto paramProvider = - std::make_shared<VolumeWithGradientParameterProvider>( mat, volume ); - - if ( auto cfg = Ra::Engine::Data::ShaderConfigurationFactory::getConfiguration( - {"VolumeLightingPass::" + mat->getMaterialName()} ) ) - { rt.setConfiguration( *cfg, m_idx ); } - else - { - // Build the shader configuration - Ra::Engine::Data::ShaderConfiguration theConfig{ - {"VolumeLightingPass::" + mat->getMaterialName()}, - resourcesRootDir + "Shaders/VolumeVisualization/volviz.vert.glsl", - resourcesRootDir + "Shaders/VolumeVisualization/volviz.frag.glsl"}; - /* - // add the material interface to the fragment shader - theConfig.addInclude( "\"" + mat->getMaterialName() + ".glsl\"", - Ra::Engine::ShaderType::ShaderType_FRAGMENT ); - */ - // Add to the ShaderConfigManager - Ra::Engine::Data::ShaderConfigurationFactory::addConfiguration( theConfig ); - // Add to the RenderTechniq - rt.setConfiguration( theConfig, m_idx ); - } - rt.setParametersProvider( paramProvider, m_idx ); - } + Ra::Engine::Rendering::RenderTechnique& rt ) const override; static const std::string getTypename() { return "Volume Vizualisation Pass"; } diff --git a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp index 1969de4a352e5eaaf253d94595ce2cd509d474fa..26bc5aeeea2fe2116afcae4449c860302eaeaa99 100644 --- a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp +++ b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp @@ -476,7 +476,14 @@ bool RenderGraph::compile() { { if ( infoNodes.find( n.get() ) != infoNodes.end() ) { - n->setIndex( idx++ ); + for ( size_t i = 0; i < n->getInputs().size(); i++ ) { + // If the node accepts render objects as input + // then it needs an index for the render techniques + if (n->getInputs()[i]->getType() == typeid(std::vector<NodeTypeRenderObject>).hash_code()) { + n->setIndex( idx++ ); + break; + } + } n->setResourcesDir( m_resourceDir ); n->setShaderProgramManager( m_shaderMngr ); afterCullingNodes.push_back( n ); diff --git a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.hpp b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.hpp index 6393b2fb71e9a17b5997e85e39fbb36c8900e28c..dad855da78469d649d4098872a11b17a253c1072 100644 --- a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.hpp +++ b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.hpp @@ -4,6 +4,7 @@ #include <RadiumNBR/NodeGraph/PremadeNodes/DataNode.hpp> #include <RadiumNBR/NodeGraph/PremadeNodes/DisplaySinkNode.hpp> +// TODO : Find a new name, it is not a RENDER graph only anymore class NodeBasedRenderer_LIBRARY_API RenderGraph : public Node { public: /// Constructor.