The Model and its Textures

The model used in this demo consists of a mesh in the form of a glTF file and a set of textures as .jpegs. These textures provide all that is required for a very life-like, detailed result. They include albedo, normal, roughness, metallicity, ambient occlusion, and emissive.

Most of these values measure a type of reflectiveness factor, so are between 0 and 1. It would not make physical sense to have values greater than one, as the object cannot reflect more light than is coming in. Realistic materials have values in the 0.1~0.9 range. A notable exception is the emissive map which can technically have any non-negative value since it is outgoing energy and not reflectivity.

In this example the Damaged Helmet model is being used. The model files can be found at:

The model can also be viewed in 3D here:

This section will show how all of the files included with the model were processed to get them ready for use in the demo.

Model Description (damagedHelmet.gltf)

glTF is a file format which can be used to store 3D models and scenes.

A glTF file consists of a description of the model or scene in a human-readable and human-editable JSON format. This includes descriptions of the textures and meshes used in the scene or model. In this demo, the model description file was called damagedHelmet.gltf.

damagedHelmet.gltf was edited to change the associated textures: A GLTF editor works perfectly fine here, but it is good to take the opportunity to show how easy it is to edit the GLTF format.

Note: For a binary GLTF an editor would not be optional.

The edits made to this GLTF file were:

  1. Replacing the .jpg texture references with the .pvr versions

    This was done by replacing the URIs for the images supplied with the model with the ones created for the demo.

    For example, "uri" : "Default_albedo.jpg""uri": "Default_albedo.pvr"

  2. Removing the separate ambient occlusion (AO) map and replacing it with the red channel of the occlusion-roughness-metallic map.

    This was done by:

    • Replacing the reference to the AO image with the occlusion-roughness-metallic image: {"uri": "Default_AO.pvr""uri": "Default_occlusionRoughnessMetallic.pvr"}

    • Replacing the reference to the AO texture with the occlusion-roughness-metallic texture: **REPLACE**"occlusionTexture" : { "index" : 4 } with "occlusionTexture" : { "index" : 1 }``

Mesh Data (damagedHelmet.bin)

This is the companion to the GLTF file, containing the binary data of the model, or more specifically, the vertex data. This file is downloaded with the model and can be left as-is.

Note: This could potentially be compressed with something like Draco, but in this case the benefit would be minimal as the size of the textures, even compressed as PVRTC, completely dwarfs the vertex data.

Optimising the model textures

In order to get the best performance out of an application some additional processing is useful for the textures.

It is recommended that these textures should be:

  1. Packed as much as possible

    This means no one or two-channel textures if it can be avoided. The textures are all sampled at more or less the same time, so needing multiple commands to fetch will degrade performance.

  2. Converted to PVRTC

    The recommended formats for textures are usually PVRTC or PVRTC2 with 4 bits per pixel (4bpp), or, if a slight quality hit is acceptable, PVRTC or PVRTC2 with 2 bits per pixel (2bpp).

Note: Remember, when using PVRTC the Alpha channel cannot be used to pack material information. This is because the alpha channel is one-bit punch-through, so can only store a 0 or 1, not a range of values. The alpha channel can only be used for information that can fit in one bit, so is normally used for alpha testing.

The rest of this section will focus on processing all of the textures to match these recommendations.

Albedo (Default_albedo.pvr)

This file contains all the reflectivity information.

Note: Albedo and reflectivity are just technical words for the colour of the material in normal, white light.

It is an R8G8B8 texture and normally also contains the transparency information. It is created by transcoding the supplied texture, Default_albedo.jpg, to PVRTC using PVRTexTool.

The transcoding process in PVRTexTool is very simple:

  1. Open the file with PVRTexTool

  2. Select Edit→Encode

  3. ChoosePVRTCII 4bpp from the list of available formats

  4. Set PVRTC Encoding Mode: Very High (Best Quality)

  5. Select Save.

PVRTexTool Texture Encoding Window

Normal (Default_normal.pvr)

This contains information about the medium-scale geometry of the surface of the object. This can include things like the object's texture, micro-bumps, scales, pebbles, and scratches.

This is an R8G8B8 texture and again is created by compressing Default_normal.jpg using PVRTexTool as was done for the albedo map.

Emissive (Default_emissive.pvr)

This file contains information about self-emitting light on the object, such as LCD panels or LEDs. This is also normally R8G8B8 normalised byte but conceptually could be HDR. This map was transcoded as 2bpp although this was mostly for illustration purposes.




Occlusion-Roughness-Metallic (Default_occlusionRoughnessMetallic.pvr)

This texture is an interesting patchwork. It contains three different texture maps within the same file:

  1. The ambient occlusion (the shaded areas of the object) - stored in the texture's red channel

  2. The roughness - stored in the texture's green channel

  3. The metallicity - stored in the texture's blue channel.

The roughness and metallicity are extracted from Default_metalRoughness.jpg while the ambient occlusion is extracted from Default_AO.jpg.

The original AO map is black and white, so all of its channels contain the same information. This means only a single channel is required to store all of the ambient occlusion information. The metallic/roughness map is green and blue, so it makes sense to use this map as the input and replace its red channel with the red channel of the ambient occlusion map. This is an example of packing a texture to ensure each channel contains useful information.

As mentioned before, textures should be packed as much as possible. This improves performance as the application does not have to load or access as many textures files.

The PVRTexTool command line interface (CLI) makes shuffling channels like this really easy.

The command to do this particular operation with the PVRTexTool CLI is:

PVRTexToolCLI -i Default_metalRoughness.jpg -f PVRTC2_4 -q pvrtcbest -red Default_AO.jpg,r -o Default_occlusionRoughnessMetallic.pvr

Translating for those not experienced with PVRTexTool, this command says:

  • Transcode the file Default_metalRoughness.jpg into PVRTC2 4bpp using best quality

  • Replace its red channel with the red channel from Default_AO.jpg

  • Output the results as Default_occlusionRoughnessMetallic.pvr.

For more information about PVRTexTool commands refer to the command PVRTexToolCLI - help.