Página 1 de 1

[GRAF] [Tutorial] Blend Modes

Enviado: Qui Abr 28, 2016 4:51 pm
por Tutoriais & Aulas
Autor original: saim
Nome: Desmistificando os blend modes
Descrição: Esse tutorial é uma mera tradução do tutorial encontrado na gmlspcripts, elaborado por Xot. Obviamente, a imagem não está traduzida. Como foi muito útil pra mim, suponho que seja útil pros demais membros da comunidade. Antes de ler, sugiro ler meus tutoriais sobre surfaces e, principalmente, o de cores, pois fiz ambos apenas como preâmbulo pra esse aqui. Não é necessário ler, mas é recomendável.
Nível de dificuldade: mediano
Requerimentos: GM 7/8 - Pro. Acredito que em versões anteriores também se aplique.
Desenvolvimento: Vamos lá.


Sobre Modos de Mistura (Blend Modes)
Manual escreveu:Existem mais duas funções que não são úteis apenas para desenhar texturas. Normalmente, primitivas são mescladas ao fundo usando o valor de alpha. Na verdade, você pode indicar como isso deve ocorrer. Além do modo normal, é possível indicar que a nova cor deve ser somada à cor existente ou subtraída da cor existente. Isso pode ser usado pra criar, por exemplo, holofotes ou sombras. Também é possível, tipo, escolher o máximo entre  a nova cor e a cor existente. Isso pode evitar alguns efeitos de saturação que você consegue com adição. Note que tanto a subtração quanto o máximo não levam o valor de alpha totalmente em conta. (DirectX não permite isso.) Então é melhor você garantir que a área externa esteja preta. Existem duas funções. A primeira te dá apenas as quatro opções descritas acima. A segunda te dá muito mais possibilidades. Você deveria experimentar um pouco com as configurações. Se use usadas efetivamente, elas podem ser usadas pra criar, por exemplo, interessantes efeitos de explosão ou de halo.
NOTA: Blend modes (Modos de mistura) não têm efeito nas funções draw_clear ou draw_clear_alpha. Dizer que algus modes "não levam o valor de alpha totalmente em conta" parece um pouco enganador. A forma que alpha é levada em conta simplesmente pode não ser o que o usuário deseja ou espera.

Blending Padrão

Manual escreveu:draw_set_blend_mode(modo) Indica que modo de mistura será usado. Os seguintes valores são possíveis: bm_normal (0), bm_add (1), bm_subtract (3), and bm_max (2). Não se esqueça de resetar o mode para o normal depois do uso, porque de outra forma, os outros sprites e até os backgrounds serão desenhados no novo modo de mistura.
NOTA: As quatro constantes de modos de mistura devem ser usadas apenas nessa função.

Mistura Extendida

Manual escreveu:draw_set_blend_mode_ext(fonte, destino) Indica qual modo de mistura usar para a cor da fonte e do destino. A nova cor é um tanto vezes a cor da fonte e outro tanto vezes a cor do destino. Esses tantos são definidos com essa função. Para entender isso, a fonte e o destino têm um componente vermelho, verde, azul e alpha. Então a fonte é (Vmf, Vdf, Azf, Alf) e o destino é (Vmd, Vdd, Azd, Ald). Todos são considerados como variando de 0 a 1. Os fatores de mistura que você pode escolher para a fonte e o destino são:
  • 1. bm_zero:           o fator de mistura é (0, 0, 0, 0). 2. bm_one:            o fator de mistura é (1, 1, 1, 1). 3. bm_src_color:      o fator de mistura é (Vmf, Vdf, Azf, Alf). 4. bm_inv_src_color:  o fator de mistura é (1–Vmf, 1–Vdf, 1–Azf, 1–Alf). 5. bm_src_alpha:      o fator de mistura é (Alf, Alf, Alf, Alf). 6. bm_inv_src_alpha:  o fator de mistura é (1–Alf, 1–Alf, 1–Alf, 1–Alf). 7. bm_dest_alpha:     o fator de mistura é (Ald, Ald, Ald, Ald). 8. bm_inv_dest_alpha: o fator de mistura é (1–Ald, 1–Ald, 1–Ald, 1–Ald). 9. bm_dest_color:     o fator de mistura é (Vmd, Vdd, Azd, Ald).10. bm_inv_dest_color: o fator de mistura é (1–Vmd, 1–Vdd, 1–Azd, 1–Ald).11. bm_src_alpha_sat:  o fator de mistura é (f, f, f, 1); f = min(Alf, 1–Ald).
Por exemplo, o modo de mistura normal define a mistura da fonte para bm_src_alpha e a do destino para bm_inv_src_alpha. Não se esqueça de resetar o mode para o normal depois do uso, porque de outra forma, os outros sprites e até os backgrounds serão desenhados no novo modo de mistura.
NOTA: As onze constantes de modos de mistura devem ser usadas apenas nessa função. Saber esses valores é útil quando consertando códigos que não usa as constantes corretas pra uma função de mistura em particular.


Como os Modos de Mistura funcionam

"Extended blend modes" - Modos de mistura extendidos - são a fonte de mais mistério que quase qualquer coisa no arsenal do Game Maker. Na verdade, eles são completamente lógicos e bastante diretos. Assim que você entender como eles operam, você não terá problemas em predizer o que qualquer modo de mistura particular fará.

É tudo matemático. O uso do termo "factor" (fator) no arquivo de ajuda é a pista, mas não chega perto de ser suficientemente detalhado.

Cada modo de mistura extendido tem dois fatores, definidos pelos dois argumentos da função draw_set_blend_mode_ext. O primeiro fator é para os pixels sendo desenhados (a fonte - source) e o segundo é para o pixel existente (o destino - destination). O pixel da fonte pode vir de qualquer comando de desenho, tais como desenhar sprites ou primitivas. Os pixels do destino podem ser o buffer de fundo (a tela) ou uma surface definida.

Para as misturas, os canais de cor (VerMelho, VerDe e AZul) são considerados como variando desde 0.0 até 1.0, ao invés de desde 0 até 255.

Vamos começar com mistura normal, o modo de mistura default do Game Maker:

Código:

Código: Selecionar todos

draw_set_blend_mode_ext(bm_src_alpha, bm_inv_src_alpha);
Olhando na tabela acima:
bm_src_alpha: o fator de mistura é (Alf, Alf, Alf, Alf).
bm_inv_src_alpha: o fator de mistura é (1–Alf, 1–Alf, 1–Alf, 1–Alf).
A tabela diz que o fator de mistura de bm_src_alpha é (Alf, Alf, Alf, Alf). O que isso quer dizer? Que cada um daqueles quatro valores ("Alf") representa o fator pra cada canal de cor (VerMelho, VerDe, AZul, ALpha). O fator "Alf" significa o Alpha do pixel da Fonte. As duas primeiras letras (apenas uma, no manual) se referem ao canal de cor e a terceira (segunda, no manual) se refere aos pixels da fonte ou do destino. Por "fator" queremos dizer multiplicação; nós multiplicaremos cada canal de cor do pixel da fonte por esse fator.

Semelhantemente, faremos o mesmo tipo de operação para os pixels de destino, só que usando o fator bm_inv_src_alpha (1-Alf), no lugar. Quando um fator tem "inv" (inverso) no nome, quer dizer que ele subtrai o canal indicado de um (assim, claro vira escuro e escuro vira claro).

O resultado dessas duas operações são então adicionados para formar a imagem final.

Aqui está toda a operação de mistura normal expressa matematicamente:
Fonte Destino Resultado
Pixels Pixels Pixels
[Vmf]*[Alf]+ [Vmd]*[1-Alf]= novo vermelho
[Vdf]*[Alf]+ [Vdd]*[1-Alf]= novo verde
[Azf]*[Alf]+ [Azd]*[1-Alf]= novo azul
[Alf]*[Alf]+ [Ald]*[1-Alf]= novo alpha

...e visualmente:

Imagem

O que está acontecendo é que a alpha da sprite está sendo usada pra (1) apagar o fundo da srpite do Mario e (2) apagar a área na imagem existente onde o Mario vai aparecer. Quando essas imagens forem combinadas, não haverá iteração entre as duas. Os elementos isolados vão encaixar perfeitamente. Obviamente, esse é um modo de mistura muito útil para jogos, por isso é o default. Aqui está um exemplo da matemática em ação. Digamos que o pixel que estamos desenhando é o da camisa vermelha do Mario (#F84070) sobre um fundo marrom (#C89858). Já que é uma parte do Mario, sabemos que o alpha é 100% pra esse pixel. O fundo também é totalmente opaco.
Fonte Destino Resultado
Pixels Pixels Pixels
[0xF8]*[1.00]+ [0xC8]*[1-1.00]= novo vermelho
[0x40]*[1.00]+ [0x98]*[1-1.00]= novo verde
[0x70]*[1.00]+ [0x58]*[1-1.00]= novo azul
[1.00]*[1.00]+ [1.00]*[1-1.00]= novo alpha
[0.97]*[1.00]+ [0.78]*[0.00]= 0.97
[0.25]*[1.00]+ [0.60]*[0.00]= 0.25
[0.44]*[1.00]+ [0.35]*[0.00]= 0.44
[1.00]*[1.00]+ [1.00]*[0.00]= 1.00
(#F84070)

O pixel resultante é da cor da camisa. Não é surpresa, eu sei, mas a matemática mostra o porquê. Agora, o que acontece quando o Mario não está totalmente opaco? Vamos tentar seu macacão azul (#408098) num alpha de 60% sobre o mesmo fundo.
[0.25]*[0.60]+ [0.78]*[0.40]= 0.46
[0.50]*[0.60]+ [0.60]*[0.40]= 0.54
[0.60]*[0.60]+ [0.35]*[0.40]= 0.50
[0.60]*[0.60]+ [1.00]*[0.40]= 0.76
(#75897F)

Conforme esperado, temos uma mistura das duas cores, um tipo de cinza-esverdeado. Note, em particular, o alpha resultante: 0.76. Normalmente, quando desenhando sobre o buffer de fundo, isso é ignorado. A janela do jogo é sempre 100% opaca, afinal. Entretanto, quando desenhando sobre uma surface, isso é extremamente importante. Se fôssemos repetir a última operação numa surface, os pixels resultantes, onde quer que desenhássemos o Mario transparente, iria de fato ficar parcialmente transparentes. Apesar de que esse efeito possa parecer uma estranha zica gráfica, é perfeitamente normal. Pode ser corrigido com operações de misitura adicionais. Faremos isso da próxima vez com algumas misturas "aditivas".

Nosso destino do desenho é uma surface, o resultado da operação anterior. Como notado, alguns pixels ficaram transparentes. Para restaurar a opacidade total, nós vamos desenhar sobre eles com preto. Como o mode de mistura que usaremos simplesmente soma duas cores juntas, e porque preto tem um valor de 0 para VerMelho, VerDe e AZul, isso não vai alterar de modo algum as cores do destino (n+0=n). O ALpha, entretanto, é igual a 1.0, totalmente opaco. Adicionar isso ao alpha existente garantirá que o resultado será, pelo menos, igual a 1.0. Valores acima de 1.0 (ou abaixo de 0.0) são cortados. O fator de mistura que nós usaremos é chamado bm_one (bm_um) que, como você deve ter adivinhado, é igual a 1.0 na equação de mistura. Nós o usaremos tanto para os pixels da fonte quanto para os do destino. O modo básico bm_add (bm_soma) trabalha de forma similar (mas não idêntica).
Fonte Destino Resultado
Pixels Pixels Pixels
[0.00]*[1.00]+ [0.46]*[1.00]= 0.46
[0.00]*[1.00]+ [0.54]*[1.00]= 0.54
[0.00]*[1.00]+ [0.50]*[1.00]= 0.50
[1.00]*[1.00]+ [0.76]*[1.00]= 1.00 (cortado de 1.76)
(#75897F)

A cor permanece a mesma, mas agora o pixel está totalmente opaco.

Até agora, todos os modos de mistura mostrados têm fatores que são os mesmo para todos os canais de cores. Não é necessariamente assim. Os fatores de mistura com a palavra "color" (cor) neles têm fatores diferentes pra cada canal. Um uso comum pra eles é em engines de iluminação, os chamados de passagem de luz/textura "multiplicativa". A idéia é desenhar o tom primeiro, então as texturas para os objetos iluminados com uma mistura multiplicativa. As cores na fonte serão multiplicadas pelas cores do destino. Áreas com tons brancos mostrarão a textura normalmente, áreas com tons coloridos vão pintar a textura, áreas com tom preto permanecerão pretas. Você pode ver o mesmo efeito quando usa a variável image_blend pra mudar a cor de uma instância. Os fatores de mistura que usaremos são bm_dest_color e bm_zero.
Fonte Destino Resultado
Pixels Pixels Pixels
[Vmf]*[Vmd]+ [Vmd][0.00]= novo vermelho
[Vdf]*[Vdd]+ [Vdd]*[0.00]= novo verde
[Azf]*[Azd]+ [Azd]*[0.00]= novo azul
[Alf]*[Ald]+ [Ald]*[0.00]= novo alpha
Se a cor da fonte é lilás (#C8A2C8) e os pixels do destino são de açafrão intenso(#FF9933):
[0.90]*[1.00]+ [1.00]*[0.00]= 0.90
[0.64]*[0.60]+ [0.60]*[0.00]= 0.38
[0.90]*[0.20]+ [0.20]*[0.00]= 0.18
[1.00]*[1.00]+ [1.00]*[0.00]= 1.00
(#E6602E)

...o resultado é uma cor acobreada, escurecida. Leitores observadores notarão que o modo de mistura (bm_dest_color, bm_zero) é exatamente o mesmo que (bm_zero, bm_src_color).

Agradecimentos: Ao Xot, obviamente, que postou o tutorial original e ao Lucas Lunar