Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: romon_28 en Junio 12, 2013, 04:27:28 PM

Título: draw_blend_mode_ext
Publicado por: romon_28 en Junio 12, 2013, 04:27:28 PM
draw_blend_mode_ext
como funsiona?
Título: Re:draw_blend_mode_ext
Publicado por: brunoxzx en Junio 15, 2013, 01:24:52 AM
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.
Título: Re:draw_blend_mode_ext
Publicado por: romon_28 en Junio 17, 2013, 03:15:16 PM
 :) 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?
Título: Re:draw_blend_mode_ext
Publicado por: brunoxzx en Junio 18, 2013, 12:45:06 AM
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);
Título: Re:draw_blend_mode_ext
Publicado por: romon_28 en Junio 18, 2013, 06:05:36 PM
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!!  :-[
Título: Re:draw_blend_mode_ext
Publicado por: brunoxzx en Junio 18, 2013, 10:49:35 PM
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...