CopyToImage is a heavy operation and should, if possible, not be called every frame iteration.
Such lighting effect is very well possible with a RenderTexture. You can find a very small example on my GitHub page (https://github.com/eXpl0it3r/Examples/blob/master/SFML/Flashlight.cpp), you of course have to make it fit your wanted effect. ;)
Tried to emulate your example in C# didn't work out as planned, the rect draws properly, the circles are created properly for the flashlight, but the blendmode isn't working as intended for the render texture. Below's just sloppy code, but I don't think I missed anything.
class Program
{ public static float mousex
= 0f
; public static float mousey
= 0f
; public static RenderStates state
; static void Main
(string[] args
) { state
.BlendMode = BlendMode
.Add; RenderWindow window
= new RenderWindow
(new VideoMode
(300,
300),
"Flashlight?"); window
.SetFramerateLimit(60); window
.SetMouseCursorVisible(false); //close window window
.Closed += (s, e
) => { RenderWindow win
= (RenderWindow
) s
; win
.Close(); }; window
.MouseMoved += (s, e
) => { mousex
= e
.X; mousey
= e
.Y; }; RenderTexture layer
= new RenderTexture
(300,
300); RenderTexture flashlightTexture
= new RenderTexture
(60,
60); flashlightTexture
.Clear(); for(uint i
= 0; i
< 6; ++i
) { CircleShape temp
= new CircleShape
(30f
-(i
*2f
)); temp
.Origin = new Vector2f
(30f
-(i
* 2f
), 30f
-(i
* 2f
)); temp
.FillColor = new Color
(255,
255,
255,
(byte) (61 - (i
* 10))); temp
.Position = new Vector2f
(30f, 30f
); flashlightTexture
.Draw(temp, state
); } flashlightTexture
.Display(); Sprite flashlight
= new Sprite
(flashlightTexture
.Texture); flashlight
.Position = new Vector2f
(150
.0f, 150
.0f
); flashlight
.Origin = new Vector2f
(30f, 30f
); RectangleShape rect
= new RectangleShape
(new Vector2f
(100f, 100f
)); rect
.Position = new Vector2f
(150f, 150f
); rect
.FillColor = new Color
(Color
.Red); Sprite msprite
= new Sprite
(); msprite
.Texture = layer
.Texture; while(window
.IsOpen()) { window
.DispatchEvents(); flashlight
.Position = new Vector2f
(mousex, mousey
); layer
.Clear(); layer
.Draw(flashlight, state
); layer
.Display(); window
.Clear(Color
.Blue); window
.Draw(rect
); window
.Draw(msprite
); window
.Display(); Console
.WriteLine("x: {0}, y: {1}", mousex, mousey
); } } }
Right! :) But also state.BlendMode = BlendMode.Add; ist not working!
use
state
= new RenderStates
( BlendMode
.None); If you use
state
= new RenderStates
( );state
.BlendMode = BlendMode
.None; it also doen't work. This seems to be a bug in CSFML....
This is not a bug in CSFML or even C#. This is the way structs are handled in the CLR. When you use the default empty constructor on structs everything in the struct will be assigned 0/null depending on the member type. Also there is no way to overload the empty constructor in structs so you must call an overloaded constructor with SFML.
sf.RenderStates hehe = new sf.RenderStates(sf.RenderStates.Default);
Actually the way to do this in C# would be
RenderStates states = RenderStates.Default;
This is not a bug in CSFML or even C#. This is the way structs are handled in the CLR. When you use the default empty constructor on structs everything in the struct will be assigned 0/null depending on the member type. Also there is no way to overload the empty constructor in structs so you must call an overloaded constructor with SFML.
Maybe you misunderstand me. You can call an overloaded constructor, but if it's possible to access a property/var from outside and assign a value to it (because it is declared as public), the value should be stored, right? :-)
so if I can write this code:
state
= new RenderStates
( );state
.BlendMode = BlendMode
.None;
BlendMode should have the value 'None' and not undefined/default....
maybe it would be better to use a property without a setter.
public BlendMode BlendMode
{
get
{
return _Value;
}
}
so now, you can not set BlendMode without using the constructor. ;)
Maybe you misunderstand me. You can call an overloaded constructor, but if it's possible to access a property/var from outside and assign a value to it (because it is declared as public), the value should be stored, right? :-)
so if I can write this code:
state
= new RenderStates
( );state
.BlendMode = BlendMode
.None;
BlendMode should have the value 'None' and not undefined/default....
This doesn't work because SFML.NET is a binding on top of unmanaged memory (accessed through CSFML API). When you create RenderStates with an overloaded constructor SFML.NET internally creates an unmanaged object and then assigns an IntPtr to the handle of this unmanaged object.
The problem is that you can not overload the default empty constructor nor can you disable the default constructor with structs. And with the default empty constructor there is no way to force creation of the unmanaged object so the handle(IntPtr) is initialized to zero.
maybe it would be better to use a property without a setter.
public BlendMode BlendMode
{
get
{
return _Value;
}
}
so now, you can not set BlendMode without using the constructor. ;)
Adding properties to structs in C# doesn't work too well and still doesn't solve the above problem.