draw_blend_mode_ext
como funsiona?
Quizá una está pequeña pregunta necesite un tutorial completo para explicarse :-X. Es raro, nunca había visto que alguien preguntará esto y según tengo entendido pocos entienden como funcionan los blending modes.
Bueno los blending modes son básicamente multiplicaciones de colores. El mismo manual de gm te lo dice, solo que se vuelve algo confuso por que usa la palabra factor
Citardraw_set_blend_mode_ext(src,dest) Indica el modo de mezcla que se debe usar para la fuente y el destino. El color resultante se calcula aplicando a cada color (fuente y destino) un factor diferente.
Bueno, primero pondré la tabla con los factores que se pueden usar con esa función.
Citar
bm_zero: El factor de mezcla es (0, 0, 0, 0).
bm_one: El factor de mezcla es (1, 1, 1, 1).
bm_src_color: El factor de mezcla es (Rf, Gf, Bf, Af).
bm_inv_src_color: El factor de mezcla es (1–Rf, 1–Gf, 1–Bf, 1–Af).
bm_src_alpha: El factor de mezcla es (Af, Af, Af, Af).
bm_inv_src_alpha: El factor de mezcla es (1–Af, 1–Af, 1–Af, 1–Af).
bm_dest_alpha: El factor de mezcla es (Ad, Ad, Ad, Ad).
bm_inv_dest_alpha: El factor de mezcla es (1–Ad, 1–Ad, 1–Ad, 1–Ad).
bm_dest_color: El factor de mezcla es (Rd, Gd, Bd, Ad).
bm_inv_dest_color: El factor de mezcla es (1–Rd, 1–Gd, 1–Bd, 1–Ad).
bm_src_alpha_sat: El factor de mezcla es (f, f, f, 1); f = min(Af, 1–Ad).
Bien partamos de que los colores en 32 bits están siempre formados por 4 canales y cada uno va de 0 a 1 (en realidad de 0 a 255 pero es mucho más cómodo manejarlos de esté modo) el primero de rojo, después sigue verde, luego azul y por ultimo el canal alpha (r.g.b.a), donde en cada uno el 0 indica que no se usará ese color y el 1 indica que se usará el tono más alto de ese color (en el caso del alpha se sigue la misma lógica aunque puede ser algo diferente ya que esté no es un color).
Veamos un ejemplo, el manual de gm nos dice:
CitarPor ejemplo, el modo de mezcla normal pone la fuente a bm_src_alpha y el destino a bm_inv_src_alpha
La fuente es lo que sea que vayamos a dibujar (un sprite, poligono, texto, etc) y el destino es el fondo en el que vamos a posicionar lo que dibujaremos, es decir, lo que estaba dibujado antes.
Bueno tenemos que los valores de bm_src_alpha son (Af, Af, Af, Af) lo que nos dice que todos los canales de la fuente son multiplicados por el alpha de la fuente.
Tambien tenemos bm_inv_src_alpha (1-Af, 1-Af, 1-Af, 1-Af) que nos dice que todos los canales del destino serán multiplicados por el alpha inverso de la fuente.
Una vez multiplicados se suman los canales de la fuente y el destino.
Entonces el nuevo color usando draw_set_blend_mode_ext(bm_source_alpha, bm_inv_source_alpha)
nuevo rojo = (Rf * Af) + (Rd * (1-Af) )
nuevo verde = (Gf * Af) + (Gd * (1-Af) )
nuevo azul = (Bf * Af) + (Bd * (1-Af) )
nuevo alpha = (Af * Af) + (Ad * (1-Af) )
Y gráficamente lo puedes ver así.
(http://www.comunidadgm.org/index.php?action=dlattach;topic=18712.0;attach=12145)
Hay algo raro con esto y difícil de notar pero usando valores de alpha como 0.5 en tu fuete al ponerlo en el destino su nuevo alpha va a ser 0.25 ya que (0.5*0.5=0.25) y si haces eso en una superficie varias veces el alpha irá disminuyendo hasta ser casi cero.
Creo que el bm_add es draw_set_blend_mode_ext(bm_one, bm_one), de ese modo los colores simplemente son sumados ya que al multiplicarse por uno quedan iguales...
Hay un tutorial genial en la gmc que no pude encontrar, es algo parecido a como lo explique pero más bastante más extendido. Si lo veo lo pongo aquí, sería bueno traducirlo.
Por cierto quizá tu no necesites tanta explicación pero lo dejo así para otros usuarios.
:) o... gracias.. ahora entiendo un poco mejor!!! he visto en el foro yanky sobre el temas pero mas que explicar solo demostraban las combinaciones que se podian hacer.
Te pido un poco mas de ayuda.
Quiero hacer trasparente un color espesifico en una imagen (por ejemplo el ROJO de la imagen adjunta)
¿Como lo hago?
MMm. Pues no es algo realmente sencillo ni eficiente en gm. Con los shaders sería increíblemente fácil...
Bueno quizá te sirva esté script sprite_replace_color (http://www.gmlscripts.com/script/sprite_replace_color).
Aquí te lo paso con una pequeñísima modificación con la que puedes añadir alpha al nuevo color.
[gml]
/*
** Usage:
** sprite_replace_color(sprite,oldcolor,newcolor, newalpha)
**
** Arguments:
** sprite sprite to change
** oldcolor color that will be replaced
** newcolor color used as replacement
** newalpha alpha used as replacement
**
** Returns:
** (-1) on error
**
** Notes:
** This script replaces one color in a sprite with another.
** No new sprites are created, the given sprite is changed.
**
** GMLscripts.com
*/
{
var sprite, oldc, newc, newa;
sprite = argument0;
oldc = argument1;
newc = argument2;
newa = argument3;
var w, h, n, i, xo, yo, surf, tempsprite, newsprite, alphasprite;
w = sprite_get_width(sprite);
h = sprite_get_height(sprite);
n = sprite_get_number(sprite);
xo = sprite_get_xoffset(sprite);
yo = sprite_get_yoffset(sprite);
surf = surface_create(w,h+1);
surface_set_target(surf);
for(i=0; i<n; i+=1) {
draw_clear_alpha(c_black,1);
draw_set_blend_mode_ext(bm_inv_dest_color,bm_one);
draw_sprite(sprite,i,xo,yo);
draw_set_blend_mode(bm_normal);
draw_point_color(0,h,oldc);
tempsprite = sprite_create_from_surface(surf,0,0,w,h+1,true,false,xo,yo);
draw_clear_alpha(newc, newa);
draw_sprite(tempsprite,0,xo,yo);
sprite_delete(tempsprite);
if (i == 0) {
newsprite = sprite_create_from_surface(surf,0,0,w,h,false,false,xo,yo);
if (newsprite < 0) return -1;
}else{
sprite_add_from_surface(newsprite,surf,0,0,w,h,false,false);
}
draw_clear_alpha(c_white,1);
draw_set_blend_mode_ext(bm_zero,bm_src_alpha);
draw_sprite(sprite,i,xo,yo);
if (i == 0) {
alphasprite = sprite_create_from_surface(surf,0,0,w,h,false,false,xo,yo);
if (alphasprite < 0) {
sprite_delete(newsprite);
return -1;
}
}else{
sprite_add_from_surface(alphasprite,surf,0,0,w,h,false,false);
}
draw_set_blend_mode(bm_normal);
}
surface_reset_target();
sprite_assign(sprite,newsprite);
sprite_set_alpha_from_sprite(sprite,alphasprite);
sprite_delete(newsprite);
sprite_delete(alphasprite);
surface_free(surf);
}
[/gml]
Entonces para borrar el rojo de la imagen sería así. sprite_replace_color(spr, c_red, c_black, 0);
Esta bueno.. :D pero no lo queria creando un sprite :'(. solo queria usar el codigo draw_surface al final del proceso. por eso queria saber si con blend mode se podia eliminar un color.
De todas formas muchisimas gracias!! :-[
mmmm pues de modo sencillo sin crear un sprite creo que no se puede. "Creo" que solo es posible de manera simple transformar a negro o a blanco el color deseado, no a transparente...