How to achieve Nuclear Throne style lighting?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By thecultcity

As you can see on those screenshots,

this lighting system has 2 levels of brightness.

When they overlap, the areas with same level should merge instead of getting brighter.

The space outside of the lights should be covered in black.

The important thing is that this lights “reveals” the things underneath it instead of making things brighter.

How do I achieve this lighting in Godot?

I’ve already tried Mask mode in Light2D node.

But the problem is that the spaces outside of the texture gets revealed instead of going black.

I’m currently using WorldEnvironment Glowing effect in my current project.
When I used a plain white circle texture in Light2D node and set it to “Add” mode,
the light causes unintended glowing in it’s radious.

Dumb Idea: Just attach 2 Sprites to Player/Camera, brightness controlled by opacity, and revealing things through Z-Index and Area2D-Signals.
Maybe worth a try…

Captain.Susuwatari | 2020-01-31 13:25

:bust_in_silhouette: Reply From: denxi

You can probably do this easily with a shader. I’ll try to lay out the basic idea.

You need two things, a shader on a different canvas layer that covers the whole viewport in black, and a light manager that’ll tell that shader where the lights are.

Each frame the light manager pulls the position and the inner/outer radii of each light. You can store the radius in a script on the lights themselves. Then it passes that info to the shader. The shader checks if the pixel’s VERTEX is within any light radii. If it isn’t, that pixels alpha value stays at 1.0, so the pixel remains black. If the pixel is within any outer radius, the alpha value changes to a semi transparent number, so something like 0.5, and if its within any inner radius, the alpha value becomes 0.0.

There may be a simpler way that doesn’t involve shaders, but this is the first thing that popped into my head.