Creating transparency based on a key colour in code         Utility function that generates a texture with transparency based on a certain colour value

Table of contents


/** Utility function that generates a texture with transparency based on a certain colour value 
     The generated texture will either have full opacity or full transparency values 
 @param filename 
     The name of the image file this texture will be based on, residing in resGroup 
 @param keyCol 
     The colour value which should cause transparency (alpha component is ignored) 
 @param resGroup 
     The resource group the base image file belongs and the generated texture will belong to 
 @param prefix 
     The generated texture will be accessible via the name prefix+filename 
 @param numMipmaps 
     Usually you leave that on default, but if you never intend to scale the texture, you can set it to 0
 @param threshold 
     If the difference between the pixel colour of the image and keyCol is less than this, it gets 
     transparent. It should be between 0 and 1. The default value is less than (1 / 256), which means 
     that for an 8 Bit channels input file, only the EXACT keyCol gets transparent. 
     Returns the name of the texture resource the generated texture can be addressed by (is prefix+filename) 
 Ogre::String loadChromaKeyedTexture(const Ogre::String& filename, 
         const Ogre::ColourValue& keyCol = Ogre::ColourValue::Black, 
         const Ogre::String& resGroup = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
         const Ogre::String& prefix = "ck_",
         int numMipmaps = Ogre::MIP_DEFAULT,
         float threshold = 0.003f) 
     using namespace Ogre; 
     using std::fabs; 
     Image srcImg; 
     srcImg.load (filename, resGroup); 
     uint width = srcImg.getWidth (), height = srcImg.getHeight ();
     // Since Ogre 1.6 Shoggoth, the OGRE_ALLOC_T memory macro must be used:
     uchar* pixelData = OGRE_ALLOC_T (uchar, PixelUtil::getMemorySize (width, height, 1, PF_A8R8G8B8), MEMCATEGORY_GENERAL);
     ulong pxDataIndex = 0, pxDataIndexStep = PixelUtil::getNumElemBytes (PF_A8R8G8B8); 
     for(uint y = 0; y < height; ++y) 
         for(uint x = 0; x < width; ++x) 
             ColourValue pixCol = srcImg.getColourAt (x, y, 0); 
             ColourValue diffCol = pixCol - keyCol; 
             pixCol.a = ( (fabs(diffCol.r)<threshold) && (fabs(diffCol.g)<threshold) && (fabs(diffCol.b)<threshold) ) 
                 ? 0 : 1; 
             Ogre::PixelUtil::packColour (pixCol, PF_A8R8G8B8, static_cast<void*> (pixelData + pxDataIndex) ); 
             pxDataIndex += pxDataIndexStep; 
     Image chromaKeyedImg;
     chromaKeyedImg.loadDynamicImage (pixelData, width, height, 1, PF_A8R8G8B8, true); 
     String resName = prefix + filename;
     // You could save the chroma keyed image at this point for caching:
     TextureManager::getSingleton ().loadImage( resName , resGroup, chromaKeyedImg, TEX_TYPE_2D, numMipmaps );
     return resName;


// Load an image; in this example we use cyan as colour key:
 Ogre::String texName = loadChromaKeyedTexture("chromaKeyed.bmp", Ogre::ColourValue(0,1,1) );

 // Create your material, e.g. like this:
 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("yourMat", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
 mat->getTechnique(0)->getPass(0)->setSceneBlending (Ogre::SBT_REPLACE);
 mat->getTechnique(0)->getPass(0)->setAlphaRejectSettings (Ogre::CMPF_GREATER_EQUAL, 128);
 mat->getTechnique(0)->getPass(0)->setCullingMode (Ogre::CULL_NONE);
 mat->getTechnique(0)->getPass(0)->setManualCullingMode (Ogre::MANUAL_CULL_NONE);

 // Instead of the original filename of the image, use the one returned by loadChromaKeyedTexture above:
 Ogre::TextureUnitState*  t = mat->getTechnique(0)->getPass(0)->createTextureUnitState(texName);

 yourEntity->setMaterialName ("yourMat");

Now your texture should have transparency!

Alias: Creating_transparency_based_on_a_key_colour_in_code