MovingBlocks / Terasology

Terasology - open source voxel world
http://terasology.org
Apache License 2.0
3.69k stars 1.34k forks source link

Terasology should have layers, like an ogre. #2671

Open emanuele3d opened 7 years ago

emanuele3d commented 7 years ago

This is a request for a new component type: a LayerComponent. Or a TagComponent, or a LabelComponent. The actual name is one of those things up for debate.

In the context of the rendering engine a LayerComponent would be useful. This component would only hold one (string) information: the layer name. By having a layer component a rendering node can find all entities in a given layer and ignore all others.

This would allow, for example, for entities with a mesh components to be rendered at different stages of the rendering pipeline: meshes in the "world" layer would be rendered while rendering the world while meshes with the "sky" layer would be rendered separately.

Notice that an entity should be able to have more than one LayerComponent attached to it, so that the same entity can be rendered (with different shaders) by multiple nodes.

There might be other ways of doing this, perhaps with existing components or inheriting from them. For example an entity with a Mesh component could instead have a SkyMesh component that is exactly the same apart from the name. When it's time to render the sky only entities with SkyMesh components might get rendered. But it feels like a misuse of the component classes.

In any case, I am open to suggestions.

Cervator commented 7 years ago

Oh, oh, you know what else has layers? Cakes have layers! Nobody needs smelly onions.

My initial thought is that we'd want any sort of renderable component to have layer data in it. Which is where again OOP tempts us to give in and make an abstract RenderableComponent that specific renderable things could extend so the base layering stuff is available to all. Temptation leads to the Dark Side.

Rather than a single LayerComponent - how many actual layers could we envision? Is it just World or Skysphere? Maybe a UI layer for meshy things in the foreground?

If you had a very small number of named layer components you could outright qualify in a Node which entities you care about purely through component names, which feels more entity system-y. So you could ask for all entities with CelestialComponent + SkysphereLayerComponent to have a Celestial Node draw planets and moons, while AuroraBorealisComponent + SkySphereLayerComponent would know via DAG ordering that its effects should be drawn in the Skysphere layer later on since it is further in the foreground?

Within layers, say regular objects in the world, it seems more like the responsibility of their LocationComponent and occlusion math to figure out what should render when? Other than when the DAG knows for sure something comes before something else.

As far as multiple Components of the same type being attached to the same entity that's not supported at present and I'm not sure if it would be a good thing - rather substantial architecture switch. But I get the impression that making more Components is relatively cheap. For instance it may be better attaching three unique but empty Components instead of a single Component with three Strings in it (or three copies of the same Component with a single String that differs). I think in the context of the ES it would be faster and more natural to simply look for the presence of a Component than going digging in a Component for actual variables. Also easier to eventually improve with an entity indexing system.

I'm probably not spot on here, but I hope that helps! Happy to dig deeper if this gets you thinking and coming up with more details and explanations :-)

emanuele3d commented 7 years ago

Thank you for the feedback @Cervator. If I think about the sky, it might have the following layers:

Effectively the layers we are discussing here, because of the distances involved, can be considered entirely separate and hence rendered separately. Once a layer is rendered the depth buffer is reset and the next layer is rendered completely behind or completely in front of the previous layer. So, given what you are saying I could just aim to tag entities with components such as "BackgroundTag", "DeepSkyTag", "PlanetaryTag" and "AtmosphereTag".

And another idea that has been sloshing in my head is to convert RenderSystems into layers. I.e. shadowcasting entities would simply need a mesh component and a ShadowCastingTag component. Same goes for semi-transparent objects: attach a SemiTransparentTag component to the entity and the mesh gets rendered by the node handling semi-transparent objects - no need to implement a RenderSystem for it.

I thought of using layers also to connect specific entities to cameras. An example would be cloaked character: it might be invisible from the player camera but it might show up in the feed from an infrared security camera instead. I guess we could implement this again by having renderable entities having a MainCameraTag and an InfraredCameraTag.

Ok, fine, you convinced me. :smile:

emanuele3d commented 6 years ago

I plan to take care of this soon. The changes in the codebase will be minimal.