- DelphiTools - https://www.delphitools.info -

FireMonkey’s TCube & Tessellation

a cube [1]If any of you had a look at FireMonkey’s TCube object, you might have noticed rendering it is quite slow and quite complex.

If you were curious enough to look at the code, you might have noticed that TCube is actually a static mesh made up of 452 vertices, 1440 indices and 480 triangles, instead of the 8 vertices and 6 quads (12 triangles) one could have expected.

That explains why it’s slow… and when looking at the indices, there are more oddities: some coordinates aren’t properly rounded (you can find -1.11759E-8 instead of zero), normals aren’t normalized, and the tessellation doesn’t seem to be the same for all the faces. There is probably an interesting story behind that cube…

That said, why would one want such a complex  cube? Though none of the uses described below apply to TCube, it allows to introduce the subject of tessellation.

Per-Vertex lighting

When lighting an object in 3D, there are two ways to go about it, the historical one (before pixel shaders [2]) was to use per-vertex lighting [3], with per-pixel linear interpolation, aka “Gouraud shading”. In such a case, if the light is close to the cube, or if the cube is fairly large, you would have artifacts, because the lighting wouldn’t be computed everywhere.

Using GLScene [4], I’ve illustrated the effect below on a single face (click to enlarge) of the effects of subdividing on per-vertex lighting, you can also download the source + precompiled executable [5] (403 kB) if you want to see it more interactively

Subdivsions and per-vertex-lighting illustration [6]

The closer the light is to a surface, the more subdivisions you need, which means that to get correct lighting with per-vertex lighting, you need a fairly high triangle count. Hence this technique wasn’t too practical, and you usually had to go for tricks (such as using lightmaps [7], decals [8], etc.) or vary the subdivision dynamically to minimize the performance impact. F.i. even though the FMX TCube is quite heavy, it’s nowhere near as heavy enough to achieve good per-vertex lighting quality with a close light-source.

Nowadays however, you have hardware pixel shaders, which allow you to compute lighting not per-vertex, but per-pixel, so you can obtain an image similar to the rightmost one above, with only two triangles.

CubeDeformations and vertex shaders

Deformations and vertex shader maths are one first use, like in the Blender [9] picture to the right.

A common mesh manipulation tool, linked to deformation or extrusion tools,is to start from a basic geometric form, with more triangles than strictly necessary, and work on those triangles to achieve a not-basic geometric form.

Another use would be to make a dynamically deforming cube, that would bounce and warp at runtime. For that you would need a vertex shader or CPU-side geometry processing. A variant would be displacement maps [10], but that usually requires a high number of vertices.

In both those case however, you’ll obviously want to control how much the faces should be subdivided, and in practice, you’re entering the area of controlled mesh tessellation, and leaving that of a simple cube object.