godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Improve the 2D light system by adding additonal OR blend mode. Add ability to easily check if object is light or unlit #7367

Open LordBrkica opened 1 year ago

LordBrkica commented 1 year ago

Describe the project you are working on

Strategy game

Describe the problem or limitation you are having in your project

Warcraft 2 is a bit less than 30 years old.

Here we see an example of how light works in that game: image

The units and buildings are the sources of players light. So on this image we have 5 sources of light, 5 Point lights if you wish.

However as we see the intesection of all of those lights does NOT add up.

There is no ADD Blend on the terrain between the units and bulidings instead we see a OR blend (so the light of the units and the light of the bulidings is NOT added).

Such a system seems to me very intuitive and appropriate for its intendent use.

Sadly there is no such system in Godot.

II) Additional point that is missing from the current Godot light system is the ability to check (quickly via code) is an object within a light source.
One might "hack" this via raycasting but good luck raycasting in 360degree radius for EACH unit AND building on a map.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I) Implement a new light blend moder "OR"

II) Add the ability to check is an object currently lit.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I have no idea ho to implement it in godot source code.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No.

Is there a reason why this should be core and not an add-on in the asset library?

I dont see these features as something exotic but rather something basic which will be used a lot.

KoBeWi commented 1 year ago

Seems like duplicate of #891 (check it for a workaround)

LordBrkica commented 1 year ago

Seems like duplicate of #891 (check it for a workaround)

I just found a workaround. Instead of lights, I'm now using sprites with additive drawing mode, drawn over screen-sized black rectangle which then draws over everything else in multiplicative mode.

So your workaround is to NOT use lights ? :D

This is how I worked as well. Workaround, workaround, workaround...

Mine was to simply have a TileMap with high Z index that acts as "Darkness" layer.

Every tile that is set is of course visually dark.

The advantage of this workaround is that you may also easily add another tile type and handle discovered but not visible tiles (so the semi-darkness area): image

Another advantage is that each unit may check is it standing on dark tile by simply calling darkMap.GetCellv(position).
So its easy to programatically act accordingly if one needs to do so.

The limitation of my approach is that it works easy as long as your units are relatively small and comparable to a tile size (thats why I am not using my own solution - I work on a project that is no longer satisfiying that criteria).

But the main thing here is that both of us wanted to use light as one might intuitively use it and we both ran into limitations that ended up with us simply ditching the use of light2D.

Zireael07 commented 1 year ago

I'm like 99% certain Warcraft 2 didn't use lights but used sprites. If you want to recreate Warcraft 2 look, you probably shouldn't be using light2d. (Not to mention sprites are rarely fillblocking unlike light2d)

KoBeWi commented 1 year ago

AFAIK 2D lights are for advanced effects with shadows and/or normal maps. Hence they are not really suitable for simple effects.

LordBrkica commented 1 year ago

I am not making a Warcraft clone, I am showing you how/why one might have a need for an additional blend mode AND for the ability to check if an object is lit or unlit.

And I disagree with the argumentation of 2D lights being unsuitable for simple effects, obviously they are unsuitable in the way they exist now but the whole point of a proposal is to show possible improvements to the engine.

Calinou commented 1 year ago

AND for the ability to check if an object is lit or unlit.

This would require a CPU-GPU readback, which is slow and complex to implement for such a simple use case. A CPU-based raycast is actually much faster in this case, especially when you don't need to query thousands of objects every frame – you can spread the load across frames.

And I disagree with the argumentation of 2D lights being unsuitable for simple effects, obviously they are unsuitable in the way they exist now but the whole point of a proposal is to show possible improvements to the engine.

2D lighting is much more expensive than a sprite-based approach, even if the sprite has to use a custom shader.

bgie commented 9 months ago

@LordBrkica small question: #7026 proposes MIN and MAX and I think MAX would be better to archieve the warcraft-like fog-of-war effect. What is specific about OR that you want to use?

OR works bitwise, so a darker light could have a bit set that is not set in a brighter light. If you OR them, the result would be brighter than both, similar to ADD, but more unpredictable when not considering the binary representation of the color values.

example with 4 bits for simplicity: 0100 = dark color 1000 = bright color 1100 = OR combination which is brighter than the bright color, same as ADD (in this case) 1000 = MAX = equal to the brightest color 1100 = ADD = brighter than both, and coincidently the same as OR

A different set of colors, where bits happen to overlap: 0010 = dark color 0110 = bright color 0110 = OR combination which is identical to the brightest color, same as MAX 1000 = ADD = brighter than both 0110 = MAX = the brightest color

I could be totally ignorant about a use case for a binary OR - so that's why I'm asking, as I'm working on a PR for the MIN/MAX