Godot's Light2D seems to have a 16-light limit, but I don't understand what that means.
If an object (a tree/a cat/etc) is lit by more than 16 lights, the lighting won't work as expected, right?
This doesn't mean you can't have more than 16 lights in a scene, right?

  • xyz replied to this.
  • CrayonApe Here you go:

    Scene structure:

    Light sprite shader:

    shader_type canvas_item;
    render_mode blend_add;
    
    uniform sampler2D mask: source_color;
    uniform sampler2D map_lit: source_color;
    
    void fragment() {
    	COLOR.rgb = texture(map_lit, SCREEN_UV).rgb * COLOR.rgb;
    	COLOR.a = texture(mask, UV).r;
    }

    CrayonApe You can have as many lights as you wish, but only 16 can be rendered at a time (i.e. be visible inside the viewport). Meaning if you have a scene/level that's larger than the viewport and you distribute your light areas so that 16 or less are visible is any scrolled position - everything will look as you expect.

      xyz Thanks for the explanation, currently I need to create many lights in very dark scenes. Due to the 16 limit I can't create many light2d nodes in the viewport, I also tried the additive blending mode of sprite2d but they don't behave as expected in very dark environments. Any ideas on this problem, I really don't know how to solve it.

      • xyz replied to this.

        CrayonApe Those are really your only 2 options. Additively blended sprites should be sufficient for emulating 2D lights without shadows or normalmaps. What do you mean by not behaving as expected?

          xyz When the environment is very dark, Sprite2d using ADD BLEND MODE is almost invisible. This is mentioned in the documentation:
          The blending formula is inaccurate compared to "actual" 2D lighting. This is usually not a problem in sufficiently lit areas, but this prevents additive sprites from correctly lighting up areas that are fully dark.

          Even when the environment is not completely dark, the lighting effects are not good.

          • xyz replied to this.

            CrayonApe What exactly you need all those lights for, what's the exact use case?

              xyz I want the town to be hard to see at night, so the player has to complete the task of making a flashlight. But there should still be a lot of lights in areas where people are very active. Knowing the 16 limit, my current idea is to merge some small lights into one big one. So the town part might not be a big problem.
              But in the future I will make a very dangerous cave, and it might be very dark. Some monsters are glowing, and the player can shoot fireballs. None of these nodes are static, so if I set them all to "Light2D", the 16 limit will obviously occur, and Sprite2Ds in dark caves won't look good.
              So should I try not to make the environment too dark?

              • xyz replied to this.

                CrayonApe You can render the fully lit environment into a separate viewport and use that as a texture for light sprites. That way you can have any number of good looking sprite lights.

                  xyz I never knew the viewport could be used as a texture, I'll give it a try. Thanks!

                  • xyz replied to this.

                    CrayonApe I never knew the viewport could be used as a texture

                    That's actually one of its main purposes.

                      xyz Can you give me some tutorials? I'm a beginner and have only read the official documentation. I think some good tutorials would really help.

                      • xyz replied to this.

                        CrayonApe I don't deal with tutorials. Search the web, I'm sure you'll be able to find something that shows the basic viewport usage.

                          xyz Hi, I tried the viewport but I probably used something wrong so the final effect is not what I wanted.
                          According to my search results, the viewport can be thought of as a "screen" that displays the contents inside, a bit like a movie screen. It can be used to make some special effects, such as 2D in 3D and vice versa.

                          I added a SubViewport node to the player node and added a light sprite to it. Then I used it as the viewport texture of the Light node.
                          But when the player enters the game scene, the light is still affected by the environment.

                          Did I misunderstand what you mean or did I do something wrong? Logically, a subviewport in a dark environment would not have an effect.

                          • xyz replied to this.

                            CrayonApe Render the fully lit map into a viewport that's exactly the size of the screen. Assign viewport's texture to a sprite and use modulate to darken it. This is now your unlit scene. Add a light sprite. Setup a shader on it that takes in viewport's texture and light mask texture. In the shader, use screen uv to read the viewport texture, and sprite uv to read the mask. Set sprite's rgb to viewport texture and its alpha to mask texture. That should be it. Add as many light sprites as you need. Oh, and you can use light sprite's modulate to tint or over-expose the light.

                            CrayonApe Here you go:

                            Scene structure:

                            Light sprite shader:

                            shader_type canvas_item;
                            render_mode blend_add;
                            
                            uniform sampler2D mask: source_color;
                            uniform sampler2D map_lit: source_color;
                            
                            void fragment() {
                            	COLOR.rgb = texture(map_lit, SCREEN_UV).rgb * COLOR.rgb;
                            	COLOR.a = texture(mask, UV).r;
                            }

                              xyz Thanks for the comprehensive explanation, but I'm still a newbie and it still confuses me how to apply it to my deeply nested scene. Currently I use the canvasmodulate node to make the day/night cycle because it's ready-made and newbie-friendly. I'm still unfamiliar with shader, maybe one day when I know more about game development I can do better. Anyway, your suggestions gave me a new way to think about this problem, thank you very much!

                              • xyz replied to this.

                                CrayonApe Your whole game scene should be parented under the viewport. This is represented by the map node in my example. On the other hand map_dark should actually be just a sprite that has this viewport's texture assigned to it so it will display everything that's rendered into the viewport, i.e. the whole map. This sprite can then be darkened in any way you see fit. So in the essence you end up with two versions of the whole scene; one is fully lit the other is fully dark. The dark one is then displayed as a background sprite covering the full screen while the lit version is drawn over it only in the areas that are masked-in with sprite masks.