Building HOOPS Luminate Materials

This book covers all the practicals aspects of material management in HOOPS Luminate. Materials are shapes attributes, as detailed by the Shape Attributes in a Scene Graph page. A material defines the rendering look of a shape or of a tree of shapes below the node that owns the material, thanks to the material inheritance rules in HOOPS Luminate. Materials are shared among shapes: all shapes with the same rendering look should use the same material.

Terminology

A material defines the way a shape is rendered. A material is composed of shaders, that are organized in rendering passes. A shader is either dedicated to the rendering (a RED::RenderShader), or dedicated to configuring the rendering (a RED::StateShader).

A shader dedicated to the rendering is composed of programs executed on the graphics hardware or in software. Among these programs, we find the vertex program, the pixel program and the geometry program. These are also called vertex shaders, fragment shaders and geometry shaders in the literature.

A rendering pass consists in drawing the scene geometry once, for the purpose of a given effect.

Contents

This book contains two key parts:

  • Using Built-in HOOPS Luminate Materials: if you want a ready-to-use material, please follow this link. We’ll detail the various materials that exist in HOOPS Luminate and how to setup them for different purposes.

  • Writing a Custom Material: if you want materials dedicated to a specific task, you may want to write your own material. Don’t be scared, this is something easy if you rely on built-in HOOPS Luminate shaders. This book chapter details all the HOOPS Luminate built-in shaders as well as how to write your own shader.

And then we can review some other important topics in material management with HOOPS Luminate:

  • Material Layersets: Learn how layersets interfere with the definition of materials and shaders.

  • The Material Controller: The material controller builds a semantic layer on top of a material to customize it’s control for any kind of need.

  • The Shading Pipeline: Please review this chapter if you’re interested in the HOOPS Luminate shading pipeline. We detail a number of important concepts here and how shaders are assembled together and rendered to compose the final image.

  • Rendering Priorities: Learn how to control rendering priorities with a material. This is a must for all use cases where sorted rendering takes place.

  • Controlling Material Batching: This chapter covers very specific HOOPS Luminate material usage, to get the best rendering performance during the manipulation of heavily dynamic geometries, or if a very precise data organization into the memory is targeted by the application.

Using Materials

HOOPS Luminate materials are created and destroyed by the cluster’s resource manager. Materials are shared resources across all scene graphs defined in the application cluster. First, let’s learn how to create or to destroy a given material. The task below illustrates the way to proceed:

Creating and Destroying Materials

// First, get our resource manager and access its interface.
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

// Then, create a material from it:
RED::Object* material;
RC_TEST( iresmgr->CreateMaterial( material, iresmgr->GetState() ) );

// Release the material after use:
RC_TEST( iresmgr->DeleteMaterial( material, iresmgr->GetState() ) );

As you can see, material creation and destruction is simple using the RED::IResourceManager interface. However, attention must be paid to the fact that a material must not be used by any shape at the time it’s destroyed. HOOPS Luminate does not invalidate possible references to the destroyed material that may exist in the calling application. This is the responsibility of the application to ensure that a material that is destroyed is no longer used by any shape being rendered. HOOPS Luminate will detect invalid materials used during a draw and will return a RED_SCG_DEAD_MATERIAL_ADDRESS error code if this happens.

It’s also a common way to proceed to duplicate an existing material. For instance a material template is loaded from a .red file and duplicated to be modified later on by the application. In this case, the following task applies:

Loading and Duplicating a Material

// Access our resource manager:
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

// Access the data manager:
RED::Object* datamgr = iresmgr->GetDataManager();
RED::IDataManager* idatamgr = datamgr->As< RED::IDataManager >();

// Load a material from a .red file:
RED::Object* redfile = RED::Factory::CreateInstance( CID_REDFile );
if( redfile == NULL )
    RC_TEST( RED_ALLOC_FAILURE );

RED::IREDFile* ifile = redfile->As< RED::IREDFile >();

RED::StreamingPolicy policy;
RED::FileHeader header;
RED::FileInfo finfo;
RED::Vector< unsigned int > contexts;

RC_TEST( ifile->Load( "MyMaterial.red", iresmgr->GetState(), policy, header, finfo, contexts ) );

// Get the first material (assuming there's one in the file!):
RED::Object* material;
if( contexts.size() != 0 )
{
    unsigned int mcount = 0;
    RC_TEST( idatamgr->GetMaterialsCount( mcount, contexts[0] ) );

    if( mcount > 0 )
    {
        RC_TEST( idatamgr->GetMaterial( material, contexts[0], 0 ) );
    }
}

// Now, duplicate the material, without duplicating large images:
RED::Object* material_copy;
RC_TEST( iresmgr->CloneMaterial( material_copy, material, iresmgr->GetState(), false, true ) );

We must pinpoint the two boolean options of RED::IResourceManager::CloneMaterial in this task: A material generally uses a lot of images. Among them, we find tiny 1x1 pixel images used by HOOPS Luminate shaders that perform texturing (for consistency, a built-in HOOPS Luminate shader generally uses either no texture to source its parameters, or all its parameters are turned into textures; therefore, we have many tiny 1x1 textures that may be used as replacement for colors if we’re using texturing); and we have large images that are generally the source images used for the material.

The RED::IResourceManager::CloneMaterial method lets you clone or share all images in the material. This is important from both a memory management perspective and also for edition needs. If a cloned material shares all its images, then any change in the material parameter will probably modify an image that is shared by both materials. If a cloned material duplicates tiny images and share other images, then modifying a small image (generally a color that was set with no texture) will modify only the cloned material.