0
\$\begingroup\$

In my toy engine I currently have a MeshComponent and a MaterialComponent.

psuedo:

struct MeshComponent
{
    Ptr<Mesh> Mesh;
};

struct MaterialComponent
{
    Ptr<Texture> DiffuseTexture;
    Ptr<Texture> NormalsTexture;
};

This is fine, for when a single mesh uses a single material.

pseudo:

Entity entity = CreateEntity();
AddComponentToEntity(entity, meshComponent);
AddComponentToEntity(entity, materialComponent);

But now I want to consider the concept of "sub-meshes" (regions of a mesh that are rendered with a different material, but each sub-mesh shares the parent vertex list). I don't want my Mesh class to know anything about materials, and vice-versa.

What good approaches are there for "joining" multiple MaterialComponent to a single MeshComponent?

I've considered having an entity for each sub-mesh, but that seems brittle (not to mention overkill, as I'm only interested in MaterialComponents).

pseudo:

struct MeshComponent
{
    Ptr<Mesh> Mesh;
    std::vector<Entity> SubMeshEntities; // Would need to ensure the indices match those of the sub-meshes
};

What other approaches are there?

\$\endgroup\$
1
\$\begingroup\$

There is no point putting GFX assets into dedicated components:

  • Assets are allocated outside of a component, no cache locality boost.
  • Most assets are not involved in the ECS update graph anyways.

Components are better reserved for things that have a state that will be processed by the systems running on the CPU (e.g. skeletal and other animations) or must be exposed to those systems (e.g. current physical transforms).

But the compositional part of the GFX department (that consists mostly of the references to the assets and their combinations) would not benefit from the ECS designs, so there is no point shoehorning it into the ECS framework.

Just as with many (mainstream and not) engines, it makes sense to build a single ECS component for housing entire scene graph of an entity. It's a good fit for composing graphics, physics and other spatial components (such as cameras and triggers) together in a single tree.

Because a scene graph has no limits of ECS, you can do the composition the way that seems most natural to you. Do a single renderable that can combine multiple assets, or go for a full blown tree.

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Interesting. The MaterialComponent exists for the RenderSystem to create GPU resources for the textures (e.g. ID3D12Resource*) and to compile a list of things that "can be rendered" (requires multiple different components in order to be classed as "renderable"). \$\endgroup\$ Apr 7 at 23:51
0
\$\begingroup\$

You think wrong that you need to put everything in a component in the ECS. Material can be part of a mesh but nothing else really and you don't have to keep multiple copies of entities in your mesh component. Think of your entity as a model, then:

struct MeshComponent
{
    std::vector<Mesh> meshes;
    std::vector<Material*> materials; // you want to keep the addresses/ids of the materials 
                                      // and not to do copies
}

Where each index i in meshes, corresponds to the material at index i. Then your drawing method would look like:

for(int i = 0; meshes.size(); i++){
    // bind material to shader
    // bind vertexBuffer
    // draw with indices or vertices
}

EDIT: its important to do it in a single draw call

\$\endgroup\$
2
  • \$\begingroup\$ But then the Material class effectively is a copy of the MaterialComponent class, but just exists within the MeshComponent? \$\endgroup\$ Apr 7 at 16:14
  • \$\begingroup\$ Yes, but the material is not a component \$\endgroup\$
    – vikAy
    Apr 7 at 16:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.