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

Author Topic: [SOLVED] sf::BlendAlpha where Alpha is Greater than 0  (Read 1137 times)

0 Members and 1 Guest are viewing this topic.

pierreofthefrench

  • Newbie
  • *
  • Posts: 3
    • View Profile
[SOLVED] sf::BlendAlpha where Alpha is Greater than 0
« on: February 20, 2018, 07:45:21 am »
Hi all, been using SFML for a few months now and have kind of run into a wall trying to achieve a particular behavior.

Basically, I'd like to blend a sprite with sf::BlendNone where the alpha value is not 0, and sf::BlendAlpha elsewhere.

The two images (32x32) on the left are drawn in sequential order, and the last is the result I'm trying to achieve.


I've tried the following to achieve this:
  • Fragment shader (Didn't quite get it working but the performance was already too poor)
  • Custom sf::BlendMode(...) but don't believe this particular behavior is possible
  • Loading the texture via an image w/ createMaskFromColor() which I didn't think would work, and didn't  ;D

If it ends up being too messy, I could just use another texture, as this composite texture is eventually passed into a shader down the road, but was hoping to avoid that for the sake of avoiding having 2 sf::Sprites + 2 sf::RenderTextures for this purpose and the performance impact (albeit probably minor for this method). Any suggestions would be appreciated.
« Last Edit: February 24, 2018, 05:33:44 am by pierreofthefrench »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: sf::BlendAlpha where Alpha is Greater than 0
« Reply #1 on: February 20, 2018, 08:06:22 am »
A fragment shader is definitely the way to go. Don't hesitate to ask if you have troubles with it.
Laurent Gomila - SFML developer

pierreofthefrench

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: sf::BlendAlpha where Alpha is Greater than 0
« Reply #2 on: February 20, 2018, 09:05:53 am »
Appreciate the response! I did get it working, but the performance impact is still pretty brutal. I was getting about 120 fps with the previous technique, and now it's down to about 70fps. I'm basically rendering each sprite twice (one with a normal image, and one with a secondary image) so I'm not sure this will be viable as  I scale up the number of sprites. Since the targetTexture is only input to a shader down the road, it sounds like my best option will be to create a separate texture to pass down into the shader separately, which I was hoping to avoid.

Is this type of performance impact expected when rendering a large number of sprites via shaders? (I'm not experienced enough with shaders / SFML to be sure)

For anyone who does want this logic snippet:
full disclosure this wasn't heavily tested
sprite.setPosition(sf::Vector2f(x, y));
sprite.setRotation(r);
shader->setUniform("background", background->getTexture());
auto rs = sf::RenderStates();
rs.blendMode = sf::BlendNone;
rs.shader = shader;
rs.texture = sprite.getTexture();
targetTexture->draw(sprite, rs);
 
w/
uniform sampler2D texture;
uniform sampler2D background;

void main()
{
        vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
        if (pixel.a != 0) {
                gl_FragColor = pixel;
        } else {
                vec2 background_size  = textureSize2D(background, 0);
                vec2 coords = gl_FragCoord.xy/background_size;
                gl_FragColor = texture2D(background, coords);
        }
}
 
« Last Edit: February 20, 2018, 09:19:30 am by pierreofthefrench »

pierreofthefrench

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: sf::BlendAlpha where Alpha is Greater than 0
« Reply #3 on: February 24, 2018, 05:33:17 am »
I think on the topic of performance, my lack of understanding of SFML is what made me think shaders wouldn't be the ideal approach. Using vertex arrays as opposed to individual sprite calls for all my objects looks like it will be the answer - making any performance implication of the shader itself menial. Thanks again!