HeroEngine's Material Instancing System allows dynamic runtime modifications to the visual appearance of a model by changing the material of a specific instance to use a new texture, shader or material properties (bump, spec, etc). Material instancing is a huge win in games allowing the reuse of a model by making simple switches of the texture for variety. For example, an artist might have created the model of a red brick wall; using material instancing the polygons of the model can be reused but the texture can be switched to that of a stone wall.
Not only does material instancing support dynamic runtime modifications, but it can also be used as a normal part of the area editing process creating a persistent change. The system provides support to changing the features associated with one or more materials associated with an object and updating their properties. There are multiple options on the UI which can be selected for editing and viewed at runtime before saving to the server.
The system also makes it easy to create assets, change their material properties, save them to the asset library and reuse them in any desired area. Without material instancing, if the project required multiple stone walls an artist would have to create individual models for each with their unique texture mapping and use them at the appropriate places. Whereas material instancing saves the efforts of recreating similar materials and allows editing individual properties for the materials. For example, there can be a material named “Material_1” which has a specular map. Selecting the same material, we can update it to undo the specular map such that there will be a new material, say, “Material_2” on the server which will have all the properties similar to that of “Material_1” but won’t have the specular map.
This allows editing the appearance of a model at runtime and making multiple materials which can be used for different objects in an area.
- is a template from which things in the game world are made. An asset instance is an object with a unique ID number, created from an asset. Areas are mainly populated with asset instances instantiated from the Asset Library. Assets own meshes.
- is a single set of geometry, and a reference to the material which it uses. There may be multiple meshes in a model -- for example, a barrel of apples may consist of a mesh for the wooden barrel and a mesh for the pile of apples.
- is a set of textures with defined roles (such as diffuse, normal/specular and macro) and associated properties. A material instance a unique combination of material properties which can be applied to one or more asset meshes. Material Instance Properties can be customized using the Material Instance Properties dialogue.
Changes made through the Material Instance Properties dialogue are represented in a serialized override string. Values which differ from the base material will appear in the string within the _MaterialOverrides property field in the Properties Panel.
The serialization format is as follows.
<serialization format version number> % <instance name> # <hash string for this material instance> [ <diffuse map path>,<diffuse map alpha type>,<normal map path>,<normal map contains specular channel>,<macro map path>,<macro map UV multiplier>,<shader map path>,<shader translucency>,<shader reflectivity>,<texture address mode U>,<texture address mode V>,<polygon attributes>,<animated UVs U1>,<animated UVs V1>,<animated UVs U2>,<animated UVs V2>]
Here is an example of a material override string after changing the diffuse map path. Note that some values are empty and others contain default enumerations which are set by the system.
- Log into any test area where changes won't be persisted (any play instance).
- Using the Asset Library, place two utility cubes in the area.
- Open the properties panel if it's not already visible.
- Select one of the cubes and navigate to the _MaterialOverrides property in the Properties Panel.
- Click on the empty space where the value for "_MaterialOverrides" would otherwise be. A "..." button will appear to the right. Click on that.
- The Material Instance Properties dialogue will appear. Click on the button with the diffuse map file name under "Diffuse/Alpha Map" and select any .dds file you like from the repository. The change you make will be immediately reflected in your viewport and to any other clients in your area instance.
- Press the close button and perform steps 4 - 6 on the other cube you placed in the area. Only, for the second cube, choose a different .dds file from the first. You'll notice that the two asset instances now have separate appearances due to their different material overrides.
Additional information about the dialogue and other customization options can be found on the Material Instance Properties wiki page.
HSL External Functions
There are several external functions available through HSL script.
external function EnumerateMaterialInstanceProperties() as List of String
This function will return the following list of strings which can be use as the "property_name" parameter in the next two functions.
external function GetMaterialInstanceValue( model as NodeRef of Class HBNode, material_name as String, property_name as String ) as String
Retrieves the value of the property corresponding to the given material instance name and the asset instance (model) to which it has been applied.
external function SetMaterialInstanceValue( model as NodeRef of Class HBNode, material_name as String, property_name as String, new_value as String )
Applies the value to the property corresponding to the given material instance name and the asset instance (model) to which it has been applied.
external function ListNodeMaterials(model as NodeRef of Class HBNode) as List of String
Returns a list of serialized override strings which represents the collection of material overrides applied to a given asset instance. This is the same string which will be located in the Properties Panel under the _MaterialOverries field for any selected asset instance.