Skip to content

Sanitize LODCutoff of various blueprints  #3940

@Garanas

Description

@Garanas

Description

As per #3912 all of the game files are now part of the repository. It revealed a couple of skeletons in the closet, one of these skeletons will be described with this issue: the Level of Detail (LOD) of meshes. We've been looking at these properties before, but then in relationship to effects.

Separate mesh blueprints have an impact on the framerate of the game. We can draw a mesh through a draw call. In all simplicity, a draw call is a message from the CPU to the GPU to draw something. The more meshes we render, the more draw calls we have. The more draw calls we have, the lower the framerate. In order to keep the number of meshes we need to render in check we can apply various sorts of tricks. We'll discuss some of these out of interest.

Culling

This is easier to understand after watching this video on Youtube. Culling happens on the GPU by default to prevent doing computations on vertices (points on a mesh) that are outside of the viewport. We can cull earlier however - and instead of culling on vertices and triangles, we cull on draw calls. This is something a lot of games do and it is commonly referenced to as Frustrum Culling. Every modern game engine supports this by default, and so does Supreme Commander according to a graphics study done by Andrian Courreges.

Batching

A usual draw call is like walking to the grocery store for a single item. Walking to and from the grocery store can easily take you half an hour, but once you're at the grocery store you can retrieve the item in a minute. If we'd do this for every item that we need for our dinner recipe then it could easily take the entire day due to the overhead of walking to and from the grocery store.

Luckily, we can think ahead and make a list of items that we want to acquire from the grocery store. By doing so we can amortize the overhead of going to and from the grocery store over the number of items on our list. We can apply exactly the same idea to our draw calls: instead of rendering one mesh at a time we can queue up calls that are similar and render them all at once.

The metaphor is easier to understand after watching this video on Youtube. Luckily, the game already does this for us where props, projectiles and units of the same type are batched together.

Level of Detail

Another method of culling is by gradually reducing the quality of an object as it gets further and further away from the user perspective. This is particularly relevant when the camera of the game allows you to look at content at great distances, such as in Supreme Commander via the strategical zoom. This value has to be set manually. It determines when it is still worth rendering the mesh in question. And that is where this pull request comes in: one skeleton in the closet is these LODCutoff values being all over the place. We'll need to sanitize that.

Course of action

You can find a complete list of skeleton-like values here:

You can ignore unit blueprint IDs (such as ues0401) and the majority of prop blueprints (those that end with _prop). We're primarily interested in sanitizing the values of separate mesh entities and of projectiles, as the average prop is already sanitized based on scale by #3662 . Because of this, you can find the majority of skeleton blueprints in the effects and the projectiles folder.

As an example we'll take the Aeon adjacency node. It is described using this mesh blueprint:

MeshBlueprint {
    LODs = {
        {
            ShaderName = 'TMeshNoNormals',
        },
        UniformScale = 1,
    },
}

This appears to be quite empty, and that is because it is. The engine has a set of default values for various fields. The complete blueprint looks like this:

  - BlueprintId: /effects/entities/aeonadjacencynode/aeonadjacencynode_mesh
  - BlueprintOrdinal: 3
  - Description: 
  - IconFadeInZoom: 0
  - LODs: table: 17B8D528
  -    1: table: 17B8D550
  -       AlbedoName: /effects/entities/aeonadjacencynode/aeonadjacencynode_albedo.dds
  -       LODCutoff: 1000
  -       LookupName: 
  -       MeshName: /effects/entities/aeonadjacencynode/aeonadjacencynode_lod0.scm
  -       NormalsName: 
  -       Occlude: false
  -       Scrolling: false
  -       SecondaryName: 
  -       ShaderName: TMeshNoNormals
  -       Silhouette: false
  -       SpecularName: 
  -    UniformScale: 1
  - SortOrder: 0
  - Source: /effects/entities/aeonadjacencynode/aeonadjacencynode_mesh.bp
  - StraddleWater: false
  - UniformScale: 1

Note that the layout is different because we printed it in game. This shows the issue: the LODCutoff value (that determines when to cull the mesh) is there, but its default value is set to a 1000! For your idea, that is the same value that is used for shields. And we're talking here about missiles and other small meshes that nowhere near correspond to the size of shields.

To fix this we can add the field ourselves:

-- Used by Aeon Adjacency nodes
MeshBlueprint {
    LODs = {
        {
            ShaderName = 'TMeshNoNormals',
            LODCutoff = 200,
        },
        UniformScale = 1,
    },
}

Note that the value is capital sensitive: it should be LODCutoff. It is also scope sensitive, it should be inside a table of the LODs table. The LODs table can have multiple entries. This isn't usually the case for these type of meshes.

Test plan

The coarse of action is to create a new branch that is based off deploy/fafdevelop. You can adjust up to 4 to 6 blueprints per branch. For each change, make sure to indicate (as a comment in the blueprint, or as a comment on Github) where we can see the change in question. Take an example of the pull requests done by @Ejsstiil, they are very informative and because of that they are relatively easy to check and merge.

Learning goals

To be more comfortable with working with Git and the repository in general.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: simArea that is affected by the Simulation of the Gamegood first issueissue that is relative easy to pick up

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions