SFML community forums

Bindings - other languages => DotNet => Topic started by: Lamonte on September 21, 2013, 05:23:16 am

Title: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Lamonte on September 21, 2013, 05:23:16 am
1. Want to emulate this effect http://www.youtube.com/watch?v=J1xr9kbQXKI
2. By creating a render window, filling it with black.  Drawing to it and then setting the transparency of the color I drew on the render window (will be updated based sprite position, not really important atm)
3. Display the render window to the screen after everything else is loaded to create said effect.

Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: zsbzsb on September 21, 2013, 05:33:04 am
https://github.com/SFML/SFML/issues/1 (https://github.com/SFML/SFML/issues/1)

Since SFML does not have rendermasks there is no way to correctly simulate that effect. However there is a dirty workaround that partially simulates that effect that is described in this thread (http://en.sfml-dev.org/forums/index.php?topic=7427.0).
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Lamonte on September 21, 2013, 05:37:50 am
That was actually going to be my 4th question if there was a way to create an image from a render texture, this work around seems doable.
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Lamonte on September 21, 2013, 06:40:32 am
Seems like the CopyToImage() function in C# has a memory leak on windows 7?

http://pastie.org/private/muwqimwmbgxodg30oyr0xq

hmm... just realized in thiat example he's not doing it every frame, trying to figure out a proper way to do this w/out killing stuff.  Because right now this runs every frame which is copying thousands of images a second lol
Title: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: eXpl0it3r on September 21, 2013, 10:11:12 am
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. ;)
Title: Re: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Lamonte on September 22, 2013, 06:20:46 am
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);
            }

        }
    }
Title: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: eXpl0it3r on September 22, 2013, 08:04:25 am
Why are you using sf::BlendAdd. everywhere when I was using sf::BlendNone?
BlendNone will apply the content directly, thus making the rendertexture transparent at specific points. ;)
Title: Re: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Mad on September 22, 2013, 01:20:02 pm
Why are you using sf::BlendAdd. everywhere when I was using sf::BlendNone?
BlendNone will apply the content directly, thus making the rendertexture transparent at specific points. ;)

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....
 
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: FRex on September 22, 2013, 01:23:13 pm
I may be wrong but I think it's caused by default C# struct ctors doing memset 0 on entire thing really so you have to set every field to sane default yourself. (I think Laurent said that..)

So if you want a
sf::RenderStates hehe;
from c++ you must do:
sf.RenderStates hehe = new sf.RenderStates(sf.RenderStates.Default);
Title: Re: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: zsbzsb on September 22, 2013, 01:36:53 pm
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;
Title: Re: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Mad on September 22, 2013, 04:09:19 pm
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.  ;)


Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: zsbzsb on September 22, 2013, 04:51:29 pm
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.


Quote
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.
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: FRex on September 22, 2013, 05:13:26 pm
Quote
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.
It doesn't. Texture and Shader are IntPtr and always set to null in overloaded constructors(unless it's copy or you passed either, then it's set to that passed one), BlendMode is C# enum and Transform is struct of 9 floats which doesn't hold any unmanaged handle either.

Quote
state = new RenderStates( );
state.BlendMode = BlendMode.None;

BlendMode should have the value 'None' and not undefined/default....
Does that code actually NOT change the value of state.BlendMode? Or do you think that is doesn't? Did you check with Console.WriteLine or debugger?
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Laurent on September 22, 2013, 07:06:12 pm
The default constructor code doesn't work because all members are set to zero. Therefore, only BlendMode is well defined because you explicitly set it after the constructor. The other members must be considered undefined (although Texture and Shader will probably be fine, Transform will be totally messed up).
Title: Re: AW: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Lamonte on September 22, 2013, 07:40:59 pm
Why are you using sf::BlendAdd. everywhere when I was using sf::BlendNone?
BlendNone will apply the content directly, thus making the rendertexture transparent at specific points. ;)

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....

Ah nice this actually worked.  For those asking me why I had to set to "Add", because I was seeing if it worked in general and nothing was working.  So i started changing settings to see if anything would change
Title: Re: Is there a way to make a transparency mask for (rendered) textures or sprites?
Post by: Mad on September 22, 2013, 07:45:27 pm
@Lamonte: Problem solved, good to here.  8)

@zsbzsb: Sure, you are right, I forgot the unmanaged -evil  ;) - part in the background  :)