Tutorial 08 - Color key
Fecha Miércoles, 05 septiembre a las 19:27:13
Tema DirectX/Opengl


En este ejemplo vamos a ver cómo hacer transparente un determinado color de una imagen, lo que se conoce como "color key". Esto nos será útil para poder desarrollar Juegos 2-D.



Vamos a realizar unos cambios en nuestra función LoadTexture() de tal forma que añadimos un canal más (canal alpha) a la imagen RGB.

Modificaremos LoadTexture() para convertir la imagen en una de 32 bits para añadirle el canal alpha para la transparencia. No serviremos de las funciones que nos ofrece freeimage para definir si el píxel es opaco o transparente.


///////////////////////////////////////////////////////////////////////////////
///     LoadTexture: Crea una textura a partir de un fichero.
///
///     @param  char *fileName: Nombre del fichero de la textura.
///     @param  Texture &texture: Estructura a la que se copiará la información
///                 sobre la textura.
///     @param  ulColorRGBA colorKey: Color que haremos transparente.
///
///     @return  int:   
///                     - -1  : error.
///                     - otro: correcto.
///////////////////////////////////////////////////////////////////////////////
int OpenGLVideoDriver::LoadTexture( char *fileName, Texture &texture
// ********************************* NEW **************************************
                                    , ulColorRGBA colorKey
// ****************************************************************************
                                    )
{
    int idTexture= -1;
    char msgError[512];
    FREE_IMAGE_FORMAT imageFormat= FIF_UNKNOWN;
    FIBITMAP *pImage= NULL;
    FIBITMAP *pImageCopy;
// ********************************* NEW **************************************
    unsigned int width, height, x, y;
    RGBQUAD rgbaColor;
// ****************************************************************************

    // Comprobamos el formato del fichero.
    imageFormat= FreeImage_GetFileType(fileName,0);
    if (imageFormat == FIF_UNKNOWN)
        imageFormat= FreeImage_GetFIFFromFilename(fileName);

    // Si es un formato soportado por la librera lo cargamos
    if ( (imageFormat != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(imageFormat) )
    {
        // Cargamos el fichero
        pImage= FreeImage_Load(imageFormat,fileName,0);
        if (pImage)
        {
// ********************************* NEW **************************************
            // Si se especifica un color transparente
            if ( colorKey.rgba != 0xffffffff )
            {
                // Convertimos la imagen a 32 bis para añadirle el canal alpha
                pImageCopy= FreeImage_ConvertTo32Bits( pImage );
                FreeImage_Unload(pImage);
                pImage= pImageCopy;

                width = FreeImage_GetWidth (pImage);
                height= FreeImage_GetHeight(pImage);

                for ( y=0; yfor ( x=0; x// Obtenemos el color del pixel
                        FreeImage_GetPixelColor( pImage, x, y, &rgbaColor );

                        if ( rgbaColor.rgbRed   == colorKey.r &&
                             rgbaColor.rgbGreen == colorKey.g &&
                             rgbaColor.rgbBlue  == colorKey.b )
                            rgbaColor.rgbReserved= 0x00; // Canal Alpha transparente
                        else
                            rgbaColor.rgbReserved= 0xff; // Canal Alpha opaco

                        // Fijamos el nuevo color del pixel
                        FreeImage_SetPixelColor( pImage, x, y, &rgbaColor );
                    }
                }
            }
// ****************************************************************************

            // Si la imagen es de menos de 16 bpp la convertimos
            if ( FreeImage_GetBPP(pImage) < 16 )
            {
                // Si no, convertimos la imagen a 24 bits
                pImageCopy= FreeImage_ConvertTo24Bits( pImage );
                FreeImage_Unload(pImage);
                pImage= pImageCopy;
            }

            // Creamos la textura
            idTexture= CreateTexture(pImage);
            FreeImage_Unload(pImage);
        }
    }

    if ( idTexture != -1)
    {
        strcpy( texture.fileName, fileName );
        m_TextureArray[ m_TextureRefs ]= idTexture;
        texture.idxTexture= m_TextureRefs++;
    }
    else
    {
        sprintf(msgError,"OpenGLVideoDriver::LoadTexture("%s"): error al cargar la textura.",fileName);
        System::ShowMessage("ERROR: ",msgError,true);
        texture.idxTexture= -1;
    }

    return texture.idxTexture;
}

En el método RenderObjects(), especificamos cómo se mezcla el color que vamos a renderizar, con lo que ya se ha renderizado. Con SetBlending() hacemos que para los valores 0x00 del canal alpha no pinte el pixel de nuestra textura y sí cuando sea 0xff.


if( m_bColorKey )
{
    m_pVideoDriver->EnableBlending( true );
    m_pVideoDriver->SetBlending( /*fuente*/eBlendSrcAlpha, /*destino*/eBlendOneMinusSrcAlpha );
}
else
{
    m_pVideoDriver->EnableBlending( false );
    m_pVideoDriver->SetBlending( eBlendDisable );
}

Para que os sirva de base, he añadido un método CheckMovement(), que comprueba si se encuentra pulsada una tecla de cursor, lo cual hace cambiar la posición de la imagen que cuando vaya a renderizarse lo hará en la posición especificada.

Debo indicar también, que en el método OnRender(), se ha cambiado los valores especificados en la proyección SetOrthoProjection() para que ahora el origen de coordenadas se encuentre en el centro de la ventana:


m_pVideoDriver->SetOrthoProjection ( -(float)m_WindowProps.width /2.0f, // left
                                      (float)m_WindowProps.width /2.0f, // right
                                     -(float)m_WindowProps.height/2.0f, // bottom
                                      (float)m_WindowProps.height/2.0f, // top
                                     -1.0f, 1.0f ); // zNear, zFar

Finalmente, podéis echar un ojo a: http://www.panelmonkey.org/category.php?id=1 para ver ejemplos de texturas que os pueden servir para hacer algún jueguecito o crearos vosotros las vuestras.

Podéis descargaros el ejemplo: tutorial-08.zip



Compartir en Facebook



Este artículo proviene de Programacion Grafica: Desarrollo 2D/3D con C++ y DirectX/OpenGL/GLUT/SDL - Windows/Linux
http://www.programaciongrafica.com

La dirección de esta noticia es:
http://www.programaciongrafica.com/modules.php?name=News&file=article&sid=9