Similarly to common rendering APIs, the triangle winding order of an Object has to be specified for the Umbra Optimizer. The triangle winding order specifies which triangles are considered to be facing the camera and which are classified as facing away from the camera. The winding order is determined for each Object by specifying the winding argument when calling Umbra::Scene::insertObject(). The options are Umbra::WINDING_CCW (the default value), Umbra::WINDING_CW and Umbra::WINDING_TWO_SIDED. When specifying counter-clockwise winding order, triangles are considered to be facing the camera if the vertex order of a triangle’s screen-space projection is counter-clockwise, or vice-versa if Umbra::WINDING_CW is specified. This is illustrated in the below image. If Umbra::WINDING_TWO_SIDED is specified, triangles are always considered to be facing the camera, regardless of the vertex order of the triangle’s screen-space projection.
Illustration of an triangle with two different winding orders.
The reason why the winding order is a property of an Object instead of a Model, is that an Object may be transformed in a manner which affects the triangle winding order. For instance, if an Object is mirrored about a plane, the triangle winding order gets reversed.
WHY THE WINDING ORDER MATTERS
The Umbra 3 Optimizer needs to know which way a triangle is facing from any given point inside the computation bounds. The Optimizer uses this information to classify areas in the scene as inside or outside. In this context, inside means that the location is a valid area of the scene into which the camera may freely move. In contrast, outside is an area in which the camera shouldn't be able to be located. Places from which a lot of back-facing geometry is visible to the camera are classified as outside. Consider, for instance, a location inside a thick wall, or under the terrain. If the camera were positioned in such a location, the majority of the geometry would appear as back-facing to the camera. See the below image for an illustration. Umbra, in turn, uses this information to greatly reduce the amount of visibility data it generates and to simplify its output in such locations. This is why it is important not to define all geometry as two-sided (Umbra::WINDING_TWO_SIDED), even though it might be tempting, as it makes it impossible for Umbra to distinguish between inside and outside locations, and consequently to do such optimizations and simplifications. This, in turn, will result in an increased runtime memory footprint. Thus, two-sided vertex winding should only be used when the corresponding model is truly two-sided.
Illustration of the concept of inside and outside geometry.
The threshold beyond which a location is considered to be outside is controlled by the back-face limit computation parameter. Please refer to Choosing Optimizer computation parameters for more details.