(Irrlicht) makeColorKeyTexture for a range of color

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

(Irrlicht) makeColorKeyTexture for a range of color

Post by Spintz »

Add to IVideoDriver.h

Code: Select all

virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor minColor, video::SColor maxColor ) = 0;
Add to CNullDriver.h

Code: Select all

virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor minColor, video::SColor maxColor );
Add to CNullDriver.cpp

Code: Select all

void CNullDriver::makeColorKeyTexture( video::ITexture* texture, video::SColor minColor, video::SColor maxColor )
{
	if (!texture)
		return;

	if (texture->getColorFormat() != ECF_A1R5G5B5 &&
		texture->getColorFormat() != ECF_A8R8G8B8 )
	{
		os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
		return;
	}

	if (texture->getColorFormat() == ECF_A1R5G5B5)
	{
		s16 *p = (s16*)texture->lock();

		if (!p)
		{
			os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
			return;
		}

		core::dimension2d<s32> dim = texture->getSize();
		s32 pitch = texture->getPitch() / 2;

		for (s32 x=0; x<pitch; ++x)
		{
			for (s32 y=0; y<dim.Height; ++y)
			{
				video::SColor texColor = A1R5G5B5toA8R8G8B8( p[y*pitch+x] );
				if( texColor.getAlpha() <= maxColor.getAlpha() &&
					texColor.getAlpha() >= minColor.getAlpha() &&
					texColor.getBlue() <= maxColor.getBlue() &&
					texColor.getBlue() >= minColor.getBlue() &&
					texColor.getGreen() <= maxColor.getGreen() &&
					texColor.getGreen() >= minColor.getGreen() &&
					texColor.getRed() <= maxColor.getRed() &&
					texColor.getRed() >= minColor.getRed() )
				{
					texColor.setAlpha( 0 );
					p[y*pitch+x] = texColor.toA1R5G5B5();
				}
			}
		}

		texture->unlock();
	}
	else
	{
		s32 *p = (s32*)texture->lock();

		if (!p)
		{
			os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
			return;
		}

		core::dimension2d<s32> dim = texture->getSize();
		s32 pitch = texture->getPitch() / 4;

		for (s32 x=0; x<pitch; ++x)
		{
			for (s32 y=0; y<dim.Height; ++y)
			{
				video::SColor texColor = p[y*pitch+x];
				if( texColor.getAlpha() <= maxColor.getAlpha() &&
					texColor.getAlpha() >= minColor.getAlpha() &&
					texColor.getBlue() <= maxColor.getBlue() &&
					texColor.getBlue() >= minColor.getBlue() &&
					texColor.getGreen() <= maxColor.getGreen() &&
					texColor.getGreen() >= minColor.getGreen() &&
					texColor.getRed() <= maxColor.getRed() &&
					texColor.getRed() >= minColor.getRed() )
				{
					texColor.setAlpha( 0 );
					p[y*pitch+x] = texColor.toA8R8G8B8();
				}
			}
		}

		texture->unlock();
	}
}
I needed this, because I had to convert a black & white based mask of earth land masses, where the land leaned towards white and the water leaned towards black, so I would only apply bump mapping to the land masses, not the oceans and seas. I called it like this -

Code: Select all

video::ITexture* landMask = VideoDriver->getTexture( "data/planets/earth/earthmask1k_2.jpg" );
VideoDriver->makeColorKeyTexture( landMask, video::SColor( 0, 0, 0, 0 ), video::SColor( 255, 127, 127, 127 ) );
landMask->regenerateMipMapLevels();
Also, notice the part where i regenerateMipMapLevels after changing the texture. You must do this, so that changed alphas are propogated to the mip map levels, otherwise only mip map level 0 would have the transparency changes.
Image
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Here's some screenshots to better see why I do it, and the original mask image for determining where land is or not -

Without Masked Bumpmapping ( Notice the bumps in the water ) -

Image

With Masked Bumpmapping ( Notice no bumps in the water ) -

Image

And here's the original mask

Image
Image
Post Reply