PNG alpha channel problems

Started by Akril15, Tue 19/02/2013 03:39:43

Previous topic - Next topic

Akril15

I've been working on a game with another person who is supplying the graphics for it. Recently, I encountered a strange problem when I was working on the game's inventory.

The inventory items are going to be PNGs with shadows created using a Photoshop's Drop Shadow effect. The PNGs look fine once they are exported from Photoshop, but when they're imported to the game and I run the game, this is what happens:

The image on the right is what I see in the game. The shadow creates a semi-transparent "cut-out" in the inventory window,
revealing the background behind it. At other times, the shadows appear completely opaque, both in the editor and the game. I have no idea why this is happening. Both the game and the PNGs are 32-bit, I'm not importing the PNGs incorrectly either. Does anyone know what's going on, and how I can resolve this issue?

Khris

I believe this happens if the Inventory GUI's background image isn't also a 32bit PNG with transparency. Try making it one even if it doesn't have to be.

Cogliostro

Akril15,

PNG Transparency doesn't work in the GUI's.  Use is as an object or a character and everything is fine.  Use in in the inventory screen and things go wrong.

- Cogliostro
"First things first, but not necessarily in that order." - Dr. Who

monkey0506

No, Khris is right. Please don't post wrong answers when the right answer has been given (7 hours ago previously! It's not like you didn't see the post...). It makes people hate you.

Personally I think it's a bug in AGS that the GUI background should have to be 32-bit with alpha channel in order for GUIControls on the GUI to have alpha transparent sprites, but that is the correct way of making it work ATM.

Akril15

The GUI background I'm using *is* a 32-bit PNG with alpha channel. I tried searching the forums for a confirmation on the "buttons/inventory items can't use alpha channel" statement, but I was unable to find anything conclusive.

I was able to find a work-around for the alpha channel problem which involved making the inventory window background a completely transparent graphic and positioning another GUI with the inventory window graphic underneath it. This solved the problem fairly well (it's still a little annoying to deal with, though).

Khris

Quote from: Akril15 on Tue 19/02/2013 03:39:43At other times, the shadows appear completely opaque, both in the editor and the game.

Do you mean that other inventory items show up opaque in-game? Or does it vary for the same sprite? (I believe the editor runs at 16bit, so alpha-PNGs won't look as expected but will in-game.)
Also, could you upload a faulty item's graphic and your background somewhere so we can check it?

Akril15

I actually discovered that just the buttons that use PNGs have opaque shadows. The inventory items are the only ones with shadows that create that "punch-out" effect.

As for uploading graphics from the game, I want to first make sure that it's okay with the artist if I upload them.

Akril15

All right -- here's an inventory item, and here's the inventory window (it's actually a cropped version of the one I'm working with, but it still produces the exact same problem).

(And since I neglected to mention it in the initial post, I'm using version 3.2.1.111 of AGS.)

Khris

Did some testing, unfortunately nothing worked.

Assigning the item image to a room object works perfectly fine, but if it's an inv item, the transparent area cuts a hole, and if it's a button's image, the shadow is a uniform grey with colored pixels near the edge.

Crimson Wizard

#9
Changing "GUI alpha rendering style" (General settings) to "Classic" will make inventory item render same to button.
Same happens if I dont use an image for GUI background, but use any plain color instead.
However, if I make GUI fully transparent (background color = 0) makes both inventory item and button graphics work properly (with translucent shadows).
E: ah right, Akril15 mentioned that already.


EDIT: The engine code actually shows, that inventory items are rendered using different operation, than buttons. That explains the difference.
I think the item image is being just plain copied to the GUI background, making it translucent too.

The button rendering is another problem. I can now seewhat is wrong there, but I can't understand what were Chris Jones intentions about that.
Thing is, the function that blends button with gui background 1) summs alpha channels 2) uses control colors 3) discards background colors. This means that no matter what you do, the result will always have control colors, and no background colors at all :-/.

Summing up, the GUI translucency works rather weird. I never used it, and I do not know the story of how this feature was added, and what it was expected to do. I may be mistaken, but, in my opinion, the feature is either broken, or have limited usage.

Khris

So I guess it's workaround time then.

I can see two possibilities:
a) Make the inventory GUI's background image use a tiled pattern beneath the inventory window and include the background in the item graphic
b) use Calin's AGSBlend plugin to dynamically combine the item graphic with the part of the GUI background graphic beneath it and assign the result as item graphic

Crimson Wizard

#11
Found how make a fix (changed engine code):

[imgzoom]http://img46.imageshack.us/img46/369/67318096.jpg[/imgzoom]

Left is Inventory item in the Inv. Window (wrong render), right is Button (correct render).
(Don't mind the nuke, I am making test games with graphics ripped from random AGS games ;))

Now, the plan is to make tests and see if it does not break other cases.

Crimson Wizard

#12
Does anyone know any games where the GUI controls with alpha channel were used?

Also, I posted my ideas about the possible fix here: http://www.adventuregamestudio.co.uk/forums/index.php?topic=47699.0
Unfortunately no one made any comment;  should have posted in this forum instead.

I ended up with this blender function:
Code: cpp

union
{
    struct
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
        unsigned char a;
    } rgba;
    unsigned long color;
} col_x, col_y, col_r;

// x is color of overlaying surface pixel
// y is color of underlying surface pixel
// n is not used for this blender
unsigned long _fixed_additive_alpha_blender(unsigned long x, unsigned long y, unsigned long n)
{
    col_x.color = x;
    col_y.color = y;

    if (col_y.rgba.a == 0)
        return x;
    if (col_x.rgba.a == 0xff)
        return x;
    if (col_x.rgba.a == 0)
        return y;

    col_r.rgba.a = col_x.rgba.a | col_y.rgba.a;
    col_r.rgba.r = col_y.rgba.r - (((col_y.rgba.r - col_x.rgba.r) * col_x.rgba.a) / 0xff);
    col_r.rgba.g = col_y.rgba.g - (((col_y.rgba.g - col_x.rgba.g) * col_x.rgba.a) / 0xff);
    col_r.rgba.b = col_y.rgba.b - (((col_y.rgba.b - col_x.rgba.b) * col_x.rgba.a) / 0xff);
    return col_r.color;
}


I think it is also possible to speed it up a little by replacing "/ 0xff" with ">> 8" at the cost of loosing a small bit of precision (~1/255).
BTW, it is not 100% precise anyway, because I removed the branch for X color component larger than Y component. In such case the value is the result of 8-bit variable overflow; but since color component has the same value range as unsigned 8-bit variable, it will be generally correct, with the loss of precision only about 1/255 (should not be noticeable by human eye).

Crimson Wizard

I was thinking more about this, and I am starting to think I better not do any "quick fix" at all :-\.

Reason is, there could not be any ultimate "correct" way to blend one layer (gui controls) into another (main gui surface).

What Chris Jones did is a blender that summs alpha (decreases total translucence of gui) and replaces main gui colors with gui control ones.
What I suggested to do up there is to summ alpha and combine colors.
These are two distinctive methods, but it cannot be said that the first is incorrect and the second correct. They both are correct - for what they are supposed to do. We may speak only about choosing one as "default", depending on what game creator usually expects from translucent gui controls being drawn over (possibly) translucent gui window. And what this "default" expectation is? I don't know. What do you think?

Ideally there should be a blending option for every gui window, at least, or even gui control. But that is more work than a common hotfix.

Snarky

#14
There are old threads around somewhere that explain how this feature came to be the way it is (Edit: here). It was an attempt to fix artifacts in an older, even brokener method, but it still doesn't really work right.

I think there is a "correct" way, which is to treat them as if they're drawings on transparent glass plates (or plastic cels, if you prefer an animation metaphor) in front of the rest of the screen. In other words, same as a Photoshop layer with "normal" blend mode.

Quote from: Crimson Wizard on Wed 24/04/2013 20:58:20
What I suggested to do up there is to summ alpha and combine colors.

That's not quite right either; the new alpha shouldn't be a simple sum. Rather, if alpha is a value from 0 (transparent) to 1 (opaque), the combination is combined_alpha = 1 - (1-front.alpha)*(1-back.alpha) (where front is the gui control and back the gui). That way, two 50% transparent layers on top of each other combine correctly to 75% opacity, rather than 100%.

The color value is pretty straightforward: combined_rgb = front.rgb * front.alpha + back.rgb * (1 - front.alpha). This is all in pseudo-code, obviously. If you want to have multiple controls on top of each other (which I don't even remember if can happen in AGS), just run the calculation repeatedly, starting from the back.

There could be an argument to support the old method for backwards compatibility reasons, and other blending modes could be added as a way to achieve special effects (like in Photoshop), but the correct normal behavior is pretty clear, IMO.

Crimson Wizard

Well, I wasn't aware of what this meant for, that's why I kept summing alphas; the global setting is called "Additive Opacity" after all. But I can clearly see this is not what normally people would like, because when you put an alpha control with e.g. a shadow on top of translucent gui, the shadow part actually makes main gui brighter (or rather more saturated), because alpha is increased.

The method you suggested sounds right. I guess overlaying controls may work in current engine, because controls are drawn with regard to z-order, and their colors will summ up at the main gui surface (or temporary bitmap, to be precise).

Regarding backward compatibility, the question is, were there games with translucent guis and gui controls made with the new blending method in such a way, that would be broken if this method is fixed. This new blending function was introduced in AGS 3.0.2, so it is there for a while already. In the worst case, we may add another option which would select the fixed blender for the game - this would act as a temporary fix before per-control blending property is implemented.

Calin Leafshade

"additive opacity" refers to the alpha within a surface.

So the GUI is a surface in and of itself and if you have a button with .5 alpha and the background graphic has .5 alpha, then the total alpha should be 1 but *only* within the surface. If the GUI has its alpha set to .5 this does not effect the alpha of the surface itself but rather the drawing of the surface to the back buffer.

Crimson Wizard

Quote from: Calin Leafshade on Thu 25/04/2013 15:46:12
"additive opacity" refers to the alpha within a surface.

So the GUI is a surface in and of itself and if you have a button with .5 alpha and the background graphic has .5 alpha, then the total alpha should be 1 but *only* within the surface. If the GUI has its alpha set to .5 this does not effect the alpha of the surface itself but rather the drawing of the surface to the back buffer.
Yes... now I remember thinking like that.
And also I remember why there was a problem to do this correctly.
Both the gui and controls are drawn directly over room background, there's no intermediate step which would allow to draw gui controls with their opacity on gui background, then draw main gui on room with its own opacity. When gui controls are drawn, they are drawn over room, which already has main gui pixels over it :-\.

Crimson Wizard

Wait wait wait, actually nevermind the post above... I probably had brain block.
Main gui surface is rendered over "temporary" bitmap, and then controls are rendered over the same temporary bitmap.

Then temporary bitmap will be drawn over screen.

Snarky

Quote from: Calin Leafshade on Thu 25/04/2013 15:46:12
"additive opacity" refers to the alpha within a surface.

So the GUI is a surface in and of itself and if you have a button with .5 alpha and the background graphic has .5 alpha, then the total alpha should be 1 but *only* within the surface. If the GUI has its alpha set to .5 this does not effect the alpha of the surface itself but rather the drawing of the surface to the back buffer.

By "GUI alpha" I assume you mean GUI.Transparency (or 100 - GUI.Transparency, to be precise).

That's how it does work (as far as alpha goes) under this additive opacity mode, but I don't think it's how it should work. "Additive opacity" is a very rough approximation of the correct calculation, and it would be better to (at least have the option to) use the correct formula.

Anyway, is this really something AGS has to solve? Aren't there already library functions in Allegro or whatever that allows you to combine two graphics with alpha-channels and get the correct result?

Calin Leafshade

I was only referring to the term itself.

Snarky

OK. I just wanted to make sure that it wasn't misunderstood to mean that additive opacity produces a "correct" result (for reasonable interpretations of "correct").

Crimson Wizard

#22
Quote from: Snarky on Thu 25/04/2013 16:33:17
Anyway, is this really something AGS has to solve? Aren't there already library functions in Allegro or whatever that allows you to combine two graphics with alpha-channels and get the correct result?

Allegro is made as a "wireframe" where you may connect your own callbacks to many of the operations, blending being one of them, so this approach is principally valid.
As for built-in blenders, unfortunately standard Allegro's alpha blender doesn't work, because it copies the resulting pixels with zero alpha value; if drawn this way all the translucent controls will create 100% transparent holes at their places on main gui surface.

Good news though, while examining the Allegro source code and comparing with various CJ's custom blenders I found that I may simply copy default Allegro's alpha blender and modify it so that it will keep alpha value. The result is almost what we need, I think, minus summing the alpha (alpha remains the one of the main gui surface).

Here's code:
Spoiler

Code: cpp

unsigned long _myblender_alpha32(unsigned long x, unsigned long y, unsigned long n)
{
    unsigned long res, g, alpha;

    n = geta32(x);

    if (n)
        n++;

    alpha = y & 0xff000000;

    res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y;
    y &= 0xFF00;
    x &= 0xFF00;
    g = (x - y) * n / 256 + y;

    res &= 0xFF00FF;
    g &= 0xFF00;

    return res | g | alpha;
}

[close]



//=========================================================
EDIT: how it looks like.
Room background is an AGS editor splash, gui is a yellow rectangle with alpha gradient (lower alpha towards left side), and gui button is poor guy from Laura Bow 2 in sarcofagus (keep forgetting his name, Dr. Carter maybe?). Gui button graphic is divided into 2 parts: left half is translucent and right part is opaque.

Spoiler

Crimson Wizard

#23
I added combined opacity as Snarky suggested, hopefuly I implemented his formula right:
Code: cpp

back_alpha = (255 - (255 - geta32(x)) * (255 - geta32(y)) / 255) << 24;
<...>
return res | g | back_alpha;


Here are the comparisons. The control with left translucent part over translucent gui over room:
Spoiler

The same control over opaque gui:
Spoiler

Does it look OK now?


//---------------------------
Quote
combined_alpha = 1 - (1-front.alpha)*(1-back.alpha) (where front is the gui control and back the gui). That way, two 50% transparent layers on top of each other combine correctly to 75% opacity, rather than 100%.

This way if the control is opaque, the summ will always be opaque regardless of back surface alpha. Is this correct?

HandsFree

Quote from: Crimson Wizard on Wed 24/04/2013 10:41:53
Does anyone know any games where the GUI controls with alpha channel were used?
I don't think it's a secret that the original question was about the King's Quest 4 remake for which we are about to release a short demo.
We took out the sprites that caused a 'hole' in the gui, but we still have the ones where alpha is displayed as opaque black.
We also had to replace the Sierra style speech portraits because the background turned out completely black.

So if this were to be fixed that would be a great help!  8-)

Crimson Wizard

#25
Quote from: HandsFree on Fri 26/04/2013 09:50:31
We took out the sprites that caused a 'hole' in the gui, but we still have the ones where alpha is displayed as opaque black.
IIRC the "holes" are caused by inventory items, because they were not fixed by CJ when he added new alpha blending.
Opaque "alpha" bug happens with other controls (e.g. buttons).
If I'll be able to find proper blending algorythm I will need to apply it to both cases, and it will work identical for all gui sprites.

I asked about games because I wanted to make tests and see that I did not screw anything.

Snarky

Nice work, CW!

Quote from: Crimson Wizard on Fri 26/04/2013 07:08:28
I added combined opacity as Snarky suggested, hopefuly I implemented his formula right:
Code: cpp

back_alpha = (255 - (255 - geta32(x)) * (255 - geta32(y)) / 255) << 24;
<...>
return res | g | back_alpha;

That looks generally right, although I don't know about the left-shift. You're bit-wise OR-ing it together with other values, so I guess it has something to do with getting it into the right part of the return value?

QuoteDoes it look OK now?

It looks OK as far as I can tell, but it's hard to evaluate with such a weird example. I'd probably just try to overlay two 50%-transparent white sprites on a black background, as well as maybe a blue and a green sprite. The other thing you could do is recreate the setup in Photoshop, and then put this on top with blend mode "difference." If the results are identical, the image should be completely black. (Due to rounding errors, every pixel may not be 100% black, though.)

Quote
Quote
combined_alpha = 1 - (1-front.alpha)*(1-back.alpha) (where front is the gui control and back the gui). That way, two 50% transparent layers on top of each other combine correctly to 75% opacity, rather than 100%.

This way if the control is opaque, the summ will always be opaque regardless of back surface alpha. Is this correct?

Yes. If front.alpha is 1 (opaque), the second term goes to 0, and combined_alpha = 1 - 0 = 1, so it's always opaque. The same happens if the gui is opaque (back.alpha = 1). And if one of them is completely transparent, the alpha of the other is used. It all works out.

Crimson Wizard

#27
Editor and engine executables with a fix, if anyone wants to test:
http://www.mediafire.com/?ta43i8g5lvh4qg4
!WARNING! based on 3.3.0 beta, so don't use it with your only real game copy.
There's an extra choice for Alpha gui rendering style in Global settings.

Quote from: Snarky on Fri 26/04/2013 16:27:46
It looks OK as far as I can tell, but it's hard to evaluate with such a weird example. I'd probably just try to overlay two 50%-transparent white sprites on a black background, as well as maybe a blue and a green sprite.

Spoiler



[close]




//------------------------------------------------------
EDIT:
There's a problem with transparent gui parts, this new blender treats magic pink as an actual color, and the result is blending translucent  control parts with with magenta.


//------------------------------------------------------
EDIT2:
Something that worries me is that when I am putting a button with "shadow" (see early posts in this thread for an example) on the translucent gui background, the shadow part becomes brighter rather than darker.

Blackthorne

I'm having a problem with Alpha-Blended sprites as portraits - we have portraits in the game that have no backgrounds - the sprites are alpha blended, and if used as an object, they appear correct with their anti-aliased edges, but as portraits there is artifacting around the edge.


Bt
-----------------------------------
"Enjoy Every Sandwich" - Warren Zevon

http://www.infamous-quests.com

Knox

If we previously used AdditiveOpacity with 3.2 without any problems, what advantages would there be for us to switch to the new MultipliedTranslucence mode in 3.3? (Curious because if I switch to the new mode in 3.3 I get pink around the alphas of certain sprites, so if there aren't any major advantages I might just stay in AdditiveOpacity).

--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

Quote from: General_Knox on Sat 07/09/2013 23:03:08
If we previously used AdditiveOpacity with 3.2 without any problems, what advantages would there be for us to switch to the new MultipliedTranslucence mode in 3.3?
It is not about advantage, these are two different types of combining alpha values. The "multiplied translucence" was added because in SOME cases "additive opacity" worked weird (check the beginning of this thread to see examples of what I mean).
If "Additive oppacity" works well for you, you may just keep using it.

Quote from: General_Knox on Sat 07/09/2013 23:03:08
Curious because if I switch to the new mode in 3.3 I get pink around the alphas of certain sprites
Hmmm, that may or may not be an error. Can you upload your sprites somewhere and explain how do you combine them?

Knox

#31
Ok as soon as I get home tonight I'll post pics.
EDIT: Got in late tonight, make that tomorrow!
--All that is necessary for evil to triumph is for good men to do nothing.

Monsieur OUXX

Just a useless supportive message, to say that I'm glad (like every average AGS user I suppose) that those things are being perfected: Less and less knowledge in "alpha bugs" is required by users. That's that much less work during early ddesign and final testing!
Thanks a lot Crimson and pals!
 

Knox

#33
Ok, here's an example of the pink alphas with MultipliedTranslucence.

Additive Opacity, Copy Source Color:
Spoiler
[close]

Multiplied Translucence, Blend Source Color:
Spoiler
[close]

How it is setup in the editor so it works well with Additive Opacity:
Inventory window has 3 layers (gInvBackground, gInventory, gInventoryOver)

Z = 0 Background image behind the inventory items
Spoiler
[close]

Z = 1 Inventory items with no background image (work-around to fix alpha issues with Additive Opacity)
Spoiler
[close]

Z = 3 Gui frame that goes over everything to hide inventory item scrolling. A highlight button with an alpha frame gets moved along with the mouse
Spoiler
[close]

If I remove the gui gInvBackground, replace the BackgroundImage of the gInventory to the same sprite (#1000), then I no longer get pink around the inventory items in Multiplied Translucence...however the button btnInv_Hilite's alpha still remains pink.

**Let me know if you want the png files too (which ones), I'll post them aswell.
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

#34
Hmm... so, to clarify.
You have 3 GUIs placed atop of each other:
1. gInvBackground, which has an opaque dark-blue background and inventory grid drawn on it.
2. gInventory, which is just a fully transparent (filled with magic pink), and InventoryWindow control.
3. gInventoryOver, which has another grid with transparent "cuts" to allow items from gInventory be seen through; and a button with a 8-point star shaped transparent "hole" (at least that's what I think I see).

My main question is this: which of those sprites have alpha channel and which do not?
I must make a test game and reproduce this behavior to see what's going on and how fixes to engine change the situation.

Knox

#35
Here is the gInvBackground sprite (no transparency/alpha, png)
Spoiler
[close]

Here is the btnInv_Hilite sprite, a highlight frame with shadow (transparency, png)
Spoiler
[close]

Here is the gInventoryOver sprite that goes over everything (transparency, png)
Spoiler
[close]

Here is one of the inventory items (transparency, png)
Spoiler
[close]

gInventory is magic pink, no sprites. Note that if you plug in a sprite into gInventory's background, the pink around the inventory items disappears, but the pink around the btnInv_Hilite remains.

(PS: How do I "collapse" images so they dont take up the whole page?)
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

Quote from: General_Knox on Wed 11/09/2013 23:03:13
(PS: How do I "collapse" images so they dont take up the whole page?)

Use [ hide ][ /hide ] tag.

Crimson Wizard

#37
The problem is this: the alpha blending function treats background (Gui) "magic pink" (transparency color) as a normal color and merges foreground (e.g. button)) with it producing corresponding result.
"Additive Opacity" does not do that because it simply discards background RGB values and paints foreground over.

This would be, perhaps, fixed by completely abstaining from using magic pink on your sprites, but it is not so simple... The situation worsens, because AGS converts pixels with alpha=0 into magic pink when the sprite is imported.
This means that all your fully transparent 32-bit pixels become magic pink pixels. This is made to make alpha-sprites compatible with AGS drawing logic.
This is why the button blending still produces pink shades in the above example: the transparent area in the gInventoryOverlay is painted in magic pink in the engine.

The only solution I see is to add a special case to blending function which will deal with magic pink.
The question is, how to deal with it. If the background color is "fully transparent", this means that only the foreground color should be drawn. But if the foreground alpha is less than 1.0, the result should be ForegroundRGB * ForegroundAlpha... is it? This means that the more transparent foreground is, the darker colors this will produce. Probably, this will be the same as if the background color was ARGB 00-00-00-00 (the foreground colors merging with black).
Is this correct/acceptable? Any thoughts on this?

Snarky

#38
Ah damn! My fault. There's something wrong with the formulas I gave earlier; the combined_rgb value calculation assumes the back.rgb is opaque:

Code: AGS
combined_alpha = 1 - (1-front.alpha)*(1-back.alpha);
combined_rgb = front.rgb * front.alpha + back.rgb * (1 - front.alpha);  // This is wrong!


Off the top of my head, I think the correct calculation is more like:

Code: AGS
combined_rgb = (front.rgb * front.alpha + back.rgb * (1 - front.alpha) * back.alpha) / combined_alpha;  // Now verified


Sorry about that! I believe if you switch to this formula, it should also take care of the magic pink problem without any special case code.

Spoiler
Incidentally, this is why many graphics formats store the rgb values premultiplied with the alpha. In that format, that last calculation really does become simply:

Code: AGS
combined_rgb_premult = front.rgb_premult + back.rgb_premult * (1 - front.alpha);
[close]

Edit: I've had a chance to think it over, and also check with Wikipedia (see the final formula in the Description section), and yes, this is the correct formula.

Knox

I came across another bug since upgrading to 3.3 but I guess its related to the same alpha issue you're currently working on (?)

In AGS Draconian r7, I have a mini-game where you cut the grass with a tractor. The room background is the "cut" grass, and over that I placed 12 characters (4 per row, 3 rows) that are zones of "long grass", and 12 characters underneath them for "long grass shadow". None of the sprites are using alpha. When the player goes over one of the zones (character), I drawString with magic pink to "eat through" the character's long grass sprite, revealing the cut grass underneath. I also do the same to the "shadow" character's sprite, only offset to give the illusion of depth. Here is a part of the code:
Code: ags
    
    DrawingSurface *dsCutGrass_A = this.GetDrawingSurface();
    dsCutGrass_A.DrawingColor = COLOR_TRANSPARENT;
    //dsCutGrass_A.DrawCircle(iMowerX+iXzoneAdjust+iRd, iMowerY+iYzoneAdjust+iRd, iMowerRadius);
    dsCutGrass_A.DrawString(iAdjX, iAdjY, eFontMowerCutter, sLt); //M=25% N=50% //O=100%
    dsCutGrass_A.Release();  
   
sLt is "J" in the font "eFontMowerCut" (I replaced the "J" with a circle of cut grass.

Works in Draconian r7:
Spoiler
[close]

Not working in 3.3 (any mode doesn't matter, still get this blue color):
Spoiler
[close]
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard


Crimson Wizard

Quote from: Snarky on Fri 13/09/2013 09:26:38
Code: AGS
combined_rgb = (front.rgb * front.alpha + back.rgb * (1 - front.alpha) * back.alpha) / combined_alpha;  // Now verified


<...>
I believe if you switch to this formula, it should also take care of the magic pink problem without any special case code.

<...>
Edit: I've had a chance to think it over, and also check with Wikipedia (see the final formula in the Description section), and yes, this is the correct formula.

Okay, with this formula I am combining translucent Gui & Button sprites and the results are identical to what I see in graphic editor (I use Paint.Net) when I make 2 translucent layers over 1 opaque one. If I do not make final division (by combined alpha) the result has something in common, but with relatively darker colors (less brightness?).

But now I got two different troubles:
1) When opaque control color is drawn on opaque gui color, result is pitch black. Translucent colors combine with opaque fine.
2) When translucent control color is drawn over gui pixels with zero alpha (e.g. magic pink 0x00FF00FF) the result is opaque.
Maybe I made some silly mistake in algorythm implementation...

Snarky

Yeah, I think there must be an implementation error somewhere there.

Code: AGS
combined_alpha = 1 - (1-front.alpha)*(1-back.alpha);
combined_rgb = (front.rgb * front.alpha + back.rgb * (1 - front.alpha) * back.alpha) / combined_alpha;


1) If front.alpha = 1 (opaque), then combined_alpha = 1-0 = 1, and combined_rgb = (front.rgb * 1 + 0) / 1 = front.rgb. So the result should be the front color. (Back color or opacity shouldn't matter, since all those terms go to 0.) Must be a mistake somewhere in the code.

2) If back.alpha = 0 (completely transparent), then combined_alpha = 1 - (1-front.alpha)*(1-0) = 1 - 1 + front.alpha = front.alpha. So the combined opacity should just be the front opacity. However, from that hex value, it looks like the magic pink pixels don't in fact have zero alpha, but are set to opaque (which I guess is the whole point of magic pink; I thought it was stored internally with 0 opacity, but that doesn't seem to be the case), so yeah, it's not going to work. I think you will have to add a special case line of code to treat magic pink with opacity 1 as having opacity 0. (I think this is a bit of an ugly hack, and that in 32-bit games we should just use the alpha channel instead of relying on "magic pink", but I guess that's the way AGS works.)

Crimson Wizard

#43
Quote from: Snarky on Mon 16/09/2013 10:08:42However, from that hex value, it looks like the magic pink pixels don't in fact have zero alpha, but are set to opaque (which I guess is the whole point of magic pink; I thought it was stored internally with 0 opacity, but that doesn't seem to be the case)
No, it has opacity (alpha) = 0. The format is ARGB with blue being the lower byte and alpha being the highest byte...
So 0x00FF00FF is:
A: 00
R: FF
G: 00
B: FF:

EDIT: corrected myself.

Crimson Wizard

#44
Okay, I found the mistake that produced unexpected black color.

Regarding magic pink (eurgh!), this was simply because the Gui sprite did not have alpha channel. Well.. it technically was 32-bit image, but the sprite was marked as not having alpha-channel, and AGS just blended it as opaque surface over room.

To make things even more confusing, the Gui which does not have background image at all, but has background color set to transparent, works properly (translucent buttons are rendered as translucent over room background).
I feel like this:
(wtf)?????????

Anyway, this is another issue and should be dealt with separately.

E: For now I am glad to tell that Col. Knox'es Inventory works well both in its original and modified way (without gInvBackground).

Snarky

Quote from: Crimson Wizard on Mon 16/09/2013 10:16:50
The format is ARGB with blue being the lower byte and alpha being the highest byte...
So 0x00FF00FF is:
A: 00
R: FF
G: 00
B: FF:

What, you mean you need to mix TWO colors to get magenta on an RGB screen?! :-D Maybe I should think before posting...

Nice work, CW! I'm pleased as punch to have alpha-blending of multiple layers working properly at last.

Crimson Wizard

#46
Just a small note,

this:
Code: text

combined_alpha = 1 - (1-front.alpha)*(1-back.alpha);

is algebraically (sp?) equivalent to
Code: text

combined_alpha = front.alpha + back.alpha * (1-front.alpha);

The latter formula is given on wiki page. It is also slightly faster to calculate.

Snarky

Sure, I just gave it in the form that corresponds to how it was logically derived, since that seemed like it would be more obvious.

(The idea is to think of transparency as the fraction of light from below "passing through" the layer to the eye, so if you have multiple layers you multiply the fractions together: If one layer is 1/2 transparent and the other layer 1/3 transparent, together they are 1/6 transparent, for example. So you get combined_transparency = front.transparency * back.transparency. The rest is just the conversion to opacity: alpha = 1 - transparency.)

Crimson Wizard

#48
@General Knox
Regarding your grass-cutting minigame -
http://www.adventuregamestudio.co.uk/forums/index.php?topic=47666.msg636467623#msg636467623

I found that this happens only with WFN fonts (TTF work properly). One silly mistake in 3.3.0. Will be fixed in the next build.

Knox

Quote from: Crimson Wizard on Tue 17/09/2013 20:44:54
@Colonel Knox
Regarding your grass-cutting minigame -
http://www.adventuregamestudio.co.uk/forums/index.php?topic=47666.msg636467623#msg636467623

I found that this happens only with WFN fonts (TTF work properly). One silly mistake in 3.3.0. Will be fixed in the next build.


Ah no I got demoted to Colonel, hehe. Nice, things are really moving along! :grin:
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard


Crimson Wizard

#51
I kinda feel myself an idiot now, because all those formulas were in Calin Leafshade's AGSBlend plugin.
The advantage of these are that they process all pixels in one loop, while Allegro drawing calls a function for every pixel, which may affect perfomance in the long run (ironically, the Allegro's loop itself is written is assembler).
Slight disadvantage is that Calin's are not optimized in the same way as Allegro's algorythms are (for instance he multiplies/divides on 255, while there's a way to work with 256 (which should be converted to bitwise shift by compiler, which is way faster) while loosing half-of-percent in color precision (which is not a big deal with 32-bit colors and AA anyway).

I am now thinking about implementing all those nice Calin's blending modes, maybe in the next subrelease, like 3.3.1 or something (yeah I still hope we can make 3.3.0 a release candidate, heh).

Knox

Quote from: Crimson Wizard on Sat 21/09/2013 17:16:58
I am now thinking about implementing all those nice Calin's blending modes, maybe in the next subrelease, like 3.3.1 or something (yeah I still hope we can make 3.3.0 a release candidate, heh).

Bah, just put 'em in 3.3.0, hehe! :grin:
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

Alright, I pushed an update to repository, keeping fingers crossed. :tongue:

Calin Leafshade

I just looked at the commit and i have to say *FINALLY*.

Excellent work CW.

Knox

Quote from: Calin Leafshade on Thu 26/09/2013 05:28:57
I just looked at the commit and i have to say *FINALLY*.

Excellent work CW.

...you implemented Calin's AGSBlend plugin? :shocked:
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

Quote from: Knox on Fri 27/09/2013 12:02:19
Quote from: Calin Leafshade on Thu 26/09/2013 05:28:57
I just looked at the commit and i have to say *FINALLY*.

Excellent work CW.

...you implemented Calin's AGSBlend plugin? :shocked:

No, (not yet). Just proper default alpha blending for now.

Knox

Hey Crimson!

Beta 8 fixed all the alpha problems I've been having, yay! I can now set Visual settings to Multiplied Translucence + Proper Alpha Blending and everything works great. :grin:

Do you know if there is a way currently to get semi-transparent alpha sprites working on the "text window gui", other than having to use pain-in-the-butt work-arounds? I've got a shadow on my text window but it isn't drawing properly from what I tested so far (minor minor issue though, for the time being I can just not use the shadow).

--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

#58
Quote from: Knox on Wed 02/10/2013 04:30:05
Do you know if there is a way currently to get semi-transparent alpha sprites working on the "text window gui", other than having to use pain-in-the-butt work-arounds? I've got a shadow on my text window but it isn't drawing properly from what I tested so far (minor minor issue though, for the time being I can just not use the shadow).

To clarify: you have a sprites with alpha set as TextWindow gui parts (corners & center), or you have something that casts shadows upon TextWindow?
Thinking about this, I could have missed the text window drawing when was fixing the gui alpha blending. I am going to check this.
E: Also - dialog options!

Knox

Yep, that's what I meant. I have semi-transparent shadows under the text window (so the corners and sides have semi-transparent shadows, the center is opaque).

Want me to send you an example of the text window sprites?

PS: You're really awesome, by the way, fixing all these issues. :=
--All that is necessary for evil to triumph is for good men to do nothing.

Crimson Wizard

Quote from: Knox on Wed 02/10/2013 17:11:10
Yep, that's what I meant. I have semi-transparent shadows under the text window (so the corners and sides have semi-transparent shadows, the center is opaque).

Did that; and also added "HasAlphaChannel" property to DialogOptionsRenderingInfo class, so that custom options rendering could have alpha sprites:

Spoiler


[close]
Spoiler


[close]

monkey0506

I can't wait for the release of that game CW! 8-) Actually, that's pretty cool! It looks like this allows drawing semi-transparent sprites against a transparent background? Would it be possible to also draw an anti-aliased TTF font against a completely transparent background? That was one feature that I would like...working around it is terrible.

Crimson Wizard

#62
Quote from: monkey_05_06 on Sun 06/10/2013 20:58:40Would it be possible to also draw an anti-aliased TTF font against a completely transparent background? That was one feature that I would like...working around it is terrible.
Hmm, you can already do that in AGS: http://www.adventuregamestudio.co.uk/forums/index.php?topic=47966.msg636469376#msg636469376
The problem arises when you draw AA TTF fonts over translucent surface.


Quote from: monkey_05_06 on Sun 06/10/2013 20:58:40
I can't wait for the release of that game CW! 8-)
lol, game?
Hmm... (roll) hmmmmmm.........

monkey0506

Quote from: Crimson Wizard on Sun 06/10/2013 21:08:58
Quote from: monkey_05_06 on Sun 06/10/2013 20:58:40Would it be possible to also draw an anti-aliased TTF font against a completely transparent background? That was one feature that I would like...working around it is terrible.

Hmm, you can already do that in AGS: http://www.adventuregamestudio.co.uk/forums/index.php?topic=47966.msg636469376#msg636469376
The problem arises when you draw AA TTF fonts over translucent surface.

Umm... no. Because then the text gets a pink outline. When drawing it on a DrawingSurface (NOT A GUI). Unless you expressly fixed that.

Crimson Wizard

#64
Quote from: monkey_05_06 on Sun 06/10/2013 21:27:11
Umm... no. Because then the text gets a pink outline. When drawing it on a DrawingSurface (NOT A GUI). Unless you expressly fixed that.

Just tested this in AGS 3.2.1,"Anti-alias TTF fonts" = True, font is Arial.
Code: ags

// room script file
Overlay *o;
DynamicSprite *s;
function room_AfterFadeIn()
{
  s = DynamicSprite.Create(300, 50, true); // <-- if this is 'false' there's no AA (all text pixels are opaque)
  DrawingSurface *ds = s.GetDrawingSurface();
  ds.Clear(COLOR_TRANSPARENT);
  ds.DrawingColor = Game.GetColorFromRGB(128, 128, 0);
  ds.DrawString(2, 2, eFontFont3, "This line is drawn with TTF");
  ds.Release();
  o = Overlay.CreateGraphical(100, 100, s.Graphic, false); // <-- this can be 'true', result is the same
}


Result:


Do I miss anything?


Things went bad when I added outline though, automatic outline made some letters transparent where they should not be... or maybe it overlapped with wrong offset, hard to say for sure. But still I do not see any pink pixels. :-\

Knox

Quote from: Crimson Wizard on Sun 06/10/2013 18:59:39
Did that; and also added "HasAlphaChannel" property to DialogOptionsRenderingInfo class, so that custom options rendering could have alpha sprites:

Oh yah!!  :grin:
--All that is necessary for evil to triumph is for good men to do nothing.

monkey0506

@CW: Sorry, I remembered wrong about the pink outline. The problem is that the image used for DialogOptionsRenderingInfo is created with no alpha channel so if the background is completely transparent then there is no anti-aliasing. If I clear the surface to non-transparent or draw an image first then anti-aliasing works. Against a transparent background the text is aliased.

Vaunted

#67
Thanks for all the work on this. It's something I was struggling with in older builds, specifically with GUI buttons, and 3.3.0 has fixed a LOT of my problems. I'm still getting some weird issues with alpha blending, however. Specifically, if I use png buttons with alpha transparency in a GUI with a transparent background (bg image and color both 0) using the Multiplied Translucence setting, it leaves a 1-pixel wide faint pink border around each sprite.

(Those left and right arrows are their own images, however, and I notice that THEY don't have a weird border where they blend onto the image behind them.)



I've tried setting the background image to a fully transparent image rather than leaving it as 0, but it just makes the phantom border a deeper shade of pink.

I've also tried using additive opacity instead, and actually does seem to solve the pink border issue! However, it seems to break in the opposite direction, drawing properly onto GUIs with transparent bgs but turning things with an alpha channel drawn onto another image (but only within the same GUI?) into a hideous blob.


Sorry if this is a known issue in the beta, I couldn't find this precise issue being discussed (although it's possible I did and I just didn't understand).

edit: Fixed some erroneous information, forgot how I had the images in the GUI set up. Sorry.

Crimson Wizard

#68
Quote from: Vaunted on Thu 10/10/2013 04:32:53
Thanks for all the work on this. It's something I was struggling with in older builds, specifically with GUI buttons, and 3.3.0 has fixed a LOT of my problems. I'm still getting some weird issues with alpha blending, however. Specifically, if I use png buttons with alpha transparency in a GUI with a transparent background (bg image and color both 0) using the Multiplied Translucence setting, it leaves a 1-pixel wide faint pink border around each sprite.

This is something unexpected. Do you use the latest beta version (#8)?

Quote from: Vaunted on Thu 10/10/2013 04:32:53
I've tried setting the background image to a fully transparent image rather than leaving it as 0, but it just makes the phantom border a deeper shade of pink.
If the background was made of "magic pink" color, then this one is correct behavior, because when translucent image blends over the surface, it uses exactly the background color and does not consider pink as a "magic transparent" color. Instead you could try to create a 32-bit background image where every pixel is RGBA = (0,0,0,0) (shown as "checkered" color in many graphic editors).
If the background was precisely transparent (0,0,0,0), then this might be an error...

Vaunted

Quote from: Crimson Wizard on Thu 10/10/2013 10:56:47
This is something unexpected. Do you use the latest beta version (#8)?
Ack! I checked this before I posted, but I somehow goofed anyway. You're right, I was a couple betas behind. Running it with Multiplied Translucense in beta8 works properly. Thanks, and sorry to have made such a silly mistake.

monkey0506

Is it safe to assume that this:

Quote from: Crimson Wizard on Sun 06/10/2013 18:59:39Did that; and also added "HasAlphaChannel" property to DialogOptionsRenderingInfo class, so that custom options rendering could have alpha sprites...

Is the resolution to this:

Quote from: monkey_05_06 on Sun 06/10/2013 23:15:14@CW: Sorry, I remembered wrong about the pink outline. The problem is that the image used for DialogOptionsRenderingInfo is created with no alpha channel so if the background is completely transparent then there is no anti-aliasing. If I clear the surface to non-transparent or draw an image first then anti-aliasing works. Against a transparent background the text is aliased.

Knox

Hi Crimson,

Everything works ok with alpha on the text windows, however I'm using the SSH's GuiPortrait v1.00 to display speech and it doesn't seem to work with that module (GSay function)http://www.adventuregamestudio.co.uk/forums/index.php?topic=34996.0.

Gsay with GuiPortrait module:


Normal text display works perfectly fine though:


**EDIT: Ok Im not sure if its only me but the normal .Say command doesn't seem to display alpha either?

--All that is necessary for evil to triumph is for good men to do nothing.

SMF spam blocked by CleanTalk