Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: New to lighting - Confused about how to handle drawing  (Read 2754 times)

0 Members and 1 Guest are viewing this topic.

That Martin Guy

  • Newbie
  • *
  • Posts: 27
    • View Profile
New to lighting - Confused about how to handle drawing
« on: April 18, 2020, 09:46:22 pm »
In the past I've done lighting in games by simply drawing a black texture on top of everything and then cutting a hole in the sprite where the player is/where the lighting is supposed to originate. However, from what I can find SFML does not offer this option and therefore I wanted to check out a more dynamic solution.

After looking around for a good while I think I understand the general idea of how games do this in general, but I do not understand how to do this in SFML in particular.

From what I understand you do the following:
  • Draw a "dark" overlay, which can range in color and opacity depending on how much you want to see through it.
  • Draw a "lighting" source multiplicatively
  • Draw sprites on top of this

The problem is that I have no clue how to tell the game how to draw something multiplicatively. I also am not sure if this is how you approach the problem.

I am using SFML.net, for the record.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: New to lighting - Confused about how to handle drawing
« Reply #1 on: April 19, 2020, 12:41:59 am »
Hi.

A basic description would be:

create a render texture that matches the window size and fill with black,
draw white (or shades of grey) for where you want lighting (or some lighting - darkening - for grey),
draw everything as normal on the window,
create a 'render sprite' (that is, a sprite to display the render texture),
then draw the render sprite on the window over everything using a blend mode - multiply.

Multiply blend mode means that white parts of the render texture are left alone, black parts are blackened and grey parts are darkened, depending on how dark the grey is.

You should be adding the blend mode to the draw call, similar (because this is C++) to:
window.draw(lightingRenderTexture, blendMode);

The Blend Mode documentation:
https://www.sfml-dev.org/documentation/2.5.1/structsf_1_1BlendMode.php
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

That Martin Guy

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: New to lighting - Confused about how to handle drawing
« Reply #2 on: April 19, 2020, 12:44:19 pm »
I really like that explaination, thank you! The way I did it works very well, with just one issue - the origin position on the render texture seems to be messed up.

The code is currently as follows:
while(window.IsOpen)
{
    //..

    //Not sure if I should remake this texture every game loop or if I just need to instantiate it once before it
    RenderTexture renderTexture = new RenderTexture(1920, 1080);
   
    RectangleShape lightingShape = new RectangleShape(new Vector2f(120, 120))
    {
         //Position should be at (0, 0) by default, but I want to explicitly set it to make sure it's there
         Position = new Vector2f(0, 0)
    };

    renderTexture.Draw(lightingShape);

    //Regular drawing stuff...

    //Not sure if this is the best way to set the blend mode, but I could put it directly in the window Draw call
    RenderStates states = RenderStates.Default;
    states.BlendMode = BlendMode.Multiply;

    window.Draw(renderSprite, states);

    window.Display();
}
 
According to the above code it seems to me the lighting square should be at the top left. However, as you can see from the below picture, it is in the bottom left instead (blending disabled in order to make it clearer)

Setting the position to (200, 200) results in it moving up and to the right:


I tried using MapPixelToCoords in order to set it relative to the window rather than the map, but it seems to have no effect.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: New to lighting - Confused about how to handle drawing
« Reply #3 on: April 19, 2020, 08:14:37 pm »
Not sure if I should remake this texture every game loop or if I just need to instantiate it once before it
It can be created before the loop - like the window - and re-used.

IMPORTANT: remember to clear, draw, and display on the render texture too!
Without that, the previous buffer can be shown and sometimes it's flipped (this isn't necessarily the issue).

Are you using views? The render texture can have the same view as the window to make it more simple.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

That Martin Guy

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: New to lighting - Confused about how to handle drawing
« Reply #4 on: April 19, 2020, 11:10:45 pm »
IMPORTANT: remember to clear, draw, and display on the render texture too!
Without that, the previous buffer can be shown and sometimes it's flipped (this isn't necessarily the issue).

This seems to have been the issue - clearing and displaying fixes it!

Are you using views? The render texture can have the same view as the window to make it more simple.
Doing this breaks the positioning... again. I still think I need to do this, and I'm just not doing it correctly. I'm modifying the view coordinates in order to try and put the player at the center of it. This works for the actual camera, but not for the RenderTexture. This again puts the lighting rectangle at the bottom left of the screen, and neither the black RenderTexture nor the white lighting rectangle seem to move at all. My drawing code together with the camera logic looks like the following:

        public void GameLoop()
        {
            mainView = window.GetView();
            RenderTexture renderTexture = new RenderTexture(1920, 1080);

            while(window.IsOpen)
            {
                    CenterCameraOnUnit(selectedUnit);

                    renderTexture.SetView(mainView);
                    window.SetView(mainView);

                    window.Clear();

                    renderTexture.Clear();

                    RectangleShape shape = new RectangleShape(new Vector2f(120, 120));
                    renderTexture.Draw(shape);

                    //Draw sprites

                    RenderStates states = RenderStates.Default;
                    states.BlendMode = BlendMode.Multiply;

                    renderTexture.Display();

                    Sprite renderSprite = new Sprite(renderTexture.Texture);

                    window.Draw(renderSprite, states);

                    window.Display();
            }
        }

        private void CenterCameraOnUnit(Unit unit)
        {
            Vector2f newViewPos = new Vector2f(unit.position.X + 8, unit.position.Y + 8);
            if(newViewPos.X - mainView.Size.X / 2 < 0)
                newViewPos.X = mainView.Center.X;
            if(newViewPos.Y + mainView.Size.Y / 2 > window.DefaultView.Size.Y)
                newViewPos.Y = mainView.Center.Y;
            mainView.Center = newViewPos;
        }
 

In the image you can see the red character in the middle of the screen "peeking out" of the black RenderTexture. The character's Y-coordinate is negative, and demonstrates that the RenderTexture does not go above origin. The white rectangle in the bottom left is the lighting (blending disabled) and should be positioned at origin, which is slightly to the left of the red character.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: New to lighting - Confused about how to handle drawing
« Reply #5 on: April 20, 2020, 12:10:52 am »
Ah. If you're modifying the view, and using the same modified view for the render texture, you'll need to position it correctly.

e.g.
If the views have their centre at (1000, 0), you would draw onto the render texture as if it was on the window. The render sprite, however, still will be positioned using its top-left corner. So, you can either subtract half of the view size from its position or set its origin to its centre (also half the view size).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

That Martin Guy

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: New to lighting - Confused about how to handle drawing
« Reply #6 on: April 20, 2020, 12:41:30 am »
From what I can tell, everything is working as it should now! Thanks for the help and great explanations!

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: New to lighting - Confused about how to handle drawing
« Reply #7 on: April 20, 2020, 02:14:18 pm »
You're welcome. Glad you got it sorted :)
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*