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

Author Topic: Question about GLSL alpha blending  (Read 6036 times)

0 Members and 1 Guest are viewing this topic.

Evan Bowman

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Question about GLSL alpha blending
« on: February 16, 2016, 02:18:46 am »
For a project I'm working on I'm trying to add simple lighting to a top-down game map, such that projectiles have an underglow that gets projected onto the game map but not in areas of the over world map texture with an alpha channel of 0 (see image). I would do this by drawing the map texture to an empty sf::RenderTexture with blend add, and then drawing glow images with a shader that works sort of like Blend-alpha, but that ignores source pixels where the corresponding destination pixels have a zero alpha channel.

For the shader, it seems like if I only wanted to color pixels with non-zero alpha channels, it would be as simple as doing this:

if (destColor.a > 0)
     destColor = sourceColor * sourceColor.a + destColor * (1 - sourceColor.a)

Having never written any GLSL, I'm not so sure how both the destination and source pixels get passed from SFML to the fragment shader as inputs, and I was wondering if someone who has implemented this sort of thing before could give me some suggestions. When looking at source code for fragment shaders, it looks like the inputs and outputs are declared globally outside a main function with no arguments or return value?

**EDIT: I guess my main issue is this: It appears easy to access values for pixels yet to be drawn, but how do I go about reading values from pixels that SFML has already drawn to the buffer? If doing so is non-trivial, is there a better way to achieve the same effect?

« Last Edit: February 16, 2016, 03:05:31 am by Evan Bowman »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Question about GLSL alpha blending
« Reply #1 on: February 16, 2016, 03:28:17 am »
It appears that shaders are applied before the entire thing is drawn to the target so no, I don't think a shader would have access to target area. (otherwise the shaders would be applied to the entire target too, right?)

I'm not sure of your process here. Are you drawing the objects and then applying the glow on the entire render texture?
Is it possible to just draw to that render texture each object using the shader individually?
If not, and you need to do the entire render texture at once, you may need an intermediary render texture.
I may be missing something obvious though.

Have you attempted this yet? What were the results and how did you go about it?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Evan Bowman

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Re: Question about GLSL alpha blending
« Reply #2 on: February 16, 2016, 03:46:06 am »
It appears that shaders are applied before the entire thing is drawn to the target so no, I don't think a shader would have access to target area. (otherwise the shaders would be applied to the entire target too, right?)

I'm not sure of your process here. Are you drawing the objects and then applying the glow on the entire render texture?
Is it possible to just draw to that render texture each object using the shader individually?
If not, and you need to do the entire render texture at once, you may need an intermediary render texture.
I may be missing something obvious though.

Have you attempted this yet? What were the results and how did you go about it?

I was just attempting to implement this when I ran into the exact problem that you describe, that a shader does not appear to have access to pixels already drawn to the buffer. I had thought to first draw the background texture and then apply the glow over top of it, but I'm running into the problem of how to mask the glow to only show up over parts of the background that are opaque (ie nonzero alpha channel, ie the parts in the picture that aren't black).

I'm reading through the sfml documentation, and I'm having trouble finding any built in features that were meant to do this, but maybe there's some sort of workaround that I'm not thinking of? Am I missing something?

Evan Bowman

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Re: Question about GLSL alpha blending
« Reply #3 on: February 16, 2016, 04:03:23 am »
The only thing I can think of right now is this:

1) Blend-Add the 'tiles' (I say tiles, but it's just one big texture);
2) Alpha blend in the glow, it now goes over the edge, but...
3) Write a shader that takes in the entire generated *texture (Edit: drawable sprite) and completely zeros everything with an alpha value less than 1. I was just hoping there was a better way without having to generate an intermediary texture, because now I need to call the draw function to draw everything to a RenderTexture, and again to draw that result to another RenderTexture, and then again to draw the final texture to the window.

Edit: so maybe something like this:

uniform sampler2D texture;

void main() {
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
    if (pixel.a < 1.0) {
        gl_FragColor = pixel * vec4(1.0, 1.0, 1.0, 0.0);
    }
    else {
        gl_FragColor = pixel * vec4(1.0, 1.0, 1.0, 1.0);
    }
}
« Last Edit: February 16, 2016, 08:20:05 am by Evan Bowman »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Question about GLSL alpha blending
« Reply #4 on: February 16, 2016, 09:26:59 am »
BlendMode(SrcAlpha, One, Add, // whatever equation you want for color...
          DstAlpha, Zero, Add); // src.a * dst.a + dst.a * 0
This blending mode will give you source alpha where destination alpha is 1, and zero (transparent) where destination alpha is 0.
You can do whatever you want for the RGB part, in this example I've put additive blending, which is most likely what you'll need for a glowing sprite :)

No need for a fragment shader.
« Last Edit: February 16, 2016, 09:28:44 am by Laurent »
Laurent Gomila - SFML developer

Evan Bowman

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Re: Question about GLSL alpha blending
« Reply #5 on: February 16, 2016, 10:52:04 am »
BlendMode(SrcAlpha, One, Add, // whatever equation you want for color...
          DstAlpha, Zero, Add); // src.a * dst.a + dst.a * 0
This blending mode will give you source alpha where destination alpha is 1, and zero (transparent) where destination alpha is 0.
You can do whatever you want for the RGB part, in this example I've put additive blending, which is most likely what you'll need for a glowing sprite :)

No need for a fragment shader.

Wow that's a lot easier to implement! I might want to try both additive and alpha blending on the RGB values to see how it looks both ways, what would I use for the RGB parameters? Would it be like this:

BlendMode(SrcAlpha, OneMinusSrcAlpha, Add, DstAlpha, Zero, Add);   // ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Question about GLSL alpha blending
« Reply #6 on: February 16, 2016, 05:20:12 pm »
Don't hesitate to look at how the predefined blending modes are defined in SFML.

https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/BlendMode.cpp#L36-L41
Laurent Gomila - SFML developer

Evan Bowman

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
    • Email
Re: Question about GLSL alpha blending
« Reply #7 on: February 16, 2016, 10:18:53 pm »
Don't hesitate to look at how the predefined blending modes are defined in SFML.

https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/BlendMode.cpp#L36-L41

Thanks for your help! This is working out pretty great for my light sources, I never realized how nice of an effect you can get with only sprites and additive blending!


 

anything