Code
Copy to clipboard
/** 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
Copy to clipboard
// 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!