MovingBlocks / Terasology

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

Integration of entity-based LightComponents with Light Propagation / Voxel Lighting #2601

Open emanuele3d opened 8 years ago

emanuele3d commented 8 years ago

Currently Terasology handle point-like lights in two separate ways, the output of which is combined via shaders.

The first method is somewhat more traditional (fully shader-based) and handles the lighting produced by entity with a LightComponent attached to them. An example of this is the held-in-hand torch of a player.

The second method handles lights placed in the landscape, i.e. torches placed on the ground or attached to a tree. These lights are not entity-based but at are light-emitting blocks instead. These are handled via Voxel Lighting / Light Propagation, a method involving a cellular automata-like algorithm.

Ideally, we'd like to eliminate the first method and handle all or most lighting through the second method, probably making exceptions for purely directional lights i.e. the sun/moon.

The rationale for this is that the Voxel Lighting / Light Propagation system produces nice visual features such as "around the corner" lighting and shadows with reasonable performance (1). Conversely, it would be quite difficult to have those features with the first method and they would be very computationally expensive.

(1) See https://www.youtube.com/watch?v=OkPL3HvYqVM

OvermindDL1 commented 8 years ago

While still having a method to get the light level of a given block?

emanuele3d commented 8 years ago

Dear @OvermindDL1, your question is obviously very clever but my smallmind just cannot make sense of it in the context of the description of this issue. Would you care to elaborate and give a chance to individuals with lesser intellects to understand your concern?

portokaliu commented 8 years ago

I think he might be referring to the method in "WorldProvider" /* * Returns the light value at the given position. * @param pos The position * @return The block value at the given position */ byte getLight(Vector3f pos);

OvermindDL1 commented 8 years ago

I think he might be referring to the method in "WorldProvider"

Precisely, yes, sorry. Busy day. :-) Many lighting suggestions I've seen around make that call more difficult. Hence my curiosity on how such a proposal would affect it.

smallmind

What is that about?

emanuele3d commented 8 years ago

smallmind: self-deprecating flunked humor - nevermind :smile:

Thank you both for clarifying the concern.

If all/most lighting goes through the voxel lighting method per-block light levels should still be very easy to obtain: the per-block data will still be there but it will also take in account the input of dynamic lights, which right now I don't makes it into the per-block light levels.

No need to worry about imminent changes though: unless somebody picks up this issue I do not intend to work on it any time soon.

eviltak commented 7 years ago

Do all the entities that use the first method use LightComponent? If not, what's the best way to identify these objects? I'd love to work on this.

emanuele3d commented 7 years ago

@eviltak: I would say the answer is yes, all lights affecting the world via the more traditional deferred lighting rendering path are entities with a LightComponent attached to them. Notice that if you look at the code related to the MainLight (sun/moon) that only -stores- the light information in a LightComponent but doesn't attach it to any entity. So, that's handled completely separately.

Tagging @Josharias and @skaldarnar for confirmation.

eviltak commented 7 years ago

@emanuele3d So we're looking at ALL entities having a LightComponent only of the POINT type, correct? I reckon that directional lights won't be simulated well with voxel light propagation.

emanuele3d commented 7 years ago

Short answer: yes.

Longer answer: I don't think the current LightComponent implementation makes much sense for directional lights, intended as lights producing parallel light rays, i.e. from astronomical sources. A number of attributes in the LightComponent are really unnecessary for directional class.

I haven't had the time to really look into this and either change it myself or write an issue about it, but I suspect the LC could be broken in smaller components that can be better mix&matched. So, a directional light might be an entity with a BaseLightComponent (containing only information regarding color/intensity) and a LocationComponent interpreted as a unit-length direction vector. Meanwhile a Point Light could be any entity with a BaseLightComponent, a LightLimits component and a LocationComponent, this time interpreted as a proper position.

I really haven't thought about the consequences of all this but this could be a way forward. Feel free to look into it and come up with proposals.

skaldarnar commented 7 years ago

[...] and a LocationComponent interpreted as a unit-length direction vector.

I advice against using components for a different purpose. The LocationComponent should onyl be used for locations, everything else is just confusing. A DirectionComponent might have the same interface and implementation, but it is clear by naming what its intention is.

Meanwhile a Point Light could be any entity with a BaseLightComponent, a LightLimits component and a LocationComponent, this time interpreted as a proper position.

This sounds like "correct" usage of the components. Just from looking at the PointLightEntity, you can guess that its a light located somewhere in the world.

emanuele3d commented 7 years ago

@skaldarnar: you make a good point about avoiding misuse of existing components. Ok, let's eventually use a DirectionComponent then. Thank you for pointing it out.

eviltak commented 7 years ago

Combing through and testing the code, I reckon it is currently not possible to implement this in an efficient way. The method I've thought of is setting the luminance of the block containing the light position (only the single block for now). But owing to the current voxel lighting architecture using Propagators, we have to keep track of the blocks that were changed, unset the changes after every frame, and recalculate (repropagate) the lighting two times (once after every block change set/unset). This can be circumvented by using a dynamic voxel lighting system, but that will require a not very small rendering pipeline change/addition, something for which I may not have enough experience with the Terasology architecture.