glTF (model format)

glTF model from Sketchfab
glTF model
glTF model from Sketchfab

1. Introduction

glTF is an efficient, modern format for animated 3D and 2D models. Developed by Khronos.

We advise using it in CGE as much as you can. It is supported by a lot of tools. We focus on supporting this format perfectly in Castle Game Engine, with all the features and efficiency.

3. Supported Features

  • Meshes (polygons, lines), transformation hierarchy.

  • Materials (with physically-based or unlit shading, internally implemented using X3D 4 materials, designed for glTF compatibility), alpha mode, double-sidedness, per-vertex colors.

  • Texturing (for base color, normal maps, emissive, material-roughness).

  • Animating transformations (position, rotation, scale) and using skin ("armature" in Blender). They can be played using standard CGE PlayAnimation method (or other means, e.g. to play multiple animations from one model simultaneously).

  • Cameras (perspective and orthogonal). Camera transformations can be animated too.

  • Punctual lights (point, spot, directional lights).

  • Both .glb and .gltf extensions are supported. Textures can be provided in separate files or embedded inside the GLTF stream.

  • It is integrated in our engine as X3D nodes graph. This means that you can include a glTF model inside larger X3D file using the Inline node, you can modify the glTF scene graph at runtime (e.g. modify material color, show/hide something etc.) and you can serialize the scene graph to an X3D file.

  • Collisions automatically work (as with all other scene formats), you only have to initialize Scene.Spatial (see the manual). By default, static meshes have precise collisions (treating them like a set of triangles), while skinned-animated meshes collide as simple bounding boxes (so they don’t cause a slowdown when animating). This can be even customized per-shape by adjusting Shape.collision property.

  • We apply gamma correction automatically on PBR materials. You can request to apply it on all materials (including unlit) to follow glTF spec in 100% easily.

  • We read glTF "extras" data that can be defined by your authoring tool, for example in Blender this is defined by "Custom properties". This allows to pass any custom information from Blender to the engine, for use in your own applications, or to influence the import — see Custom properties in Blender.

  • We use PasGLTF, a great open-source library for reading glTF by Benjamin "Bero" Rosseaux.

TODO: Main missing glTF feature is morph targets. It is coming!

4. Attaching objects to bones

This is available using TCastleScene.ExposeTransforms. You can "expose" a bone transformation as TCastleTransform child and attach there a scene. See https://castle-engine.io/wp/2020/10/09/attach-objects-to-animated-bones-like-weapon-in-characters-hand-by-exposetransforms/ .

5. Collisions when your glTF mesh uses skinned animation

For speed, the shapes animated using skinned animation in glTF uses bounding box for collisions. That’s because the triangles would change every frame and updating the octree would have a significant cost for FPS.

If you need to have better collision detection:

  1. You can use X3D file that uses Inline to include 2 glTF files. One of them would be your animated model, but not collidable. The other would be a static model, invisible, used only for collisions.

    This means that your model keeps working fast (as opposed to solution 2 below). And the collisions are resolved with respect to precise triangles. However, the triangles remain static, unaffected by animation.

    To do this you would create a file like mycreature.x3dv with content:

     #X3D V3.2 utf8
     PROFILE Interchange
    
     Collision {
       proxy Inline { url "mycreature-collidable-invisible-notanimated.gltf" }
       children Inline { url "mycreature-animated-visible-notcollidable.gltf" }
     }

    And then in game, you open castle-data:/mycreature.x3dv instead of opening any glTF file directly. Playing all animations on mycreature.x3dv should work exactly as in mycreature-animated-visible-notcollidable.gltf, it exposes the same animations.

  2. If you desperately need precise collisions, and the collision structure has to be updated at runtime, and you can tolerate some performance loss (it may be acceptable for smaller models) then you can find TShapeNode occurrences in the model, and change the TShapeNode.Collision from scBox to scDefault.

    Like this:

     procedure TMyState.Load;
     var
       Model: TX3DRootNode;
     begin
       Model := LoadNode('castle-data:/example.gltf');
       Model.EnumarateNodes(TShapeNode, @HandleNode, false);
       Scene.Load(Model, true);
     end;
    
     procedure TMyState.HandleNode(Node: TX3DNode);
     begin
       (Node as TShapeNode).Collision := scDefault;
     end;

6. Switching to Phong lighting model (for performance or just different look)

glTF models use PhysicalMaterial or UnlitMaterial for their materials.

The PhysicalMaterial node performs physically-based rendering which is very pretty but also comes with some performance cost. It also requires Phong shading (not faster Gouraud shading) to make sense.

If you need maximum speed, you can set global GltfForcePhongMaterials to true. This automatically converts (during load) all PhysicalMaterial nodes into Material nodes (using Phong lighting model, and Gouraud shading by default). Note that it will change the look of your models significantly. So if you want to go this way, you should probably prepare your models from the start testing it.

Of course, remember that you can also use unlit materials in glTF. These always have the best performance :) Blender can export glTF unlit materials.

7. Gamma Correction

The PhysicalMaterial, used by most glTF models, has Gamma Correction turned on by default.

  • If you need maximum speed, consider disabling gamma correction, by GammaCorrection := gcNone.

  • If you need maximum glTF compatibility, consider enabling gamma correction for all materials (PhysicalMaterial, UnlitMaterial, Material), by GammaCorrection := gcAlways.

Note that enabling or disabling gamma correction will change the look of your game. So you should make a decision about it early on — and test your models look with the desired setting.


To improve this documentation just edit the source of this page in AsciiDoctor (simple wiki-like syntax) and create a pull request to Castle Game Engine WWW (cge-www) repository.