• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GM8 Surface Issues

O

orSQUADstra

Guest
Before I start, let me point out that I'm using GameMaker 8.0 for this project (I have the reasons for it). So that means there are no shaders whatsoever.

So my issue is a pretty common issue I'd say. Have a surface, filled with a rectangle of 100% alpha. Then draw a sprite on top of it with a 50% opacity. That'll make the surface itself translucent on that position.

I've been struggling to find a fix for this but nothing. How can this be resolved?

Any help is appreciated!
 

matharoo

manualman
GameMaker Dev.
I fixed this issue in my project by using
Code:
draw_set_color_write_enable(1, 1, 1, 0)
before drawing the translucent sprite but not sure whether 8.0 has it.
 
O

orSQUADstra

Guest
I fixed this issue in my project by using
Code:
draw_set_color_write_enable(1, 1, 1, 0)
before drawing the translucent sprite but not sure whether 8.0 has it.
Sadly GM 8.0 doesn't have draw_set_color_write_enable :/
 

CMAllen

Member
Sadly GM 8.0 doesn't have draw_set_color_write_enable :/
GM8 is very limited in that regard. You *might* be able to get what you want with:
Code:
draw_set_blend_mode_ext(bm_one,bm_dest_alpha)
Just be sure to set the blend mode back to bm_normal afterward.
 
O

orSQUADstra

Guest
GM8 is very limited in that regard. You *might* be able to get what you want with:
Code:
draw_set_blend_mode_ext(bm_one,bm_dest_alpha)
Just be sure to set the blend mode back to bm_normal afterward.
Thanks, I'll give it a try when I get home
 
O

orSQUADstra

Guest
GM8 is very limited in that regard. You *might* be able to get what you want with:
Code:
draw_set_blend_mode_ext(bm_one,bm_dest_alpha)
Just be sure to set the blend mode back to bm_normal afterward.
It doesn't work, it just gives a white rectangle with 100% opacity instead of the 50% opacity sprite :/
 

sp202

Member
Assuming you want the sprite alpha to override the surface alpha, try
Code:
draw_set_blend_mode_ext(bm_one,bm_zero)
 
O

orSQUADstra

Guest
Assuming you want the sprite alpha to override the surface alpha, try
Code:
draw_set_blend_mode_ext(bm_one,bm_zero)
No, that's exactly what I don't want.

There's a gray surface. I draw a sprite on it with 0.5 alpha.
What I expect to see:


But instead, what I'm getting:


So how do I fix this?
 
O

orSQUADstra

Guest
show how you're drawing that sprite and the surface.
Code:
surface_set_target(surf)
draw_set_blend_mode(bm_normal)
draw_sprite_ext(sprTest,0,50,50,2,2,0,c_white,0.5)
surface_reset_target()

draw_surface(surf,x,y)
 
O

orSQUADstra

Guest
where are you drawing the rectangle?
Oh, I draw that in the create event. Forgot to include that as well
Code:
x = 0
y = 0
w = 200
h = 200
surf = surface_create(w,h)
surface_set_target(surf)
draw_set_color(c_dkgray)
draw_rectangle(0,0,w,h,false)
surface_reset_target()
 

Kyon

Member
Oh, I draw that in the create event. Forgot to include that as well
Code:
x = 0
y = 0
w = 200
h = 200
surf = surface_create(w,h)
surface_set_target(surf)
draw_set_color(c_dkgray)
draw_rectangle(0,0,w,h,false)
surface_reset_target()
don't draw that in the create event. Only create the surface there.

so in draw event:
Code:
surface_set_target(surf)
draw_set_blend_mode(bm_normal)
draw_rectangle(0,0,w,h,false)
draw_sprite_ext(sprTest,0,50,50,2,2,0,c_white,0.5)
surface_reset_target()

draw_surface(surf,x,y)
 

Kyon

Member
Wait even better, don't use draw_set_color,
just draw the rectangle with color:
Code:
draw_rectangle_color(0,0,w,h,c_gray,c_gray,c_gray,c_gray,0);
 
O

orSQUADstra

Guest
Wait even better, don't use draw_set_color,
just draw the rectangle with color:
Code:
draw_rectangle_color(0,0,w,h,c_gray,c_gray,c_gray,c_gray,0);
Yeah, but it's still the same stuff.

This will look a bit funny but I jus tset some randomness as a background to see how it goes. But yeah, here's the result:


This is the sprTest:
 

Kyon

Member
Strange, I just tested the code in my game and it doesn't show that. Did you remove your creation code?
Only this part is needed:
Code:
w = 200
h = 200
surf = surface_create(w,h)
And I notice you set a blend mode. Are you messing around with different blend modes in your draw event? Like bm_subtract?
If so, try putting
draw_set_blend_mode(bm_normal); right before when you draw the surface.
If not, remove it.
 
O

orSQUADstra

Guest
Strange, I just tested the code in my game and it doesn't show that. Did you remove your creation code?
Only this part is needed:
Code:
w = 200
h = 200
surf = surface_create(w,h)
And I notice you set a blend mode. Are you messing around with different blend modes in your draw event? Like bm_subtract?
If so, try putting
draw_set_blend_mode(bm_normal); right before when you draw the surface.
If not, remove it.
This is all I have in the game:
Create:
Code:
x = 0
y = 0
w = 200
h = 200
surf = surface_create(w,h)
And draw:
Code:
surface_set_target(surf)
    draw_rectangle_color(0,0,w,h,c_gray,c_gray,c_gray,c_gray,0);
    draw_sprite_ext(sprTest,0,50,50,2,2,0,c_white,0.5)
surface_reset_target()

draw_surface(surf,x,y)
The result is still exactly the same.


Also, what version of GameMaker did you test your code on? (Just as a note, like I also mentioned in the original post, I'm using GameMaker 8.0)
 

Kyon

Member
Oops sorry my bad, I got the same problem lol. Using GMS2 btw, but that doesn't matter.
So yeah, apparently this is how surfaces work? I never really used it like this though.
Hmmm, I'm trying some things but nothing really seems to work. Easyest ways to solve it would be to make two surfaces. One with the square or "background" and one with the objects on top of it.
 

sp202

Member
Why do you need to draw a transparent sprite onto a surface with blending? If we know the end result you want we could suggest alternate methods.
 
O

orSQUADstra

Guest
Why do you need to draw a transparent sprite onto a surface with blending? If we know the end result you want we could suggest alternate methods.
I already showed what end result I want.

There's a gray surface. I draw a sprite on it with 0.5 alpha.
What I expect to see:


But instead, what I'm getting:

So how do I fix this?
 

sp202

Member
I mean beyond that, what is the final outcome you want? If all you wanted was a transparent sprite in front of a rectangle you'd just draw the sprites.
 
O

orSQUADstra

Guest
I mean beyond that, what is the final outcome you want? If all you wanted was a transparent sprite in front of a rectangle you'd just draw the sprites.
In the end it would be a window with a file list, selection, and all kinds of stuff. Something that is different for everyone and can't do it as sprites.
 
O

orSQUADstra

Guest
I don't see the relation to the transparent sprite though.
The icons can appear as tranlucent. As well as function icons if they're not available for the desired file. Also doing visual animations by having two sprites with changing alpha values, for example a tickbox that fades from that state to the other.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I'm pretty sure you need the blend mode:

Code:
draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
So you'd need to do this:

Code:
surface_set_target(surf)
draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
draw_rectangle_color(0,0,w,h,c_gray,c_gray,c_gray,c_gray,0);
draw_sprite_ext(sprTest,0,50,50,2,2,0,c_white,0.5);
draw_set_blend_mode(bm_normal);
surface_reset_target();
draw_surface(surf,x,y);
Failing that, you could try simply premultiplying the alpha of all the sprites then draw them using the correct blend mode. This approach is covered here:

http://gmc.yoyogames.com/index.php?showtopic=474273

See the scripts by Martin Baert (and this method works beautifully in GM8 as I used it myself for a few things).
 
O

orSQUADstra

Guest
I'm pretty sure you need the blend mode:

Code:
draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
So you'd need to do this:

Code:
surface_set_target(surf)
draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
draw_rectangle_color(0,0,w,h,c_gray,c_gray,c_gray,c_gray,0);
draw_sprite_ext(sprTest,0,50,50,2,2,0,c_white,0.5);
draw_set_blend_mode(bm_normal);
surface_reset_target();
draw_surface(surf,x,y);
Failing that, you could try simply premultiplying the alpha of all the sprites then draw them using the correct blend mode. This approach is covered here:

http://gmc.yoyogames.com/index.php?showtopic=474273

See the scripts by Martin Baert (and this method works beautifully in GM8 as I used it myself for a few things).
The problem with that code is, even though it does act as intended alpha-wise, but not color-wise. Here, the sprite is being drawn with 0.1 alpha. The colors get very light of the sprite:



With 1 alpha, it draws correctly.


So it kind of seems like it's additive.

If I set the background black, then nothing really happens. Here's the sprite is displayed with 0.1 alpha, yet looks 100% like if it was drawn with 1 alpha.
 
O

orSQUADstra

Guest
Also in that thread there is an example .gm7, but it includes functions (sprite_add_alpha) which GM8 doesn't have
 

sp202

Member
The only solution seems to be to premultiply, but then you lose the colour and you end up with pretty much a transparent black sprite.
 
O

orSQUADstra

Guest
Well... RIP this idea then.

Any idea what else I could use? I need something that I can draw onto, that cuts off anything that goes off it, and can be drawn with one command, resized and alpha changed if necessary. (Pretty much everything that a surface offers). Only if there were shaders for GM8.. I mean, I know this problem could be solved by using shaders in either GM 1.4 or GM 2, but then there is no execute_string(), object_add(), object_event_add() and so on that this project also needs...
 

sp202

Member
@Nocturne Am I doing something wrong then?
Code:
surface_set_target(surf)
draw_sprite(sprBackground,0,0,0)
draw_set_blend_mode_ext(bm_src_alpha_sat,bm_zero);
draw_sprite(sprTransparent,0,mouse_x,mouse_y)
surface_reset_target()

draw_set_blend_mode_ext(bm_one,bm_inv_src_alpha)
draw_surface(surf,0,0)
draw_set_blend_mode(bm_normal)
 

sp202

Member
Oh, you had only linked to the topic earlier, so I was just taking xot's advice.

EDIT: Just realized you had pointed out Maarten Baert's scripts in text, my bad. But yes, that does work just fine.

@orSQUADstra
Code:
alpha=0.5
surface_set_target(surf)
draw_sprite(sprBackground,0,0,0)
draw_set_blend_mode_ext(bm_one,bm_inv_src_alpha);
draw_sprite_ext(sprTransparent,0,x,y,1,1,0,make_color_rgb(255*alpha,255*alpha,255*alpha),alpha)
surface_reset_target()
      
draw_set_blend_mode_ext(bm_one,bm_inv_src_alpha)
draw_surface(surf,0,0)
draw_set_blend_mode(bm_normal)
 
Last edited:
yes to: blendmode(1,1-As)
and yes to: premulitply alpha
you need both to make it work.

Premultiplying alpha:
Option 1: for sprites only

use a premultiplier plugin for Photoshop or gimp. I got one for gimp here:
http://gaming-reverends.com/main/index.php/en/mnp-devtools-en/mnp-premultiplyalpha-en

Option 2: for shapes
simply multiply the alpha into the colour values. Here's two scripts that might help:
Code:
/// premultiply_color(color, alpha);
/*
Description:
    This script takes a color and returns it whith premultiplied alpha.
  
Arguments:
    argument0: color, $BBGGRR
               The original color
    argument1: alpha, real 0 - 1
               The alpha value to multiply with RGB
  
Return:
    $BBGGRR, premultiplied color
  
Examples:
    surface_set_target(srf_1);
    draw_clear_alpha(c_black, 1);
    draw_set_blend_mode_ext(bm_one, bm_inv_src_alpha);
    draw_set_alpha(0.5);
    draw_set_colour(premultiply_color(c_red, 0.5));
    draw_rectangle(10, 10, 100, 100, false);
    draw_set_blend_mode(bm_normal);
*/

var col = argument0;
var alf = argument1;

return make_colour_rgb(colour_get_red(col) * alf, colour_get_green(col) * alf, colour_get_blue(col) * alf);
Code:
/// alpha_to_gray(alpha);
/*
Description:
    This script returns the gray-scale-color of an alpha value.
  
Arguments:
    argument0: alpha, real 0 - 1
               The alpha value to be converted into a gray-scale color
  
Return:
    $BBGGRR
    The gray-scale color of the alpha value.
  
Examples:
    col = alpha_to_gray(0.5);
  
    This will store $7F7F7F in the variable 'col'.
*/

var intensity = argument0 * 255;

return make_colour_rgb(intensity, intensity, intensity);
Option 3: only for GM:S 1.2 and later:
You're going to use shaders anyways, so why not just take this premultiplication code here and insert that into your main shader:
Code:
/*-----------------------------------------------------------------------------
Premutliply Alpha Shader: Multiplies each fragments alpha into it's color
Fragment Shader: Premultiply Alpha
-----------------------------------------------------------------------------*/

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
   vec4 col = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord);
   gl_FragColor = vec4(col.rgb * col.a, col.a);
}
 
Top