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

Author Topic: [SOLVED]Combine 2 sprites into a single one?  (Read 4412 times)

0 Members and 1 Guest are viewing this topic.

Nero

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
[SOLVED]Combine 2 sprites into a single one?
« on: July 23, 2018, 08:52:42 am »
So, I am facing this problem:


Basically, I have 2 rectangles ( body shadow and gun shadow ), each one having a black texture with 40% opacity that goes up to 80% in the place where they intersect. Is there a way to make the shadows appear as a single shape?

Thanks in advance !
« Last Edit: July 23, 2018, 07:32:20 pm by Nero »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Combine 2 sprites into a single one?
« Reply #1 on: July 23, 2018, 09:36:52 am »
This is probably not the only option, but you can draw all the shadows to a sf::RenderTexture without applying alpha blending ("None" blend mode), and then draw your render-texture with alpha blending enabled.
Laurent Gomila - SFML developer

Nero

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Combine 2 sprites into a single one?
« Reply #2 on: July 23, 2018, 10:06:53 am »
This is probably not the only option, but you can draw all the shadows to an sf::RenderTexture without applying alpha blending ("None" blend mode), and then draw your render-texture with alpha blending enabled.

I've looked at the sf::RenderTexture and sf::BlendMode documentation but I couldn't understand how to do it. I've tried something but I've created a buggy and laggy texture.

Could you help me with the code? Both bodyShadow and gunShadow are rectangles directly drawn on the window.

PS: I didn't set shadows transparency using setFillColor function, but using photoshop to add transparency to the texture (if this matters).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Combine 2 sprites into a single one?
« Reply #3 on: July 23, 2018, 10:20:56 am »
Quote
I've looked at the sf::RenderTexture and sf::BlendMode documentation but I couldn't understand how to do it. I've tried something but I've created a buggy and laggy texture.
Can you show what you've tried? We prefer to help people understand and fix their code, rather than giving code to copy and paste ;)
Laurent Gomila - SFML developer

Nero

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Combine 2 sprites into a single one?
« Reply #4 on: July 23, 2018, 11:04:43 am »
I deleted what I've done after I saw it doesn't work. I recreated it and I think it's a bit better than before.
So, I have a class called Player. I initialized the texture in Player constructor :
if (!texture.create(100, 100))
        std::cout << "error" << std::endl;

And then here is Player draw function :
void Player::draw()
{

        texture.clear(sf::Color::White);

        //Application::getInstance()->window.draw(shadow); <---- that's the draw call I've been using before
        texture.draw(shadow);
        Application::getInstance()->window.draw(body); // draw of the body (not the shadow)
        //Application::getInstance()->window.draw(gunShadow); <--  draw call used before
        texture.draw(gunShadow);
        Application::getInstance()->window.draw(gun);

// Some bullets draw thing, not important
        for (size_t i = 0; i < bullets.size(); i++)    
        {
                        Application::getInstance()->window.draw(bullets.at(i).getBody());
        }

        texture.display();

        sf::Sprite sprite(texture.getTexture());
        Application::getInstance()->window.draw(sprite);
}
 

Right now, it kinda looks like a mask or something, but the problem is obviously still there because I haven't used sf::BlendMode.
That's how it looks :

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Combine 2 sprites into a single one?
« Reply #5 on: July 23, 2018, 11:18:33 am »
Note that shadow and gunShadow should be drawn to the render texture without any transparency. The transparency is added onto the texture when drawn.
On that texture, should be a fully opaque, probably solid colour, mask-type image. However, it's probably better if the render texture is cleared with sf::Transparent.

You can then just use a slightly transparent white colour (white with a non-full alpha channel) for the render sprite to draw it.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Combine 2 sprites into a single one?
« Reply #6 on: July 23, 2018, 11:23:13 am »
I see 3 mistakes in your code:

1. The render-texture should be cleared with transparent color, so you don't get that white background in addition to your shadows

2. As I said, the shadows should be drawn to the render-texture without alpha-blending (sf::BlendNone)

3. There should also be some position adjustements, obviously

To avoid having to adjust positions when drawing to the render-texture, you could just have it the same size as the window. This would also allow you to handle shadows of the whole scene, in case there are others to draw.
Laurent Gomila - SFML developer

Nero

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Combine 2 sprites into a single one?
« Reply #7 on: July 23, 2018, 11:41:36 am »
I was aware of the white clear color and later I realized that I should change the size too. I've also changed the textures so they are fully opaque. This is what I have right now:
void Player::draw()
{

        texture.clear(sf::Color::Transparent);

        texture.draw(shadow, sf::BlendNone);
        Application::getInstance()->window.draw(body);
        texture.draw(gunShadow, sf::BlendNone);
        Application::getInstance()->window.draw(gun);

        for (size_t i = 0; i < bullets.size(); i++)    
        {
                        Application::getInstance()->window.draw(bullets.at(i).getBody());
        }

        texture.display();

        sf::Sprite sprite(texture.getTexture());
        Application::getInstance()->window.draw(sprite);
}

But it still looks weird :


That's how it looks without BlendNone :


I guess it should work if I would apply a color overlay to the whole texture, without using BlendNone on body and gun textures separately... Is this possible? What should I do next?
« Last Edit: July 23, 2018, 02:53:14 pm by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Combine 2 sprites into a single one?
« Reply #8 on: July 23, 2018, 02:55:16 pm »
Ok, then do as Hapax suggested: your shadows should be opaque (you can even use the original textures, with a black color), so you can use regular alpha-blending, and then apply an opacity when you draw your render-texture to the window.

void Player::draw()
{
        texture.clear(sf::Color::Transparent);

        texture.draw(shadow); // shadow image is opaque black on transparent background
        Application::getInstance()->window.draw(body);
        texture.draw(gunShadow); // same here
        Application::getInstance()->window.draw(gun);

        for (size_t i = 0; i < bullets.size(); i++)    
        {
                        Application::getInstance()->window.draw(bullets.at(i).getBody());
        }

        texture.display();

        sf::Sprite sprite(texture.getTexture());
        sprite.setColor(sf::Color(255, 255, 255, 128)); // make the shadow overlay semi-transparent
        Application::getInstance()->window.draw(sprite);
}
« Last Edit: July 23, 2018, 02:58:44 pm by Laurent »
Laurent Gomila - SFML developer

Nero

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Combine 2 sprites into a single one?
« Reply #9 on: July 23, 2018, 07:31:39 pm »
Damn, I was looking like an idiot for a SetFillColor function lol.
Thanks very much!