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
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)(https://i.imgur.com/O5z7Kmn.png)
Setting the position to (200, 200) results in it moving up and to the right:
(https://i.imgur.com/a2WeKhz.png)
I tried using MapPixelToCoords in order to set it relative to the window rather than the map, but it seems to have no effect.
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
; } (https://i.imgur.com/7uDtuE2.png)
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.