Inconsistent Output with PointLight2D when Sprite2D has a texture with normal map and blend mode Is not 'Add'
Tested versions
Reproducible in 4.3.dev, 4.2.stable
System information
Windows 10 - Godot 4.2.stable - Forward+
Issue description
I am doing a 2D platformer game where I have a dark room only illuminated by torches. I do use a PointLigt2D with subtract option to make it dark and the other lights illuminate nicely the rest with option 'add'. All fine until I added normal maps to the bricks.
Here is an example. Sprite on the left has normal map, on the right doesn't.
I would spec both to get darker as the sprite on the right (without the normal map). If this is intended to be the correct behavior, then there should be a way to darken the scene.
Steps to reproduce
- Create 2 Sprite2D
- Assign the same texture to both of them
- Assign a normal map texture to one of them
- Create a PointLigth2D and set the blend mode to subtract. Just can use any texture you feel like.
Minimal reproduction project (MRP)
Couldn't get an answer from the rendering team but I see this in the documentation
https://docs.godotengine.org/en/stable/tutorials/2d/2d_lights_and_shadows.html
CanvasModulate is used to darken the scene by specifying a color that will act as the base "ambient" color. This is the final lighting color in areas that are not reached by any 2D light. Without a CanvasModulate node, the final scene would look too bright as 2D lights would only brighten the existing unshaded appearance (which appears fully lit).
Hey @huwpascoe, thank a lot for catching that. It is not in the CanvasModulate documentation (it should be added), so I used that node only for fade-in and fade-out the whole screen.
But I think you have found a design problem. I am gonna make a proposal to see if it makes sense.
Here we go:
https://github.com/godotengine/godot-proposals/discussions/10307
I took a look at the MRP locally and I can confirm that this is the expected behaviour. The "subtract" blend mode tells the light that instead of adding its impact to the scene, it should subtract it.
So basically think of it as calculating how much light a pixel should receive, then subtracting that amount instead.
Here is what the scene looks like with the "add" blend mode. You can see the bright spots on the left correspond to the dark spots in your screenshot.
It sounds like you want to mix physically-based lighting (with a normal map) with a light that doesn't behave as a light and instead just acts to darken a portion of the scene.
I can think of three ways to achieve that that look slightly different.
One is to increase the height of the light, so it hits the surface more directly. This will result in more darkening, but it will still maintain some of the shape from the normal map:
The second is to use the same texture as your light in a Sprite2D that uses the subtract blend mode:
Finally, you can write a custom light shader
Thanks @clayjohn a lot.
The shader plus some other tricks made it possible. But it is nothing intuitive, specially in the shader where all they layer information from the lights is gone. I don't know which lights I am "receiving." -I was expecting to get only the lights from the Sprite2D light-layers that contained the shader.-