Extension development for Horde3D

Introduction

Horde3D has an extension mechanism that can help you to add new functionality to engine without modification of the engine source. There are a number of extensions already available, some of them are in the engine's repository.

Extension interface

Usually extension has the following structure:
- a folder in Extensions directory with the name of the extension;
- Bindings directory that (at least) contains one or several header files in C++ subdirectory;
- Source directory that contains source files for the extension;
- Sample folder that contains sample's source code, if present.

Extension interface consists of two parts: an internal one, that is used by the engine, and the external one, used by application. Internal interface is a class that defines extension initialization and destruction procedures. It is usually defined in header file and its implementation is in source file:

    #include <egPrerequisites.h>
    #include <egExtensions.h>
    
    namespace ExtensionNamespace {
    using namespace Horde3D;
    
    class SampleExtension : public IExtension
	{
	public:
		virtual const char  *getName() const { return "ExtensionName"; }
		virtual bool init();
		virtual void release();
	};

    } // namespace
    

As Horde3D uses a procedural API interface, extension should provide a similar procedural interface to control its behavior. External interface is usually defined and implemented in source file.

    namespace ExtensionNamespace {

        H3D_IMPL void h3dextFunc1()
        {
            // code
        }

    }
    

How to select render interface

Sometimes it is necessary to do different things for different render interfaces, for example, different shaders are used. The following code can help you getting current render interface:

    switch ( Modules::renderer().getRenderDeviceType() )
    {
        case RenderBackendType::OpenGL2:
        {
            // code
        }
        case RenderBackendType::OpenGL4:
        {
            // code
        }
        case RenderBackendType::OpenGLES3:
        {
            // code
        }
        default:
            return false;
        }
    }
    

Adding new pipeline actions

It is possible to add new pipeline actions through extensions. Currently Overlays extensions uses this mechanism. New pipeline action can be added through the following function:

    // Register new pipeline commands
    Modules::pipeMan().registerPipelineCommand( "CommandName", parseFunction, drawFunction );
    

Extension has to provide name of the command, that can be used in the pipeline xml file; parsing function that parses the parameters in pipeline file; draw function that is called when pipeline command is reached during rendering. Pipeline action registration should be done during initialization of the extension.

Registering new uniforms

Extension can register uniforms that would be used in shaders.

    // Register new engine uniform that will be searched for in all loaded shaders
    _uni_extensionUniform = Modules::renderer().registerEngineUniform( "uniformName" );