• Miércoles 20 de Noviembre de 2024, 10:36

Autor Tema:  Como hacer un alpha blending?  (Leído 1253 veces)

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
Como hacer un alpha blending?
« en: Jueves 3 de Septiembre de 2009, 14:59 »
0
Buenas:

estoy dibujando unos sprites en pantalla.
Para ello tengo un buffer con el fondo (24 bits, canales r,g,b entrelazados) y un buffer con el sprite (24 bits tambien entrelazado), luego tengo otro buffer igual de grande con el canal alpha del sprite, un blur sobre lo que seria su mascara para que los bordes sean suaves.

Bien, estoy teniendo problemas con el blending.

en teoria (corregidme si me equivoco)

la formula seria

r= ( rojo de overlay & rojo de Mascara)      | (rojo de fondo & (255-rojo de mascara));
g= ( verde de overlay & verde de Mascara) | (verde de fondo & (255-verde de mascara));
b= ( azul de overlay & azul de Mascara)      | (azul de fondo & (255-azul de mascara));

es asi? por que haciendolo asi me esta dando fallos en el gradiente. Y salen extrañas rayas.

overlay : verde completo liso con una banda blanca
mascara: Es un gradiente de blanco a negro de izquierda superior a derecha inferior
fondo: el visible, la mayor parte en rojo.


Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Como hacer un alpha blending?
« Respuesta #1 en: Sábado 5 de Septiembre de 2009, 22:08 »
0
Tal vez el problema sea que estás tratando de usar sólo operadores de bits.

Si "a" es un pixel del overlay [0..255], "b" uno del fondo [0..255] y "m" es la máscara [0..255], "c" será el resultado:

c = a + (m*(b-a)/255)

o bien (si es tolerable un poco de error en el cálculo):

c = (a<<8  +  m*(b-a)) >> 8

Nota: En procesadores Intel es mejor usar el primer caso por que los desplazamientos los hace mucho más lento en comparación a procesadores AMD.
Es posible optimizar las cosas un poco usando un arreglo[511] precalculado en lugar de multiplicar y dividir todo el tiempo, quedaría asi:
Código: C++
  1.  
  2. c = a + arreglo[255+b-a];
  3.  
  4.  
o bien usando punteros
Código: C++
  1.  
  2. // Asumimos que nunca se accederá a un valor menor que -255 ni mayor que 255
  3. int* arreglo2 = &(arreglo[255]);
  4. ...
  5. c = a + arreglo2[b-a];
  6.  
  7.  

Puede que la primera forma sea más rápida (siempre y cuando el arreglo sea estático) por que los compiladores suelen evitar optimizar código donde están involucrados punteros.

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
Re: Como hacer un alpha blending?
« Respuesta #2 en: Martes 8 de Septiembre de 2009, 11:50 »
0
buenas:

gracias por la respuesta, pero no se si no lo sabia implementar, pero no me salia bien con tu formula.
Sin embargo, encontré el problema con la mia  :wacko:

simplemente, no estaba usando unsigned char y encima lo almacenaba mal

Código: C++
  1.  
  2.  
  3. unsigned int r,g,b;
  4.             unsigned char Or=img->Data[ImgOffset];
  5.             unsigned char Og=img->Data[ImgOffset+1];
  6.             unsigned char Ob=img->Data[ImgOffset+2];
  7.  
  8.             unsigned char Mr=Mask->Data[ImgOffset];
  9.             unsigned char Mg=Mask->Data[ImgOffset+1];
  10.             unsigned char Mb=Mask->Data[ImgOffset+2];
  11.  
  12.             unsigned char Br=this->Data[CanvasOffset];
  13.             unsigned char Bg=this->Data[CanvasOffset+1];
  14.             unsigned char Bb=this->Data[CanvasOffset+2];
  15.  
  16.             r=Br*(255-Mr)+(Or*Mr);
  17.             g=Bg*(255-Mg)+(Og*Mg);
  18.             b=Bb*(255-Mb)+(Ob*Mb);
  19.             r>>=8;
  20.             g>>=8;
  21.             b>>=8;
  22.  
  23.  

esta es la solucion