Creating transparency based on a key colour in code
From Ogre Wiki
/** Utility function that generates a texture with transparency based on a certain colour value
@remarks
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.
@return
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:
// chromaKeyedImg.save(resName);
TextureManager::getSingleton ().loadImage( resName , resGroup, chromaKeyedImg, TEX_TYPE_2D, numMipmaps );
return resName;
}
Usage
// 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);
t->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
yourEntity->setMaterialName ("yourMat");
Now your texture should have transparency!

