A class that matches the rendered objects shader and render function(sets shader resources) based on its `typeid` hash. #include <unordered_map> #include <glm/glm.hpp> #include "gl_func.h" #include "gl_buffer.h" #include "shader.h" #include "log.h" class Renderer { private: typedef void (*RenderFunctionPointer)(); typedef std::unordered_map< size_t, Shader* >::iterator ShaderIterator; typedef std::unordered_map< size_t, RenderFunctionPointer >::iterator FunctionIterator; std::unordered_map< size_t, Shader* > Shaders; std::unordered_map< size_t, RenderFunctionPointer > RenderFunctions; glm::mat4 ProjectionMatrix; glm::mat4 ViewMatrix; public: // Sets the given matrices for all shaders void SetProjectionMatrix( glm::mat4 p ); void SetViewMatrix( glm::mat4 v ); /*! \brief Tells the renderer how to render object of type T * \param shd Shader to use for rendering. * \param f Pointer to a function that takes a shader and a T& argument. */ template< typename T > void AddObjectType( Shader* shd, void (*f)(Shader*, T& ) ) { size_t type = typeid( T ).hash_code(); Shaders[type] = shd; RenderFunctions[type] = (RenderFunctionPointer)f; } /*! \brief Renders the given object. * The object type has to be registered before this call. * \param obj Object to Render */ template< typename T > void Render( T& obj ) { size_t type = typeid( T ).hash_code(); ShaderIterator i = Shaders.find( type ); if( i == Shaders.end() ) { LOG_WARNING() << "Couldn't find shader for object: " << typeid( T ).name(); return; } Shader* shd = i->second; shd->SetModelMatrix( obj.GetTransform() ); shd->Bind(); FunctionIterator f = RenderFunctions.find( type ); if( f == RenderFunctions.end() ) { LOG_WARNING() << "Couldn't find renderfunction for object: " << typeid( T ).name(); return; } RenderFunctionPointer rp = f->second; reinterpret_cast< void(*)(Shader* shd, T& t) >(rp)( shd, obj ); } }; Here is some usage to clarify why is a `reinterpret_cast` necessary(this is not code to be reviewed, just rough example of usage): // Init DeferredRenderer->AddObjectType<Asset>(AssetShader.Get(), RenderFunctions::Deferred::RenderAsset ); // Somewhere passing a Asset to external C code( lua ) void* genericRenderable = MyAsset; PassToLua( genericRenderable ); // Lua code calling entity system. SetComponent( DeferredRenderable, genericRenderable ); // The render system processing entities static_cast<Renderable*>(genericRenderable)->Render( DeferredRenderer ); // This calls void Asset::Render( Renderer* r ) // where r is DeferredRenderer { r->Render( *this ); }