Then the answer is: When you draw on a surface the GPU blends the source pixel colour RGB & A with the destination colour RGB & A.
The destination surfaces colour was set to RGBA(0,0,0,1) by draw_clear(c_black) and the source circles colour is RGBA(1,1,1,0.5).
You draw in normal blend mode which is (bm_src_alpha, bm_inv_src_alpha),
where src_alpha is (As,As,As,As) and inv_src_alpha is (1-As,1-As,1-As,1-As).
So the final colour on the surface after drawing will be (component-wise calculated):
source(Rs,Gs,Bs,As) * bm_src_alpha +destination (Rd,Gd,Bd,Ad) * bm_inv_src_alpha
= (1, 1, 1, 0.5) * (0.5, 0.5, 0.5, 0.5) + (0, 0, 0, 1) * (1-0.5 , 1-.0.5, 1-0.5, 1-0.5)
= (0.5, 0.5, 0.5, 0.25) + (0, 0, 0, 0.5)
= (0.5,0.5,0.5,0.75)
So the result is a medium grey with some transparency:
Canvas:
surface after draw_clear(c_black):
circle to draw (white, 0.5 alpha):
surface after drawing (gray, alpha 0.75):
There's a great Tech blog about this by Mark Alexander:
https://www.yoyogames.com/blog/56/explaining-blend-modes-part-1
https://www.yoyogames.com/blog/57/explaining-blend-modes-part-2
And a really old forums post of mine:
http://gmc.yoyogames.com/index.php?showtopic=636009&hl=
A solution to this is changing the blend mode and pre-multiply the alpha into the colour.
Setting the blend mode:
before "if surface_exists(surface)" set the blend mode like this:
Code:
gpu_set_blendmode_ext(bm_one, bm_inv_src_alpha);
// or in GM:S 1: draw_set_blendmode_ext();
and before "mouse_xprevious = mouse_x;" set the blend mode back like this:
Code:
gpu_set_blendmode(bm_normal);
// or in GM:S 1: draw_set_blendmode();
pre-multiply the alpha:
somewhere in create event or where the colour changes:
Code:
var alpha = 0.5;
var colour = c_white; // or any colour in BGR format
var red = color_get_red(col);
var green = color_get_green(col);
var blue = color_get_blue(col);
colour_premultiplied = make_colour_rgb(red * alpha, green * alpha, blue * alpha);
inside your draw event where you draw the circle:
Code:
draw_set_alpha(alpha);
draw_circle_colour(mouse_x+dx, mouse_y+dy, brush_size, colour_premulitplied, colour_premulitplied, false);
draw_set_alpha(1);
Btw: you can move surface_set_target(surface) and surface_reset_target() outside the for-loop. This function costs quite some performance.
Edit 1: Hope I didn't mess up the code. But I don't know if there's another way in GMS2. Haven't looked into the new sepalpha blend mode functions yet.
Edit 2: fixed broken make_colour_rgb line.
Edit 3: In case you wonder why this doesn't happen when drawing to the application surface: The application surface cant change alpha.