1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GMS 2 Save surface with the "correct" alpha blending

Discussion in 'Programming' started by CodeManu, Jan 21, 2020.

  1. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    Hey all!

    I've been trying to export an surface (via surface_save method) into a .png, but due to how alpha blending works on surfaces it gets tinted (towards black as I'm using draw_clear_alpha(c_black,0) to clear the surface).

    I know this is the correct behaviour, and that It can be fixed by premultiplying alpha and using bm_one,bm_inv_src_alpha blendmode when drawing, but this doesn't apply to saving the surface as you can't apply the blendmode to the saved file.

    Any clues on how to proceed?
     
  2. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    Bump and a bit more info about the issue:

    This is how the image looks on aseprite with a 0.5 alpha, with the alpha being reduced on aseprite: https://i.imgur.com/GLCfPxh.png

    This is how it looks with a 0.5 alpha, with the alpha being reduced on GMS and then saved with surface_save(): https://i.imgur.com/QETe8XK.png

    The problem here is very simple, the image is getting merged with a black background with alpha 0, (rgba = 0,0,0,0) so it gets darker than it "should". As I say, this is working as intended, but not the result I'm looking for. You can fix this inside GMS by premultiplying alpha to rgb values of the image and then using blendmode_ext(bm_one,bm_inv_src_alpha) while creating the surface, and then using that same blendmode while drawing, but this last step can't be done while saving into a .png

    So TL;DR, I'd like to have the first image I posted instead of the second one when exporting the surface.
     
  3. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,417
    In order to get the first version, you would need to disable blending as you write to the surface in the first place, otherwise it'll always be blended with whatever the background colour is.

    Can you write to the surface without blending, then write to the alpha channel directly later, by locking off the colour channels and doing a filled rect over the whole image?

    (kind of like this....)

    clear surface
    Disable blending
    draw whatever
    lock RGB channels
    draw rect with alpha of 0.5
    enable blending

    save surface..... (or of course leave alpha as full, and just draw the surface alpha'd)
     
    Last edited: Jan 22, 2020
  4. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    Hi Mike, thanks for taking your time to answer!

    That would certainly work if the image has only an overall alpha value of 0.5, but I'm afraid it wouldn't work if the image has different alpha at different points, for example, a gradient that goes from 1 to 0 alpha from left to right. I haven't tested it yet (it's late here, I'll do that tomorrow) so I might be wrong.
     
  5. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,417
    Or draw it in 2 parts.... draw the opaque bits first - without blending (or alphatest), then the variable alpha bits once you lock off the colour channels.
     
  6. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    I still didn't have time to test it, but giving it a second thought, wouldn' the alpha channel still be blended with the clear surface value? RGB channels would mantain the sprite values as they are not blended, but if the alpha is 0.5, and the surface clear alpha is 0, wouldn't it output a 0.25 final alpha value?

    Also, this solution will work for a single sprite, but how would it be handled for multiple sprites with different alpha values? I suppose you could repeat that process and bounce surfaces for every image but It'd get expensive really fast.
     
  7. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    I've been doing some tests, and as I thought, it works perfectly for a single sprite, but sadly overlapping sprites with different alphas are not blended at all. Any chance for another idea?
     
  8. josyanf1

    josyanf1 Member

    Joined:
    Jan 12, 2018
    Posts:
    18
    Hi guys! The Mike's response also works for a single sprite. But like 'CodeManu', sprites with different alphas are not blended :(
     
  9. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    Bump, anybody?
     
  10. CodeManu

    CodeManu Member

    Joined:
    Jun 20, 2016
    Posts:
    29
    Bump again, I still can't solve this :(
     

Share This Page