Handling transparency for sprites with holes in them
#1 Members - Reputation: 132
Posted 30 January 2013 - 05:03 PM
#3 Members - Reputation: 958
Posted 30 January 2013 - 08:58 PM
Since you don't want partial translucency: just discard pixels with an alpha of less than 0.5. As a bonus you won't even need to sort quads since there isn't any blending involved, the depth buffer by itself is enough.
EDIT: oh, I see what you mean. But the method still works for linear filtered textures (for example, look at the trees in Super Mario 64 - yes, it's the same method). If you want partial translucency then you have no option but to do proper blending.
Edited by Sik_the_hedgehog, 30 January 2013 - 08:59 PM.
#4 Members - Reputation: 210
Posted 30 January 2013 - 09:10 PM
There's a method of computing a "distance field" from the texture to give the texture an edge that's sharp but not blocky. Here's a paper discussing how to use the method for textured fonts/decals:
http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
I'm not sure how easily it can be applied to full-color sprites, but I think it could be done.
Edited by BLM768, 30 January 2013 - 09:11 PM.
#5 Members - Reputation: 132
Posted 01 February 2013 - 07:06 PM
can't alpha blend them?
Not really unless I want to also use the depth buffer. Here's a scene with proper sorting and linear filtering:
And the scene without proper sorting and no use of discard in the fragment shader:
And the scene where I discard pixels with alphas of 0.5 or less:
#6 Members - Reputation: 958
Posted 02 February 2013 - 03:51 AM
Yeah, you need to make sure that the pixels that are supposed to be transparent still have the same colors as the surrounding ones that aren't, or color bleeding like in the last pic will happen. Also you need to make the borders of the texture translucent if you don't want sudden clipping (if you want a texture to wrap around (e.g. a wall) then by all means make the borders opaque though).
There isn't really any workaround for the jagged edges, that comes with bitmaps. Either make them a higher resolution, or resort to vector graphics (at least to cut the borders). Although remember that most of the time you won't have sprites that close to the camera anyway, so the texels won't look as big in practice.
Edited by Sik_the_hedgehog, 02 February 2013 - 03:53 AM.
#7 Members - Reputation: 132
Posted 02 February 2013 - 08:30 PM
Yeah, you need to make sure that the pixels that are supposed to be transparent still have the same colors as the surrounding ones that aren't, or color bleeding like in the last pic will happen
I thought the bleeding was caused by the depth buffer in my picture.
In my last two examples I'm drawing the slug before the wall behind it. That draws a big square to the depth buffer. In the picture where I don't discard any fragments at all I get the big blue square surrounding the slug and blocking the wall behind. In the picture where I discard fragments with alpha less than 0.5 there are still fragments that, while having an alpha less than zero, still block the wall behind since they're drawn to the depth buffer.
Edited by AaronWizardstar, 02 February 2013 - 08:31 PM.
#8 Members - Reputation: 958
Posted 03 February 2013 - 04:39 AM
The discard method (last picture) doesn't have any blending at all, pixels are always either opaque or missing, so the depth buffer never gets in the way (it's exactly the same as drawing a normal triangle). It's when you have blending that the depth buffer becomes an issue (first image).
The "bleed" pixels have alpha > 0.5, the reason they have the wrong color is because the texture filtering is being applied between the solid and transparent texels (this is true even for the alpha channel, which is why the borders are rounded). The behavior is entirely correct, the textures need to take this into account.
#9 Members - Reputation: 532
Posted 03 February 2013 - 10:20 AM
A more exact method would be draw everything back to front and only discard pixels with alpha==0. Or clear framebuffer to black not blue, draw front to back, discard everything with apha!=1 to make use of the depth buffer for solid objects, then draw anything thats transparent back to front and this time discard alpha==0 and alpha==1.
Edited by wintertime, 03 February 2013 - 10:23 AM.
#10 Members - Reputation: 946
Posted 03 February 2013 - 11:42 AM
I think the blue border is not from texture filtering but from combining the half transparent pixels with the blue background pixel thats already in the framebuffer. Then its written back into the framebuffer and the depth of the sprite is put into the depth buffer so it blocks the later drawing of the wall. You need to change the alpha to 1 for all pixels you dont discard inside the fragmentshader to prevent this.
Or just disable alpha blending.






