SFML community forums

Help => Graphics => Topic started by: grimmreefer on September 20, 2012, 08:06:49 pm

Title: is it possible to subtract a texture from an other
Post by: grimmreefer on September 20, 2012, 08:06:49 pm
First of all, sorry for my worst english,

i hope you understand me anyway.

(http://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Alpha_compositing.svg/500px-Alpha_compositing.svg.png)

i want do get the effect of the third picture of the first row.

is it possible?
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 20, 2012, 10:07:24 pm
I don't know of any SFML function that could do this, so I guess it's not possible. If yxou really need it you might be able to do such a thing with OpenGL, but I'm not an expert on OpenGL... ;)
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 20, 2012, 10:14:51 pm
thanks for the fast answering, i hope you are wrong, i doesn't know much about OpenGl.

In an German Forum some guy said that i have to use Render Textures,  but he can't explain i have to do this.
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 20, 2012, 10:22:06 pm
Do you want this effect to be applied in real time? Or can it be done once at init?
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 20, 2012, 10:45:17 pm
it should "Simulate" a point light in real time
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 20, 2012, 11:58:47 pm
Hum... how does subtracting two textures simulate a point light?
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 21, 2012, 09:38:53 am
I make the whole screen black and on the place i want i cut a circle out. So i have a simple point light
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 21, 2012, 09:43:55 am
Ok, so in fact you want to create a mask.

This is possible, you can do it this way:

- create a RenderTexture which covers your screen
- clear it with opaque black
- draw your spot light to it, with blend mode = sf::BlendNone (so that its alpha is copied rather than interpreted)
- draw your RenderTexture to your window with a sprite
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 21, 2012, 02:15:00 pm
Sounds good, but can you write a short sample, i don't really get it.
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 21, 2012, 02:24:36 pm
I think something like this (untested):

sf::CircleShape point(10);
point.setColor(255, 255, 255, 1);

sf::RenderTexture rtex;
rtex.create(windowWidth, windowHeight);
rtex.clear();
rtex.draw(point, sf::BlendNone);
rtex.display();

sf::Sprite sprite;
sprite.setTexture(rtex.getTexture());

// ...

window.draw(sprite);

Interesting enough the alpha channel of the circle/punch hole, can't be fully transparent, otherwise it will just be ignored.
@Laurent is this the intended behavior?

Anyways since I found the question interesting and somehow on another board has asked about the same questions here goes a complete example: ;D
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(300, 300), "Hello World!");
    window.setFramerateLimit(30);
    window.setMouseCursorVisible(false);

    sf::RectangleShape rect(sf::Vector2f(100.f, 100.f));
    rect.setFillColor(sf::Color::Red);
    rect.setPosition(10, 10);

    sf::CircleShape circle(20);
    circle.setRadius(20);
    circle.setPosition(110, 110);
    circle.setFillColor(sf::Color(255, 255, 255, 1));

    sf::RenderTexture rtex;
    rtex.create(300, 300);

    sf::Sprite sprite;
    sprite.setTexture(rtex.getTexture(), true);
    sprite.setPosition(0, 0);

    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                window.close();
        }

        circle.setPosition(static_cast<sf::Vector2f>(sf::Mouse::getPosition(window)));

        rtex.clear();
        rtex.draw(circle, sf::BlendNone);
        rtex.display();

        sprite.setTexture(rtex.getTexture(), true);

        window.clear(sf::Color::Blue);

        window.draw(rect);
        window.draw(sprite);

        window.display();
    }
}
 
But keep in mind drawing to the render texture every frame is quite a heavy task, it's like drawing two frames at once, so if it's not really needed don't do this every frame iteration. ;)
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 21, 2012, 03:07:05 pm
You all are awesome, i'll test it and post the result.

Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 21, 2012, 03:24:07 pm
Quote
@Laurent is this the intended behavior?
Did you use the RC? I thought I already fixed it.
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 21, 2012, 03:28:26 pm
Quote
@Laurent is this the intended behavior?
Did you use the RC? I thought I already fixed it.
Nope, a one or two week old SFML release...

Edit: Just updated SFML to the latest commit and transparency with alpha channel = 0 and BlendNone still just doesn't draw anything...
(Windows, MinGW 4.7.0, static, debug)
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 21, 2012, 04:07:54 pm
Hmm... it was fixed the 15th of march:
http://en.sfml-dev.org/forums/index.php?topic=7294.msg48230#msg48230
https://github.com/SFML/SFML/commit/78e7dcea38b33bdee29105d39e30814a260fe47d
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 21, 2012, 04:12:11 pm
Ok, wait, there's another bug (was supposed to be a feature ;D), specific to shapes.

I'll see what I can do.
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 21, 2012, 04:27:11 pm
Does it mean i wont work?
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 21, 2012, 04:32:38 pm
Does it mean i wont work?
It works as long as you use an alpha channel greater than 0. ;)
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 21, 2012, 10:03:47 pm
It's fixed, you can now use completely transparent shapes.
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 09:34:29 am
   8) it work fine.

but it doesn't work if i use more than one "Light"
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 22, 2012, 10:13:31 am
Quote
but it doesn't work if i use more than one "Light"
What happens? Can you show the code?
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 10:23:11 am
i make a class for the light, if i add an other light the visible range is at the overlab, omg my english is so bad ^^



#ifndef CLIGHTS_HPP
#define CLIGHTS_HPP

#include <iostream>
#include <SFML\Graphics.hpp>


#include <vector>
#include <string>
#include <sstream>

using namespace std;

class CLights
{
    public:

            CLights(int SizeX, int SizeY);


            void SetPosition(int PosX, int PosY);
            void SetLightSize(float Radius);
            void SetLightColor(sf::Color LightColor);
            void SetLightPosition(int PosX, int PosY);
            void BackgroundColor(sf::Color Color);

            void Draw(sf::RenderWindow &window);



    private:

            float m_Radius;

            sf::Color m_LigthColor;

            int m_PosX;
            int m_PosY;

            int m_LightPosX;
            int m_LightPosY;

            sf::CircleShape m_CircleLight;
            sf::RenderTexture m_RTex;
            sf::Sprite m_ShapeBackground;
};



#endif







#include <iostream>
#include <SFML\Graphics.hpp>
#include <SFML\Audio.hpp>

#include "Lights.hpp"

#include <string>
#include <vector>
#include <sstream>

using namespace std;

CLights::CLights(int SizeX, int SizeY)
{
    m_RTex.create(640,480);
    m_CircleLight.setRadius(0);
    m_CircleLight.setPosition(0,0);
    m_CircleLight.setFillColor(sf::Color(255,255,255,1));

    m_ShapeBackground.setTexture(m_RTex.getTexture(), true);
    m_ShapeBackground.setPosition(0,0);



}



void CLights::SetLightColor(sf::Color LightColor)
{
    m_CircleLight.setFillColor(LightColor);
}



void CLights::SetLightSize(float Radius)
{
    m_Radius = Radius;

    m_CircleLight.setRadius(m_Radius);
}



void CLights::SetLightPosition(int PosX, int PosY)
{
    m_LightPosX = PosX;
    m_LightPosY = PosY;


    m_CircleLight.setPosition(sf::Vector2f(m_LightPosX, m_LightPosY));
}

void CLights::SetPosition(int PosX, int PosY)
{
    m_PosX = PosX;
    m_PosY = PosY;

    m_CircleLight.setPosition(sf::Vector2f(m_PosX, m_PosY));
}



void CLights::BackgroundColor(sf::Color Color)
{
        m_ShapeBackground.setColor(Color);

}



void CLights::Draw(sf::RenderWindow &window)
{
    m_RTex.clear();
    m_RTex.draw(m_CircleLight, sf::BlendNone);
    m_RTex.display();

    m_ShapeBackground.setTexture(m_RTex.getTexture(), true);




    window.draw(m_ShapeBackground);
}

 
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 22, 2012, 11:15:23 am
You must draw all your lights to the same render texture. You should take some time to figure out how this code works, it seems that you have no idea what it does ;)

m_RTex.clear(sf::Color::Black); // to make it more obvious
m_RTex.draw(light1, sf::BlendNone);
m_RTex.draw(light2, sf::BlendNone);
m_RTex.draw(light3, sf::BlendNone);
...
m_RTex.display();

// no need to call it everytime
// m_ShapeBackground.setTexture(m_RTex.getTexture(), true);

window.draw(m_ShapeBackground);

So of course you need to redesign your class a little bit.

Quote
the visible range is at the overlab, omg my english is so bad
I have no idea what "overlab" means, and my dictionnary couldn't help ;D
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 22, 2012, 11:27:54 am
He just meant that only the last light will should up.
Also keep in mind that if lights do overlap you'll have to draw them in the right order to the rendertexture, although it will still lead to some unwanted effects...
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 12:14:21 pm
I give google translate a try

but yet, I figure it already slow. this is definitely a huge help.
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 05:35:53 pm
i tried wiht a vector but it doesn't work, one light is nice.  but with a RenderTexture there is no way to add lights if the "Game" is running.




CLights::CLights(int SizeX, int SizeY)
{
    m_SizeX = SizeX;
    m_SizeY = SizeY;

    m_RTex.create(m_SizeX, m_SizeY);




}

void CLights::AddLigth(int PosX, int PosY, int Radius, sf::Color TempColor, sf::RenderWindow &window)
{
    m_SpriteBackground.setTexture(m_RTex.getTexture(), true);
    m_SpriteBackground.setPosition(0, 0);
    m_SpriteBackground.setColor(sf::Color(0,0,0,255));

    m_CircleLight.setPosition(sf::Vector2f(Mouse.getPosition(window).x, Mouse.getPosition(window).y));
    m_CircleLight.setRadius(Radius);
    m_CircleLight.setFillColor(sf::Color(255,255,255,1));

    m_VectorShape.push_back(m_CircleLight);


}


void CLights::Draw(sf::RenderWindow &window)
{
    for(int i = 0; i < m_VectorShape.size(); i++)
    {
        m_SpriteBackground.setColor(sf::Color(0,0,0,240));
        m_RTex.clear();
        m_RTex.draw(m_VectorShape[i], sf::BlendNone);
        m_RTex.display();

        m_SpriteBackground.setTexture(m_RTex.getTexture(), true);

        window.draw(m_SpriteBackground);

    }



}
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 22, 2012, 05:58:40 pm
Please make use of the code=cpp tag!! :)

You still don't understand how it works, don't you? Please at least try to understand it! ;)
You only have to clear and display the render texture once and not with every single light...
Title: Re: is it possible to subtract a texture from an other
Post by: Laurent on September 22, 2012, 05:59:52 pm
Or just look at the code I posted above.
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 06:27:58 pm
@Laurent

in your code i have to write every single light in my class, i cant add lights while the program is running

@eXpl0it3r

please believe me, i try to understand  ;D
Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 22, 2012, 06:37:16 pm
He meant that you don't call clear() and display() in ever iteration.

Lets take an easy analogy:
The window is a piece of paper with a drawing on it. The render texture is another piece of paper on top of the other one and it is just black.
Now to see what's underneath you go and cut out some parts of the black paper. After that you can look through that cutout part onto your window.

What you did in the code with the vector is. Everytime you've cut out a square, you threw away the black paper with the hole and took a new black paper and cut out the next hole. Obviously you'll always just see one hole (since you've thrown the other holes away).

What you actually want is to take the black paper, punch as many holes as you want into it and the overlay it  with the drawing paper.

Got it? ;)
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 07:28:26 pm
 :( i give up, now i can place many lights bur can move the one of the playercharakter
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 22, 2012, 10:40:25 pm
 YES YES YES, i made it YES YES YES 8)


Edit:

it still works, but at 5 lights the performance is terrible
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 24, 2012, 12:54:39 pm
Here is the result

http://www55.zippyshare.com/v/54013397/file.html

Title: Re: is it possible to subtract a texture from an other
Post by: eXpl0it3r on September 24, 2012, 12:59:48 pm
I don't see where there are multiple 'lights' but congrats! ;)
Btw it crashes at exit on my PC.
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 24, 2012, 01:09:28 pm
Sorry, with T you can add a torchlight.


EDIT:

This funktion is the problem, maybe someone have a idea how i can fix this.


Code: [Select]
void CLights::SyncLightPosition(int PosX, int PosY)
{
    for(int i = 0; i < m_VectorShape.size(); i++)
    {
        m_RTex.clear();
        m_VectorShape[0].setPosition(PosX, PosY);
            for(int i = 0; i < m_VectorShape.size(); i++)
            {
                m_RTex.draw(m_VectorShape[i], sf::BlendNone);
            }

    }
}

Title: Re: is it possible to subtract a texture from an other
Post by: FRex on September 24, 2012, 05:30:40 pm
void CLights::SyncLightPosition(int PosX, int PosY)
{
        m_RTex.clear();
        m_VectorShape[0].setPosition(PosX, PosY);
            for(int i = 0; i < m_VectorShape.size(); i++)
            {
                m_RTex.draw(m_VectorShape[i], sf::BlendNone);
            }
m_RTex.display();
}
 
Title: Re: is it possible to subtract a texture from an other
Post by: grimmreefer on September 24, 2012, 05:39:15 pm
as i used one for loop it doesn't work, but now is works fine, 40 lights and still playable.


thank you guys!