Advertisement

Breaking higher level ECS components up into lower level components

Started by December 13, 2021 10:32 AM
2 comments, last by mr.otakhi 3 years ago

I am writing my own rendering engine using the entity-component-system approach using EnTT. My idea is that I don't want to hard code my engine too much. I want to leave it open for the user to extend with new components and support writing their own shaders with framebuffer configurations. I do this more for myself to experiment with rendering techniques.

These are a selection of components I have. The example uses OpenGL terminology.

  • Mesh component: Contains pure vertex data, such as position, normals, uv coordinates and tangent data. Render system uses it to create and fill vertex buffers and stores the id's (vbo, vao) in the Renderable object.
  • Material: Contains properties of the material (i.e. uniforms, textures used, shader file names). Render system uses it to compile vertex shader/fragment shader (material contains path to the shaders). Program id is stored in the Renderable component. Material system updates the material properties to the program every frame. So MaterialSystem and RenderSystem are both OpenGL specific.
  • Renderable: Component that contains all the state needed to perform glDraw* calls. I try to put the OpenGL state exclusive in the Renderable component.

It works fine up to now. The question that I have is:

1. How to deal with “higher-level components/materials or postprocessing effects”? These require multiple passes and different framebuffer configurations, chaining them together.

I am struggling with how to approach these higher order effects into the ECS analogy. Take for example Bloom, that can be represented as a multi-pass approach with multiple materials (i.e. brightness extraction, blurring, blend).

My idea is:

  • Create a bloom component and bloom system.
  • The bloom system creates a set of entities with material components reflecting the state of the bloom component.
  • The bloom system updates every frame (or triggers only when parameters are changed) and reflects those changes to the parameters.

Like bloom, there will likely be more higher level components (shadow for example).

2. Is it a proper approach to write systems that add lower level components based on a higher order component? These systems actually act more as factories with the added responsibility to keep the parameters in sync.

Could anyone shine a light on whether my thinking is correct or whether it's considered bad practice?

IHMO, this is a way too granular level of using ECS. You should design your renderer without ECS in mind, and then have ECS configure the renderer in a way where optimally you have one component per construct. For example, just have a MeshRenderer (which has its mesh, its materials etc…) and the system creates the necessary resources to render that mesh. That way, if somebody wants to right a different implementation for the renderer, he can create another simple component (ProceduralMeshComponent, for example) which also uses the base-render framework and doesn't have to manage 10 different components.

As for something like bloom, again I would personally not make a “bloom” component, this doesn't really make sense (are there going to be 10 “blooms” in the same scene? probably not). For one-off effects in the scene, you can make a “PostProcessing”-component, which takes a specific material used for post-processing and handles the whole stack of scene-effects. For more complex things like bloom where you need multiple passes, I'd again say that this is probably not the best to put in an ECS. I can't think of a way to make it work without being absolutely brittle and unstable (in usage). I personally use a node-based render-interface for configuring the more complex effects, which would still allow users to implement effects themselves, but is easier to use in that regard than a pure ECS implementation.

Advertisement

Check out our OO web game engine.

https://www.otakhi.com/

https://www.otakhi.com/public/document

We allow users to wrap lower level code, scripts, and GUI components into Objects that can be shared online.

Our approach is top-down using UML which is more natual since object design requirement comes from end users not the developers. ECS approach means the behavior of the root class is fixed and dictated by the developer, while our approach does not suffer from this rigidity. For those programming nerds, this is partially due to our use of OBJECT COMPOSITON rather than INHERITANCE.

View a sample object here: https://www.otakhi.com/detail/16622

This topic is closed to new replies.

Advertisement