Alpha blending en XNA (II de IV)

Recordemos la formula general usada para las transparecias:

(Source * SourceBlend) (blendFunction) (Destination * DestinationBlend)

 

En los dos ejemplos anteriores usamos como BlendFunction la operación suma que suele ser la más común, pero se pueden usar otras, la lista completa es:

Add     result = (Source * SourceBlend) + (Destination * DestinationBlend)

Max     result = max( (Source * SourceBlend), (Destination * DestinationBlend)

Min     result = min( (Source * SourceBlend), (Destination * DestinationBlend)

ReverseSubtract     result = (Destination * DestinationBlend) – (Source * SourceBlend)

Subtract     result = (Source * SourceBlend) – (Destination * DestionationBlend)

Para los parámetros SourceBlend y DestionationBlend que como vimos anteriormente nos indica el nivel de aportación a la mezcla del Source (lo que queremos pintar con transparencia) y del Destination (lo que ya está se ha pintado en el framebuffer, el fondo), y los configuramos para que usaran un valor constante de alpha para toda la textura usando el BlendFactor ó que usaran el canal alpha de la textura, pero también existen muchos otros valores, aquí os dejo la lista completa también:

Zero
Each component of the color is multiplied by (0, 0, 0, 0).

One
Each component of the color is multiplied by (1, 1, 1, 1).

SourceColor
Each component of the color is multiplied by the source color. This can be represented as (Rs, Gs, Bs, As), where R, G, B, and A respectively stand for the red, green, blue, and alpha source values.

InverseSourceColor
Each component of the color is multiplied by the inverse of the source color. This can be represented as (1 − Rs, 1 − Gs, 1 − Bs, 1 − As) where R, G, B, and A respectively stand for the red, green, blue, and alpha destination values.

SourceAlpha
Each component of the color is multiplied by the alpha value of the source. This can be represented as (As, As, As, As), where As is the alpha source value.

InverseSourceAlpha
Each component of the color is multiplied by the inverse of the alpha value of the source. This can be represented as (1 − As, 1 − As, 1 − As, 1 − As), where As is the alpha destination value.

DestinationAlpha
Each component of the color is multiplied by the alpha value of the destination. This can be represented as (Ad, Ad, Ad, Ad), where Ad is the destination alpha value.

InverseDestinationAlpha
Each component of the color is multiplied by the inverse of the alpha value of the destination. This can be represented as (1 − Ad, 1 − Ad, 1 − Ad, 1 − Ad), where Ad is the alpha destination value.

DestinationColor
Each component color is multiplied by the destination color. This can be represented as (Rd, Gd, Bd, Ad), where R, G, B, and A respectively stand for red, green, blue, and alpha destination values.

InverseDestinationColor
Each component of the color is multiplied by the inverse of the destination color. This can be represented as (1 − Rd, 1 − Gd, 1 − Bd, 1 − Ad), where Rd, Gd, Bd, and Ad respectively stand for the red, green, blue, and alpha destination values.

SourceAlphaSaturation
Each component of the color is multiplied by either the alpha of the source color, or the inverse of the alpha of the source color, whichever is greater. This can be represented as (f, f, f, 1), where f = min(A, 1 − Ad).

BothInverseSourceAlpha
(Win32 only) Each component of the source color is multiplied by the inverse of the alpha of the source color, and each component of the destination color is multiplied by the alpha of the source color. This can be represented as (1 − As, 1 − As, 1 − As, 1 − As), with a destination blend factor of (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the SourceBlend render state.

BlendFactor
Each component of the color is multiplied by a constant set in BlendFactor.

InverseBlendFactor
Each component of the color is multiplied by the inverse of a constant set in BlendFactor. This blend mode is supported only if SupportsBlendFactor is true in the SourceBlendCapabilities or DestinationBlendCapabilities properties.

BothSourceAlpha
This mode is obsolete. The same effect can be achieved by setting the source and destination blend factors to SourceAlpha and InverseSourceAlpha in separate calls.

Ahora es cuando muchos os estaréis preguntando que para que tantos valores, pues como veis las posibles combinaciones son muchas y con todas ellas el resultado es algo diferente, que sean más o menos útiles ya es otra cosa XD.

Las combinaciones más usadas y conocidas son:

Alpha Blending     (source * Blend.SourceAlpha) + (destination * Blend.InvSourceAlpha)

Additive Blending     (source * Blend.One) + (destination * Blend.One)

Multiplicative Blending     (source * Blend.Zero) + (destination * Blend.SourceColor)

2X Multiplicative Blending     (source * Blend.DestinationColor) + (destination * Blend.SourceColor)

 

BlendModes

1. Alpha Blending, 2. Additive Blending, 3. Multiplicative Blending, 4. 2X Multiplicative Blending

También cabe destacar que existen diferentes formas de pensar en la transparencia esta que acabamos de ver podemos llamar la forma convencional en la mayoría de APIs.

Conventional Alpha Blending

Idea:

blend(source, destination) = (source.rgb * source.a) + (destination.rgb * (1 – source.a))

En XNA:

GraphicsDevice.RenderState.AlphaBlendEnable = true;

GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;

GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;

GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

Pero como podemos observar en esta situación los valores RGB y el alpha son independientes, de manera que sería posible tener un objeto totalmente transparente con valores de color en RGB, esto a un informático no le preocupa en exceso, pero no es un comportamiento muy real. Por ello existen otras formas de pensar en la transparencia como:

Premultiplied Alpha Blending

Idea:

blend(source, destination) = source.rgb + ( destination.rgb * (1 – source.a) )

En XNA:

GraphicsDevice.RenderState.AlphaBlendEnable = true;

GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;

GraphicsDevice.RenderState.SourceBlend = Blend.One;

GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

En este caso el alpha y el RGB están ligados y para que un objeto sea transparente debe tener el máximo de transparencia, y el color de RGB debe ser nulo (0,0,0). Si os fijáis la formula es la misma que la anterior solo que el source.rgb lo multiplicamos por 1, esto implica que si el objeto es translucido tendremos que realizar una conversión previa de las texturas para pasarlas a premultiplied format:

color.rgb *= color.a

Uno de los grandes motivos por el que se tiende a usar está técnica es porque se adapta mejor con DTX compression.

************************************************************************************************

Alpha Blending en XNA (I de IV)

Alpha Blending en XNA (II de IV)

Alpha Blending en XNA (III de IV)

Alpha Blending en XNA (IV de IV)

************************************************************************************************

Publicado por

jcanton

Javier is a Computer Science Engineer who has always had a passion for 3D graphics and software architecture. He learned C# almost at the same time as he learned to talk, and his first word was "base". He enjoys imparting talks about technology and has contributed in many important software and video game events. He has participated in multitude of software projects involving multitouch technologies, innovative user interfaces, augmented reality, and video games. Some of these projects were developed for companies such as Microsoft, Syderis, and nVidia. His professional achievements include being MVP for Windows DirectX and DirectX XNA for the last eight years, Xbox Ambassador, as well as Microsoft Student Partner and Microsoft Most Valuable Student during his years at college. Currently he works at Plainconcepts and he is the development team lead at WaveEngine project.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *