Jump to content


Photo

Surface Alpha Problems Explained


  • This topic is locked This topic is locked
25 replies to this topic

#1 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 13 May 2010 - 09:46 PM

At some point when I was still using game maker, I tried to render things to a surface either as a way to precompute some effects or to do things like motion trails.
And then I noticed that alpha blending doesn't quite work right. The only fix I came up with at the time was to add a pass over the surface which bumps its alpha component back up to 1, but this left the problem of incorrectly blended colours unsolved and made it impossible to use the alpha channel. I know plenty of people still encounter this problem in some form or other, so here is a pair of great articles about it by Shawn Hargreaves, one of the core XNA developers.
http://blogs.msdn.co...omposition.aspx
http://blogs.msdn.co...lied-alpha.aspx

I'm hoping after some discussion here, someone will whip up a demo and put it up on the Tutorials/Examples forum.
  • 4

#2 IceMetalPunk

IceMetalPunk

    InfiniteIMPerfection

  • GMC Elder
  • 9328 posts
  • Version:Unknown

Posted 14 May 2010 - 01:33 AM

This is great when drawing geometric shapes. But how do you efficiently premultiply the colors of image resources, like sprites and backgrounds?

I suppose you could try and follow this process:

1) Draw image to extra surface.

2) Set blend mode to (bm_src_alpha,bm_zero).

3) Draw a rectangle with the desired multiplying factor as its alpha on top of everything.

4) Set blend mode to (bm_subtract).

5) Draw a black, opaque rectangle over everything to clear it all to transparent.

6) Set blend mode to (bm_add).

7) Draw the sprite, with an alpha of the appropriate multiplying factor and a blend color of c_black. This sets the transparency to what you want.


Convert that to a sprite and draw that sprite. That seems a bit inefficient to do every time you want to draw an image to a surface.

-IMP :D :lol:
  • 0

#3 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 14 May 2010 - 02:47 AM

You can pre-premultiply by just processing the sprites after loading them. Its as simple as px.rgb*=px.a.
  • 0

#4 IceMetalPunk

IceMetalPunk

    InfiniteIMPerfection

  • GMC Elder
  • 9328 posts
  • Version:Unknown

Posted 14 May 2010 - 08:40 PM

You can pre-premultiply by just processing the sprites after loading them. Its as simple as px.rgb*=px.a.

Yes, I know. My question is how to get that effect in GM. That seems to be a per-pixel effect, no? If you do it with blend modes, like I mentioned, it'll be inefficient. If you do it per-pixel, snails will finally become marathon champions in comparison.

Sorry, misread. I suppose you could do that. But if you have many sprites that could (or definitely will) be drawn to a surface, then it'll be a slow startup.

I guess you could have a "Please Wait... Processing Images..." screen on game start. It still seems inefficient to me, though, to have to create an entire duplicate of your entire sprites "library" just so you can draw them to a surface properly... I feel like there must be a more real-time way of doing this...

-IMP :blink: :whistle:

Edited by IceMetalPunk, 14 May 2010 - 08:43 PM.

  • 0

#5 xot

xot

    GMC Dismember

  • GMC Elder
  • 4775 posts
  • Version:GM:Studio

Posted 15 May 2010 - 01:35 AM

I feel like there must be a more real-time way of doing this...


I think all you need to do to premultiply the sprites is to draw the sprites to a surface with _ext(bm_src_alpha_sat, bm_zero). From there you can draw the surface to the destination with _ext(bm_one, bm_inv_src_alpha).

Either do this in-game as an intermediate pass between the sprite and the destination, or to preprocess sprites before the game starts (or maybe re-saved to disk to be loaded by the game at run-time).
  • 1

#6 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 16 May 2010 - 01:53 AM

Here's a quick demo of this at work:
www.messy-mind.net/temporary/premultiplied.gmk

I learned two things while making it: photoshop does not play nice with premultiplied alpha (I ended up writing an xna script to do it), and game maker surfaces don't work correctly with some nvidia cards. This demo flat out looks wrong on my nvidia desktop, but works perfectly fine on my ati laptop.

Edit: revised the demo a bit to show comparison between the surface drawing and surface-less. If your GM is handling your blending correctly then they'll be identical.

My goodness, after being away from GM for a while its such a pain to use. No auto-indent. Stupid resource naming scheme. Stupid editor that wastes screen space and leaves none where you need it. Argh!

Edited by GearGOD, 16 May 2010 - 04:25 AM.

  • 0

#7 blue_chu_jelly

blue_chu_jelly

    Shut your FMaj7

  • GMC Member
  • 228 posts

Posted 16 May 2010 - 04:48 AM

when the surface is premultiplied it looks the same surface-less. bm_normal doesn't though. Is this what's meant to happen? I've got an nvidia 9800GTX+ by the way.
  • 0

#8 xot

xot

    GMC Dismember

  • GMC Elder
  • 4775 posts
  • Version:GM:Studio

Posted 16 May 2010 - 05:11 AM

That's the point. Drawing to a surface is not exactly the same as drawing to the back buffer, which causes results to look different when using normal blending. This technique of premultiplying the RGB channels with the Alpha channel, and drawing with an alternate blending mode, allows surface drawing to act like the back buffer does when drawing with normal blending. This makes surfaces more useful and intuitive for many common tasks. The fact that the two modes looked the same shows that it is working. When set to "bm_normal" mode (space bar), you can see how surfaces and the back buffer work differently when you toggle between them with the Enter key.

Thanks for sharing this with us, GearGOD. I did my best to port it to GM7 for myself and others who have not yet registered GM8. I hope I didn't miss anything.

Posted Image

(EDIT: Rehosted file.)

Edited by xot, 20 May 2010 - 01:37 AM.

  • 1

#9 Master Xilo

Master Xilo

    GMC Member

  • GMC Member
  • 394 posts
  • Version:GM8

Posted 17 June 2010 - 11:15 AM

Thanks GearGOD, this will be handy.
  • 0

#10 NGen

NGen

    GMC Member

  • New Member
  • 26 posts

Posted 19 June 2010 - 05:41 PM

Would this work with sprites whose alpha values are constantly fluctuating? From my understanding you have to pre-multiply values for each value of transparency.
  • 0

#11 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 19 June 2010 - 07:53 PM

No. If you're changing alpha, all you have to do is multiply the blend colour by it (or don't, and you'll get additive blending!). Read my comments.
  • 0

#12 bennikniet

bennikniet

    GMC Member

  • GMC Member
  • 14 posts

Posted 05 July 2010 - 10:28 AM

Maarten Baert is a mod of the dutch GMC. He wrote a tutorial about PMA, and made 2 scripts to convert your sprites to PMA sprites.

Tutorial ( Dutch )

Scripts

This man is an expert on how DirectX is used in Game Maker.
Credits to Maarten Baert!
  • 0

#13 Medusar

Medusar

    GMC Member

  • GMC Member
  • 1228 posts
  • Version:GM:Studio

Posted 05 July 2010 - 02:41 PM

Maarten Baert is a mod of the dutch GMC. He wrote a tutorial about PMA, and made 2 scripts to convert your sprites to PMA sprites.

Tutorial ( Dutch )

Scripts

This man is an expert on how DirectX is used in Game Maker.
Credits to Maarten Baert!

That is a nice explanation! For those interested who don't understand Dutch, here is a translation:

Premultiplied alpha: explanation, advantages and usage
This tutorial is about the technique in general. It is not only applicable to Game Maker.
GM-version: 6, 7 and probably 5 too
Registration required: Unfortunately (for blend modes)
Level: Advanced

This tutorial is about premultiplied alpha. I’ll explain what the technique means, what the advantages of it are compared to normal alpha, and how to use it in Game Maker. Especially now that alpha transparency will become much more important in Game Maker 8, it seemed a good idea to explain this, for actually premultiplied alpha is the 'natural' way to represent colours. Some people even go as far to say that the normal alpha calculation is simply wrong (and I largely agree with that).

There is one problem: the sprite editor of Game Maker 8 does not really seem to be made for premultiplied alpha. That is quite stupid, for I’m 99% certain that the sprite editor (just like practically every other drawing program supporting alpha) works with premultiplied alpha internally. For that is the only way to be able to correctly handle blending operations internally. You can easily circumvent this problem by using these scripts.

My renderer (which is in Model Creator) has also got the option, you can turn off 'compensate for alpha value' off there. When I made the renderer, I knew nothing about premultiplied alpha, but the renderer used it internally without me realising it. I just noticed that the calculations became incredibly much simpler and more rational if I simply already multiplied the colour with the alpha value. That was because premultiplied alpha is associative, but you’ll read more about that in this tutorial.


What is premultiplied alpha?
Premultiplied alpha is an alternative method to represent colours with an alpha value. Put very simply, the only difference is that with premultiplied alpha, the colours have already been multiplied with the alpha value, while with normal alpha that only happens at the moment the colour is drawn. I’ll explain it with an example. In all examples in this tutorial I’ll represent colours as (r, g, b, a) where all values go from 0 to 1. I’ll to this to make calculations of blend modes easier.
- With normal alpha, or straight alpha, the colours are represented as the colour of the material (r ,g, b) and the opacity (the inverse of transparency) of the material (a). This way, a bright red material that’s 40% transparent gives the colour value (1, 0, 0, 0.6). This form of alpha is used with the blend mode src_alpha:inv_src_alpha.
- With premultiplied alpha, this works differently. Wit this, the colour shows how much colour it adds to the material, and the alpha shows how much of the colour below the material is removed. This way, the same red material has the colour value (0.6, 0, 0, 0.6). You can see that the colour part in this has already been multiplied with the alpha value. This form of alpha is used with the blend mode one:inv_src_alpha because the colour value has already been multiplied with the alpha value.
"Now is that such a huge difference? With those blend modes it comes down to exactly the same thing?" is what you probably think. It is not the same at all, you’ll notice that if you read on. Premultiplied apha assumes a whole different way of thinking.

The advantages
Premultiplied alpha has incredibly many advantages. This is because it’s actually a much more rational method, mathematically, than normal alpha. I’ll give the most important advantages here, if you get to work with it more, you’ll see that there are many more advantages.
  • There is only one kind of fully transparent colour.
    With normal alpha, there are loads of colours which are all transparent: as long as the alpha value is 0, the colour itself doesn’t matter. With premultiplied alpha, that’s different: if the alpha value is 0, all colour channels are the same, for they are multiplied by 0. You’ll notice this has advantages later on.
  • Interpolation works much more rational (or even better, interpolation works)
    In many cases (linear, or some other) interpolation of colours is used, for instance when you draw a stretched sprite or if you use primitives (or models!) with vertex colours. With this, two colours are mixed with this formula:
    newcolour = t*colour1 + (1-t)*colour2
    The t in this shows how much of each colour is taken. This formula is applied to all four channels (red, green blue and alpha) of the colour. With normal alpha, the result of this formula is quite strange: suppose you mix the colours (1, 0, 0, 1) (red) and (0, 0, 0, 0) (fully transparent) with t=0.5. You expect to get semitransparent red, but what you’ll actually get is dark red, (0.5, 0, 0, 0.5). So if you have a sprite with a red square in the middle and transparent edges, you’ll find a strange black ring near the edges. Oh dear, what have we done now? The solution that is found everywhere on the Internet, recommended by everyone and also automatically applied in Game Maker 7 and 6 if you make transparent sprites, is the following: replace the colour for all transparent pixels near the edges with the colour of the edge. Solved! Or not?
    Posted Image
    The transition of red to transparent with normal alpha. Correction was used for the bottom half.
    The strange results you get near the edges are only a clue for a much bigger problem. Because the colour and the alpha value are only multiplied after the interpolation, the colour transition is no longer linear! For you multiply two linear functions, and the result of that is a quadratic function! The interpolation is wrong everywhere unless the colour value (or alpha value) is equal at two pixels, but it is clearest near the edges because the biggest difference in colour and alpha is usually there. If you were to make an image with a lot of difference in colour and alpha, you can see that error everywhere. Apart from that, you’ll get into trouble when more pixels with different colours lie around the same transparent pixel.

    But suppose you had used premultiplied alpha. You wouldn’t have had a problem at all! For (0.5, 0.5, 0.5) is simply semitransparent red with premultiplied alpha! With this, you haven’t only solved the probem with the edges, but also the (usually hardly visible) error on the whole image. Congratulations, you’ve just discovered the most important advantage of premultiplied alpha for computer graphics!
  • Blending operations are associative.
    Associative means that it doesn’t matter how you place the parentheses in a calculation. This is also valid for premultiplied alpha:
    blendmode(colour1, blendmode(colour2, colour3)) = blendmode(blendmode(colour1, colour2), colour3)
    What is the advantage of that? If you program a renderer, you’ll notice. And otherwise you’ll notice it when you read the next advantage.
  • The result of blending operations gives correct results in the alpha channel.
    Almost a year ago I wrote a tutorial on blend modes. Blijbol responded to that with this message:

    I don’t fully understand the explanation by the way, you say that this is bm_normal:

    (Rs, Gs, Bs, As)*source_blend_factor + (Rd, Gd, Bd, Ad)*destination_blend_factor =
    (Rs, Gs, Bs, As)*(As, As, As, As) + (Rd, Gd, Bd, Ad)*(1-As, 1-As, 1-As, 1-As)

    Resulting alpha = As2 + Ad – Ad*As
    As = 1/2 (just a random value)
    Ad = 1 (Whatever is already there is not transparent)

    Resulting alpha= (1/2)2 + 1 – 1*1/2 = 1/4 +1 – 1/2 =3/4

    My experience is that pixes on the screen don’t just become 25% transparent. What happens to the alpha which is calculated like that?

    And a bit further:

    It will probably be shocking news to you: the alpha calculation you give is correct. A surface actually becomes transparent when you draw transparently to it.

    Back then, I simply thought this was an error in the design of Game Maker (and later of DirectX, for it has the same problem by itself). Now though, I understand that that wasn’t the case at all: the error is the blend mode you set. If you set it to src_alpha:inv_src_alpha, you’ll get:
    Resulting alpha = As2 + Ad*(1-As)
    That’s not rational. If you think about it for a minute, you’ll come to the conclusion that this should be
    Resulting alpha = As + Ad*(1-As)
    without the square. And if you think about it a little more, you’ll realise that you would get this if you use one:inv_src_alpha. Premultiplied alpha, great!

    A direct consequence of this is that if you draw several things to surfaces to draw them to the screen in one step, you get the same result as if you draw them directly to the screen. To do that, you have to draw everything to the surface with one:inv_src_alpha, and then draw the surface itself with one:inv_src_alpha to get a correct result. For the surface also contains a lot of colours in premultiplied alpha format. This is the associativity I talked about.
  • You can draw the other way round.
    If the current render target – the DirectX term for what you’re drawing to, a dynamic texture (surface) or the back buffer (normal screen) – has an alpha channel, you can achieve interesting results by swapping source and destination. In Game Maker, only surfaces have an alpha channel and the normal screen doesn’t, so that won’t work of course. It will work with surfaces only. To draw the other way, you have to swap source and destination with the blend mode calculations:
    (Rd, Gd, Bd, Ad)*1 + (Rs, Gs, Bs, As)*(-1Ad, 1-Ad, 1-Ad, 1-Ad) = (Rs, Gs, Bs, As)*(1-Ad, 1-Ad, 1-Ad, 1-Ad) + (Rd, Gd, Bd, Ad)*1
    This matches inv_dest_alpha:one. If you draw things with this blend mode (with premultiplied alpha of course), then it’s just like you draw these things 'behind' the things you drew earlier on.
  • You can use normal blending and additive blending in one sprite, in one blend mode.
    With premultiplied alpha, you can use additive blending by cheating a bit with the colour value: you can set it to a bit higher than the alpha value, which effectively adds light. If you know that additive blending is one:one with premultiplied alpha, you’ll understand that you can achieve the same with one:inv_src_alpha if alpha is simply 0. If you remember the explanation at the beginning of this tutorial, you’ll understand why: the alpha value only shows how much of the colour of the back is removed. If this is 0, all of the background is kept, just like with additive blending. This also allows you to create effects 'between' normal blending and additive blending. Because you don’t have to change the blend mode, you’ll also save some calculating time (It won’t really matter in Game Maker, but if you use C++, it matters a lot, for instance if you quickly try to draw thousands of particles, which sometimes are additive and sometimes normal).
  • You can use 'multipass rendering' easier.
    Multipass rendering is a technique to draw the same thing several times (with different colours, blend modes and/or texture) to have more possibilities. This technique was thought of when multitexturing (several textures on top of each other on one primitive) wasn’t possible yet. Because Game Maker doesn’t support multitexturing anyway, it’s a very suitable way to achieve reasonably advanced effects. Multipass rendering is reasonably simple with primitives which are opaque, but much trickier when pieces are transparent. Which blend modes you have to use depends a lot of what you want to achieve, so I’ll give you a concrete example: suppose you made a 3D model, and you have two textures you can both use for that model. You could make that something break by drawing cracks onto the second texture. You then want the first texture to transition to the second slowly. If the model is fully opaque, you can simply change the alpha value the second time you draw the model, but if there are transparent pieces it’s trickier. You have to do something like this:
    draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
    draw_set_color(merge_color(c_black, c_white, 1-broken));
    draw_set_alpha(1);
    d3d_model_draw(model, x,y,z, background_get_texture(bg_tex1));
    draw_set_color(merge_color(c_black, c_white, broken));
    draw_set_alpha(0);
    d3d_model_draw(model, x,y,z, background_get_texture(bg_tex2));
    The only difference between the two passes is that we adapt the colour and alpha. Your model can of course not contain any vertex colours, for then changing the draw colour and alpha has no effect.

Usage in Game Maker
To use additive blending in Game Maker is not very difficult. The only thing you have to set is the blend mode:
draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
With this, you can use both normal and additive blending, so that makes everything even easier. Now you have to think about setting your colours correctly by multiplying the values with the alphavalue you use (or perhaps not if you use partially additive blending). You can use the following script for that:
// premultiply_color(color,alpha)
return make_color_rgb(
round(color_get_red(color)*alpha),
round(color_get_green(color)*alpha),
round(color_get_blue(color)*alpha)
);
Once you get used to it, you can of course also set the colours correctly straight away. You have to do the same for all your sprites and backgrounds. That sounds complicated, but by itself it’s simple, however Game Maker tries to do corrections to your sprites. You therefore cant put premultiplied sprites straight into GM, but what you can do is make sprites with straight alpha and convert these into sprites with premultiplied alpha with these scripts.

An alternative is to load the sprites externally. Game Maker then does not do that correction. And what’s also possible, is to import the sprite and alpha of the sprite separately, and merging them at game start using sprite_set_alpha_from_sprite. But in particular in GM8 it’s a lot simpler to just use the scripts I gave.

You can use premultiplied sprites in the renderer of Model Creator by turning off 'compensate for alpha':

If this is switched on, the color of the pixels will be divided by their alpha value to compensate for the blending used in Game Maker. This means a face with color (50,50,50,0.5) will create pixels with color (50,50,50,0.5), which is what you want most of the time. If you turn this of, pixels with color (25,25,25,0.5) will be created.

Remember that you can load these into GM8, for then GM8 tries to correct them again. So this is only useful if you want to load them externally, or if you load colour and alpha as separate sprites into GM.

Conclusion
I hope this technique is useful for you. It may sound tricky, but once you get used to it, you’ll notice how many new possibilities this technique has. Good luck!

Edited by Medusar, 05 July 2010 - 02:42 PM.

  • 4

#14 blendman

blendman

    GMC Member

  • New Member
  • 42 posts

Posted 27 December 2010 - 11:53 AM

Hi

This thread is very interesting.

I have read the tutorial from Maarten Baert, and try the file from GearGod, but I can't obtain, what I would like, with alpha premultiplied.

I use a sprite (png with alpha chanel, for example), and change his color by :
draw_sprite_ext(Sprite,0,mouse_x,mouse_y,global.size,global.size,0,global.color,global.alpha); 

Is there a technic with the color changed by draw_sprite_ext and alpha_premul ?

a picture to explain :
Posted Image


Here is my file :
http://blendman.free...emul_sprite.gmk
  • 0

#15 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 28 December 2010 - 01:55 AM

Two things:
Did you actually premultiply the images involved?
As stated in my code and my posts, you must multiply the drawing colour components by the alpha component. Eg:

r = 255 * alpha
b = 255 * alpha
g = 255 * alpha

color = make color from rgb

draw_sprite_ext(Sprite,0,mouse_x,mouse_y,global.size,
global.size,0,color, alpha);
  • 0

#16 blendman

blendman

    GMC Member

  • New Member
  • 42 posts

Posted 28 December 2010 - 12:58 PM

Two things:
Did you actually premultiply the images involved?
As stated in my code and my posts, you must multiply the drawing colour components by the alpha component. Eg:

r = 255 * alpha
b = 255 * alpha
g = 255 * alpha

color = make color from rgb

draw_sprite_ext(Sprite,0,mouse_x,mouse_y,global.size,
global.size,0,color, alpha);

Hi

Thank you for your answer.

I have tried to change that, but I still have a bug :
Posted Image

The file :
http://blendman.free...ed_modified.gmk

To change the color, the keys are :
R, G and B ;).

Thank you again.

Edited by blendman, 28 December 2010 - 12:59 PM.

  • 0

#17 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 29 December 2010 - 08:59 AM

Two things:
Did you actually premultiply the images involved?
[...]


  • 0

#18 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 749 posts
  • Version:GM8.1

Posted 29 December 2010 - 07:10 PM

There were three problems:
- You have to premultiply the color when you use draw_sprite_ext:
draw_set_blend_mode_ext(bm_one,bm_inv_src_alpha)
draw_sprite_ext(brush_s,0,mouse_x, mouse_y,global.size,global.size,0,premultiply_color(global.color,global.alpha),global.alpha);
- You have to use one:invsrcalpha when drawing the surface:
draw_set_blend_mode_ext(bm_one,bm_inv_src_alpha);
draw_surface(0,0,surfdraw);
draw_set_blend_mode(bm_normal);
- There was a bug in my conversion scripts because sprite_set_alpha_from_sprite works differently in GM8 (it multiplies the old alpha value by the color of the second sprite). I've fixed it now (the scripts are here).

Your program now works correctly:
http://andere.maarte...emul_sprite.gmk
  • 0

#19 blendman

blendman

    GMC Member

  • New Member
  • 42 posts

Posted 30 December 2010 - 02:14 PM

Maarten Baert : thank you very very much ! It works perfectly. I will use this in my 2D application ;).

GearGod : Sorry, I haven't understand that the sprite would be premultiplied. If I use a premultiplied sprite, it works better.
  • 0

#20 blendman

blendman

    GMC Member

  • New Member
  • 42 posts

Posted 19 January 2011 - 02:03 PM

Hi

I have some new questions about alpha premultiplied :
- is there a way to "un-premultiplied" (de-premultiplied?) the png saved by surface_save(), with GM ? Because the png saved is premultiplied, and I would like to use it on a non-premul layer (surface).
- When I use draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha), the alpha of the surface isn't working as a normal alpha, which is logical because the surface isn't drawn in a "normal" blend mode. How can I have an alpha working correctly ?

Thank you again for your answer.

PS : I use a lot this technic in my 2D application made with Game Maker8 (You can see a video of this programm, named "animatoon" : http://vimeo.com/18884395)

Edited by blendman, 19 January 2011 - 08:25 PM.

  • 0

#21 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 749 posts
  • Version:GM8.1

Posted 23 January 2011 - 02:22 PM

- is there a way to "un-premultiplied" (de-premultiplied?) the png saved by surface_save(), with GM ? Because the png saved is premultiplied, and I would like to use it on a non-premul layer (surface).

Unfortunately there's no blend mode for division, so you will have to do this manually (pixel by pixel). You might want to create a DLL that can do this for you if the image is very large.

- When I use draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha), the alpha of the surface isn't working as a normal alpha, which is logical because the surface isn't drawn in a "normal" blend mode. How can I have an alpha working correctly ?

If the surface was created correctly, drawing it with draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha) should work correctly. However, if you're using draw_surface_ext (or similar) and you're using the alpha argument, you have to premultiply the color argument too. Otherwise it won't work properly.
  • 0

#22 blendman

blendman

    GMC Member

  • New Member
  • 42 posts

Posted 27 January 2011 - 05:05 PM

Hi Maarten, Thank you very much for your answer ;) (dank u !).


- is there a way to "un-premultiplied" (de-premultiplied?) the png saved by surface_save(), with GM ? Because the png saved is premultiplied, and I would like to use it on a non-premul layer (surface).

Unfortunately there's no blend mode for division, so you will have to do this manually (pixel by pixel). You might want to create a DLL that can do this for you if the image is very large.

I have tried with draw_getpixel(), but it's too long with a layer > 64*64.
So, for the moment, I use silent.dll +irfanviewer to convert the layer saved (in png), and eventually reload this png in my 2D application (made with GM), and it works fine.

If I can later, I will try to wrote a dll to do this operation.


- When I use draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha), the alpha of the surface isn't working as a normal alpha, which is logical because the surface isn't drawn in a "normal" blend mode. How can I have an alpha working correctly ?

If the surface was created correctly, drawing it with draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha) should work correctly. However, if you're using draw_surface_ext (or similar) and you're using the alpha argument, you have to premultiply the color argument too. Otherwise it won't work properly.

Oh, thank you , it works better if I premultiply the color of the layer, with the alpha of the layer !

Thank you again.
  • 0

#23 golden_cow2

golden_cow2

    GMC Member

  • New Member
  • 178 posts

Posted 16 April 2011 - 06:03 AM

I'm not sure if this is the same thing, but I'm using surfaces and alpha and there is a problem so it can't hurt to ask.

In order to cut back on instances, I combine the sprites of all the tile objects I placed in the room editor into one large sprite, using a surface, which I then use for collision checking. But when I make the sprite, it looks different than the tiles did pre-surface. If I use the replace_premultiplied_sprite() script, it makes the whole screen a sprite, and mutes the colors even more (though I must be using it wrong, I don't understand anything in this thread).

Here's the code I'm using
//make_sprite(object)
//combines the sprites of all instances of "object" and destroys all
//instances of "object"

var obj, surf, sprite;
obj = argument0;
surf = surface_create(room_width,room_height);

surface_set_target(surf);
draw_clear_alpha(c_white,0);
with(obj)
    {
    draw_sprite(sprite_index,image_index,x,y);
    instance_destroy();    
    }
surface_reset_target();

sprite = sprite_create_from_surface(surf,0,0,room_width,room_height,false,false,0,0);

surface_free(surf);

replace_premultiplied_sprite(sprite);

return sprite;

//I just use sprite_index = make_sprite(obj_...)

And here is the gmk.
  • 0

#24 mireazma

mireazma

    GMC Member

  • GMC Member
  • 357 posts

Posted 06 January 2012 - 12:28 PM

You can pre-premultiply by just processing the sprites after loading them.

Should I understand that the sprites need only be processed once? After that no extra code would be necessary? I'd be happy to take away as much as possible from the CPU loading at real time.
GearGOD's gmk has the every-step approach.
I've tried Maarten's scripts but I can see no effect. I called the scripts once, in the creation event of an object.

Edited by mireazma, 06 January 2012 - 12:29 PM.

  • 0

#25 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 22053 posts
  • Version:GM:Studio

Posted 06 January 2012 - 06:11 PM

You can pre-premultiply by just processing the sprites after loading them.

Should I understand that the sprites need only be processed once? After that no extra code would be necessary? I'd be happy to take away as much as possible from the CPU loading at real time.
GearGOD's gmk has the every-step approach.
I've tried Maarten's scripts but I can see no effect. I called the scripts once, in the creation event of an object.


I use them in the game start event of the first object in my game (usually my logo) and it looks like this :


Spoiler



The scripts are "scr_create_premultiplied_sprite" and "scr_replace_premultiplied_sprite" (the names may be slightly different!). When drawing to the surface you use the extended blend mode

draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha)

And that's it!
  • 0

#26 mireazma

mireazma

    GMC Member

  • GMC Member
  • 357 posts

Posted 08 January 2012 - 11:35 AM

Thanks. I was missing the extended blend mode thing.
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users