Radium Engine  1.5.0
RenderTechnique.cpp
1 #include <Engine/Rendering/RenderTechnique.hpp>
2 
3 #include <Engine/Data/BlinnPhongMaterial.hpp>
4 #include <Engine/Data/ShaderProgramManager.hpp>
5 #include <Engine/RadiumEngine.hpp>
6 
7 #include <Core/Utils/Log.hpp>
8 
9 namespace Ra {
10 namespace Engine {
11 namespace Rendering {
12 
13 using namespace Core::Utils; // log
14 
15 std::shared_ptr<Ra::Engine::Rendering::RenderTechnique> RadiumDefaultRenderTechnique { nullptr };
16 
17 RenderTechnique::RenderTechnique() : m_numActivePass { 0 } {
18  for ( auto p = Index( 0 ); p < s_maxNbPasses; ++p ) {
19  m_activePasses[p] = PassConfiguration( Data::ShaderConfiguration(), nullptr );
20  m_passesParameters[p] = nullptr;
21  }
22 }
23 
24 RenderTechnique::RenderTechnique( const RenderTechnique& o ) :
25  m_numActivePass { o.m_numActivePass },
26  m_dirtyBits { o.m_dirtyBits },
27  m_setPasses { o.m_setPasses } {
28  for ( auto p = Index( 0 ); p < m_numActivePass; ++p ) {
29  if ( hasConfiguration( p ) ) {
30  m_activePasses[p] = o.m_activePasses[p];
31  m_passesParameters[p] = o.m_passesParameters[p];
32  }
33  }
34 }
35 
36 RenderTechnique::~RenderTechnique() = default;
37 
39  Core::Utils::Index pass ) {
40  m_numActivePass = std::max( m_numActivePass, pass + 1 );
41  m_activePasses[pass] = PassConfiguration( newConfig, nullptr );
42  setDirty( pass );
43  setConfiguration( pass );
44 }
45 
46 const Data::ShaderProgram* RenderTechnique::getShader( Core::Utils::Index pass ) const {
47  if ( hasConfiguration( pass ) ) { return m_activePasses[pass].second; }
48  return nullptr;
49 }
50 
52  std::shared_ptr<Data::ShaderParameterProvider> provider,
53  Core::Utils::Index pass ) {
54  if ( m_numActivePass == 0 ) {
55  LOG( logERROR )
56  << "Unable to set pass parameters : is passes configured using setConfiguration ? ";
57  return;
58  }
59  if ( pass.isValid() ) {
60  if ( hasConfiguration( pass ) ) { m_passesParameters[pass] = provider; }
61  }
62  else {
63  for ( int i = 0; i < m_numActivePass; ++i ) {
64  if ( hasConfiguration( i ) ) { m_passesParameters[i] = provider; }
65  }
66  }
67  // add the provider specific properties to the configuration
68  addPassProperties( provider->getPropertyList(), pass );
69 }
70 
71 void RenderTechnique::addPassProperties( const std::list<std::string>& props,
72  Core::Utils::Index pass ) {
73  if ( m_numActivePass == 0 ) {
74  LOG( logERROR )
75  << "Unable to set pass properties : is passes configured using setConfiguration ? ";
76  return;
77  }
78  if ( pass.isValid() && hasConfiguration( pass ) ) {
79  m_activePasses[pass].first.addProperties( props );
80  setDirty( pass );
81  }
82  else {
83  for ( int i = 0; i < m_numActivePass; ++i ) {
84  if ( hasConfiguration( i ) ) {
85  m_activePasses[i].first.addProperties( props );
86  setDirty( i );
87  }
88  }
89  }
90 }
91 
93 RenderTechnique::getParametersProvider( Core::Utils::Index pass ) const {
94  if ( hasConfiguration( pass ) ) { return m_passesParameters[pass].get(); }
95  return nullptr;
96 }
97 
99  auto shaderProgramManager = RadiumEngine::getInstance()->getShaderProgramManager();
100 
101  for ( auto p = Index( 0 ); p < m_numActivePass; ++p ) {
102  if ( hasConfiguration( p ) &&
103  ( ( nullptr == m_activePasses[p].second ) || isDirty( p ) ) ) {
104  m_activePasses[p].second =
105  shaderProgramManager->getShaderProgram( m_activePasses[p].first );
106  clearDirty( p );
107  }
108  }
109  for ( auto p = Index( 0 ); p < m_numActivePass; ++p ) {
110  if ( m_passesParameters[p] ) { m_passesParameters[p]->updateGL(); }
111  }
112 }
113 
116  if ( RadiumDefaultRenderTechnique != nullptr ) {
117  return *( RadiumDefaultRenderTechnique.get() );
118  }
119  std::shared_ptr<Data::Material> mat( new Data::BlinnPhongMaterial( "DefaultGray" ) );
120  auto rt = new RenderTechnique;
121  auto builder = EngineRenderTechniques::getDefaultTechnique( "BlinnPhong" );
122  if ( !builder.first ) {
123  LOG( logERROR ) << "Unable to create the default technique : is the Engine initialized ? ";
124  }
125  builder.second( *rt, false );
126  rt->setParametersProvider( mat );
127  RadiumDefaultRenderTechnique.reset( rt );
128  return *( RadiumDefaultRenderTechnique.get() );
129 }
130 
134 namespace EngineRenderTechniques {
135 
137 static std::map<std::string, DefaultTechniqueBuilder> EngineTechniqueRegistry;
138 
142 bool registerDefaultTechnique( const std::string& name, DefaultTechniqueBuilder builder ) {
143  auto result = EngineTechniqueRegistry.insert( { name, builder } );
144  return result.second;
145 }
146 
150 bool removeDefaultTechnique( const std::string& name ) {
151  std::size_t removed = EngineTechniqueRegistry.erase( name );
152  return ( removed == 1 );
153 }
154 
160 std::pair<bool, DefaultTechniqueBuilder> getDefaultTechnique( const std::string& name ) {
161  auto search = EngineTechniqueRegistry.find( name );
162  if ( search != EngineTechniqueRegistry.end() ) { return { true, search->second }; }
163  auto result = std::make_pair( false, [name]( RenderTechnique&, bool ) -> void {
164  LOG( logERROR ) << "Undefined default technique for " << name << " !";
165  } );
166  return result;
167 }
168 
169 bool cleanup() {
170  EngineTechniqueRegistry.clear();
171  return true;
172 }
173 
174 } // namespace EngineRenderTechniques
175 
176 } // namespace Rendering
177 } // namespace Engine
178 } // namespace Ra
void setParametersProvider(std::shared_ptr< Data::ShaderParameterProvider > provider, Core::Utils::Index pass=Core::Utils::Index(-1))
void clearDirty(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE)
void setConfiguration(const Data::ShaderConfiguration &newConfig, Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE)
const Data::ShaderParameterProvider * getParametersProvider(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE) const
void addPassProperties(const std::list< std::string > &props, Core::Utils::Index pass=Core::Utils::Index {})
static RenderTechnique createDefaultRenderTechnique()
const Data::ShaderProgram * getShader(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE) const
bool hasConfiguration(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE) const
bool isDirty(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE) const
void setDirty(Core::Utils::Index pass=DefaultRenderingPasses::LIGHTING_OPAQUE)
Definition: Cage.cpp:3