GMS 2.3+ surface_save(application_surface) alpha blending problem...

FoxyOfJungle

Kazan Games
Hi!

#1 - I have this code in the Step Event of an object:

GML:
if keyboard_check_pressed(vk_space) {
    surface_save(application_surface, "ImageFile.png");
}

#2 - Result:



As you can see, there is a color difference in anything with transparency (like the shadow of the player) between the saved image and the game's application_surface.
This is normal? Why does it happen? How do I make this not happen? Is it a bug and should I report it?

Notes: I didn't disable the application_surface and I'm not drawing manually, it's all default, I'm just saving the application_surface.


Saved surface:




I did a test and this also occurs the same problem:
GML:
_surf = surface_create(surface_get_width(application_surface), surface_get_height(application_surface));
surface_copy(_surf, 0, 0, application_surface);
surface_save(_surf, "10.png");
 
Last edited:

basementApe

Member
I've had similar problems drawing sprites with alpha to surfaces before. What worked for me was setting gpu_set_colorwriteenable(true, true, true, false) right before drawing the sprite and then setting it back to gpu_set_colorwriteenable(true, true, true, true) after the drawing finished.
 

FoxyOfJungle

Kazan Games
I've had similar problems drawing sprites with alpha to surfaces before. What worked for me was setting gpu_set_colorwriteenable(true, true, true, false) right before drawing the sprite and then setting it back to gpu_set_colorwriteenable(true, true, true, true) after the drawing finished.
Yes, I already tested that and it doesn't work, unfortunately:

GML:
_surf = surface_create(surface_get_width(application_surface), surface_get_height(application_surface));

surface_set_target(_surf);
draw_clear_alpha(c_black, 0);
surface_reset_target();

gpu_set_colorwriteenable(true, true, true, false);
surface_copy(_surf, 0, 0, application_surface);
gpu_set_colorwriteenable(true, true, true, true);

surface_save(_surf, "10.png");
The saved surface turns all transparent. And I really need to copy the surface, so there's no way to use this function in this case.

Already tried:
  • Put gpu_set_colorwriteenable(true, true, true, false); on the Draw Begin and gpu_set_colorwriteenable(true, true, true, true); on Draw End.
  • Create a surface, define the target, clear the black alpha, disable the alpha write, draw the application_surface and re-enable everything again, reset the target and save the surface after 1 step.
  • Save the surface inside the Draw GUI event.

Thanks.
 
Last edited:

FoxyOfJungle

Kazan Games
I submitted a bug report:
Ticket number: 187540

Hello!

Well, it doesn't matter what I do, but the application_surface is always saved with a different color than it actually is. This happens if there are transparent sprites in it, such as the player's shadow and others. The pixels where there was transparency, get a darker color in the saved or copied surface.

I used surface_copy() and surface_save() and it's like the opacity is doubled, getting a darker color when saved.
This problem is bad because I'm making a transition system, and whenever I copy the application_surface, this issue is very visible on the screen.

I showed the problem reproduction here:
I also sent a simple project.

I've tested it on Windows and HTML5, but I think it should affect all platforms.

Thanks for listening. Have a nice day!
 

FoxyOfJungle

Kazan Games
Okay, I partially solved this issue myself by writing this shader and replace the surface_copy() to a custom one:

GML:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 _color = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);
    if (_color.a < 1.0) {
        _color.a = 1.0;
    }
    gl_FragColor = _color;
}
Any pixel with opacity less than 1, it sets the pixel opacity to 1.

 
Last edited:
Top