Commit c3cfdcfa authored by hybrid's avatar hybrid

Merged revisions 2006:2016 from 1.5 branch, makeColorKeyTexture changes.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2017 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 77216f12
......@@ -11,6 +11,10 @@ Changes in version 1.6
-------------------------------------
Changes in version 1.5.1 (??.?? 2009)
- Changed behaviour of PixelBlend16() / PixelBlend16_simd() so that they treat the 1 bit alpha of the source pixel as boolean, i.e. they draw either the source pixel, or the destination pixel, rather than "blending". (Issue revealed by the fix to IVideoDriver::makeColorKeyTexture()).
- IVideoDriver::makeColorKeyTexture() bug fixed so that only alphas, not whole texel colors, are zeroed. An optional parameter allows using the old (buggy) behaviour for backwards compatibility.
- MD2 mesh loader: Now uses much less memory, reduced number of allocations when loading meshes.
-----------------------------------
......
......@@ -271,30 +271,41 @@ namespace video
//! Remove all hardware buffers
virtual void removeAllHardwareBuffers() = 0;
//! Creates a 1bit alpha channel of the texture based of an color key.
/** This makes the texture transparent at the regions where
//! Sets a boolean alpha channel on the texture based on a color key.
/** This makes the texture fully transparent at the texels where
this color key can be found when using for example draw2DImage
with useAlphachannel==true.
with useAlphachannel==true. The alpha of other texels is not modified.
\param texture Texture whose alpha channel is modified.
\param color Color key color. Every pixel with this color will
become transparent as described above. Please note that the
\param color Color key color. Every texel with this color will
become fully transparent as described above. Please note that the
colors of a texture may be converted when loading it, so the
color values may not be exactly the same in the engine and for
example in picture edit programs. To avoid this problem, you
could use the makeColorKeyTexture method, which takes the
position of a pixel instead a color value. */
virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color) const = 0;
position of a pixel instead a color value.
\param \deprecated zeroTexels If set to true, then any texels that match
the color key will have their color, as well as their alpha, set to zero
(i.e. black). This behaviour matches the legacy (buggy) behaviour prior
to release 1.5 and is provided for backwards compatibility only.*/
virtual void makeColorKeyTexture(video::ITexture* texture,
video::SColor color,
bool zeroTexels = false) const = 0;
//! Creates a 1bit alpha channel of the texture based of an color key position.
/** This makes the texture transparent at the regions where
this color key can be found when using for example draw2DImage
with useAlphachannel==true.
//! Sets a boolean alpha channel on the texture based on the color at a position.
/** This makes the texture fully transparent at the texels where
the color key can be found when using for example draw2DImage
with useAlphachannel==true. The alpha of other texels is not modified.
\param texture Texture whose alpha channel is modified.
\param colorKeyPixelPos Position of a pixel with the color key
color. Every pixel with this color will become transparent as
described above. */
color. Every texel with this color will become fully transparent as
described above.
\param \deprecated zeroTexels If set to true, then any texels that match
the color key will have their color, as well as their alpha, set to zero
(i.e. black). This behaviour matches the legacy (buggy) behaviour prior
to release 1.5 and is provided for backwards compatibility only.*/
virtual void makeColorKeyTexture(video::ITexture* texture,
core::position2d<s32> colorKeyPixelPos) const = 0;
core::position2d<s32> colorKeyPixelPos,
bool zeroTexels = false) const = 0;
//! Creates a normal map from a height map texture.
/** If the target texture has 32 bit, the height value is
......
......@@ -2321,6 +2321,9 @@ bool CD3D9Driver::reset()
if(DepthBuffers[i]->Surface)
DepthBuffers[i]->Surface->Release();
}
// this does not require a restore in the reset method, it's updated
// automatically in the next render cycle.
removeAllHardwareBuffers();
DriverWasReset=true;
......
......@@ -853,8 +853,10 @@ const SLight& CNullDriver::getDynamicLight(u32 idx) const
}
//! Creates an 1bit alpha channel of the texture based of an color key.
void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor color) const
//! Creates a boolean alpha channel of the texture based of an color key.
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
video::SColor color,
bool zeroTexels) const
{
if (!texture)
return;
......@@ -876,19 +878,27 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co
return;
}
core::dimension2d<s32> dim = texture->getSize();
s32 pitch = texture->getPitch() / 2;
const core::dimension2d<s32> dim = texture->getSize();
const s32 pitch = texture->getPitch() / 2;
// color with alpha enabled (color opaque)
s16 ref = (0x1<<15) | (0x7fff & color.toA1R5G5B5());
// color with alpha disabled (i.e. fully transparent)
const s16 refZeroAlpha = (0x7fff & color.toA1R5G5B5());
for (s32 y=0; y<dim.Height; ++y)
const s32 pixels = pitch * dim.Height;
for (s32 pixel = 0; pixel < pixels; ++ pixel)
{
for (s32 x=0; x<pitch; ++x)
// If the colour matches the reference colour, ignoring alphas,
// set the alpha to zero.
if(((*p) & 0x7fff) == refZeroAlpha)
{
s16 c = (0x1<<15) | (0x7fff & p[y*pitch + x]);
p[y*pitch + x] = (c == ref) ? 0 : c;
if(zeroTexels)
(*p) = 0;
else
(*p) = refZeroAlpha;
}
++p;
}
texture->unlock();
......@@ -906,16 +916,23 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co
core::dimension2d<s32> dim = texture->getSize();
s32 pitch = texture->getPitch() / 4;
// color with alpha enabled (color opaque)
s32 ref = 0xff000000 | (0x00ffffff & color.color);
// color with alpha disabled (fully transparent)
const s32 refZeroAlpha = 0x00ffffff & color.color;
for (s32 y=0; y<dim.Height; ++y)
const s32 pixels = pitch * dim.Height;
for (s32 pixel = 0; pixel < pixels; ++ pixel)
{
for (s32 x=0; x<pitch; ++x)
// If the colour matches the reference colour, ignoring alphas,
// set the alpha to zero.
if(((*p) & 0x00ffffff) == refZeroAlpha)
{
s32 c = (0xff<<24) | (0x00ffffff & p[y*pitch + x]);
p[y*pitch + x] = (c == ref) ? 0 : c;
if(zeroTexels)
(*p) = 0;
else
(*p) = refZeroAlpha;
}
++p;
}
texture->unlock();
......@@ -924,9 +941,10 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor co
//! Creates an 1bit alpha channel of the texture based of an color key position.
//! Creates an boolean alpha channel of the texture based of an color key position.
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
core::position2d<s32> colorKeyPixelPos) const
core::position2d<s32> colorKeyPixelPos,
bool zeroTexels) const
{
if (!texture)
return;
......@@ -938,6 +956,8 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
return;
}
SColor colorKey;
if (texture->getColorFormat() == ECF_A1R5G5B5)
{
s16 *p = (s16*)texture->lock();
......@@ -948,21 +968,11 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
return;
}
core::dimension2d<s32> dim = texture->getSize();
s32 pitch = texture->getPitch() / 2;
s16 ref = (0x1<<15) | (0x7fff & p[colorKeyPixelPos.Y*dim.Width + colorKeyPixelPos.X]);
const s16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
for (s32 y=0; y<dim.Height; ++y)
{
for (s32 x=0; x<pitch; ++x)
{
s16 c = (0x1<<15) | (0x7fff & p[y*pitch + x]);
p[y*pitch + x] = (c == ref) ? 0 : c;
}
}
texture->unlock();
colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit);
}
else
{
......@@ -974,22 +984,12 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
return;
}
core::dimension2d<s32> dim = texture->getSize();
s32 pitch = texture->getPitch() / 4;
s32 ref = (0xff<<24) | (0x00ffffff & p[colorKeyPixelPos.Y*dim.Width + colorKeyPixelPos.X]);
for (s32 y=0; y<dim.Height; ++y)
{
for (s32 x=0; x<pitch; ++x)
{
s32 c = (0xff<<24) | (0x00ffffff & p[y*pitch + x]);
p[y*pitch + x] = (c == ref) ? 0 : c;
}
colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
}
texture->unlock();
}
makeColorKeyTexture(texture, colorKey, zeroTexels);
}
......
......@@ -274,10 +274,10 @@ namespace video
const c8* name);
//! Creates an 1bit alpha channel of the texture based of an color key.
virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color) const;
virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels) const;
//! Creates an 1bit alpha channel of the texture based of an color key position.
virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d<s32> colorKeyPixelPos) const;
virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d<s32> colorKeyPixelPos, bool zeroTexels) const;
//! Creates a normal map from a height map texture.
//! \param amplitude: Constant value by which the height information is multiplied.
......
......@@ -1404,12 +1404,6 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source
return;
}
if ( Lights.size () == 0 )
{
dest->Color[0] = Material.EmissiveColor;
return;
}
// eyespace
/*
core::matrix4 modelview = Transformation[ETS_WORLD].m * Transformation[ETS_VIEW].m;
......
......@@ -292,31 +292,31 @@ REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1)
// 1 - Bit Alpha Blending
inline u16 PixelBlend16 ( const u16 c2, const u16 c1 )
inline u16 PixelBlend16 ( const u16 destination, const u16 source )
{
u16 c = c1 & 0x8000;
c >>= 15;
c += 0x7fff;
c &= c2;
c |= c1;
return c;
if((source & 0x8000) == 0x8000)
return source; // The source is visible, so use it.
else
return destination; // The source is transparent, so use the destination.
}
// 1 - Bit Alpha Blending 16Bit SIMD
inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 )
inline u32 PixelBlend16_simd ( const u32 destination, const u32 source )
{
u32 c = c1 & 0x80008000;
switch(source & 0x80008000)
{
case 0x80008000: // Both source pixels are visible
return source;
c >>= 15;
c += 0x7fff7fff;
case 0x80000000: // Only the first source pixel is visible
return (source & 0xFFFF0000) | (destination & 0x0000FFFF);
c &= c2;
c |= c1;
case 0x00008000: // Only the second source pixel is visible.
return (destination & 0xFFFF0000) | (source & 0x0000FFFF);
return c;
default: // Neither source pixel is visible.
return destination;
}
}
......
#include "testUtils.h"
#include "irrlicht.h"
using namespace irr;
using namespace scene;
using namespace video;
/** Tests the Burning Video driver */
bool burningsVideo(void)
{
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO,
core::dimension2di(160,120), 32);
if (!device)
return false;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
smgr->addCubeSceneNode(10.f, 0, -1, core::vector3df(0.f, 0.f, 20.f));
smgr->addCameraSceneNode();
// Test that ambient lighting works when there are no other lights in the scene
smgr->setAmbientLight(video::SColorf(.7f, .1f, .1f, 1.f));
bool result = false;
device->run();
if (driver->beginScene(true, true, video::SColor(0, 80, 80, 80)))
{
smgr->drawAll();
driver->endScene();
result = takeScreenshotAndCompareAgainstReference(driver, "-ambient-lighting.png", 100);
}
device->drop();
return result;
}
......@@ -80,6 +80,8 @@ int main(int argumentCount, char * arguments[])
TEST(textureRenderStates)
};
static const unsigned int numberOfTests = sizeof tests / sizeof tests[0];
TEST(burningsVideo);
TEST(makeColorKeyTexture);
unsigned int testToRun = 0;
unsigned int fails = 0;
......
// Copyright (C) 2008 Colin MacDonald
// No rights reserved: this software is in the public domain.
#include "irrlicht.h"
#include "testUtils.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
/** Test the behaviour of makeColorKeyTexture() using both 16 bit (software)
and 32 bit (Burning) textures, with the new behaviour and the legacy
behaviour. */
static bool doTestWith(E_DRIVER_TYPE driverType,
bool zeroTexels)
{
IrrlichtDevice *device = createDevice( driverType,
dimension2d<s32>(160, 120), 32);
if (!device)
return false;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager * smgr = device->getSceneManager();
// Draw a cube background so that we can check that the keying is working.
ISceneNode * cube = smgr->addCubeSceneNode(50.f, 0, -1, vector3df(0, 0, 60));
cube->setMaterialTexture(0, driver->getTexture("../media/wall.bmp"));
cube->setMaterialFlag(video::EMF_LIGHTING, false);
ITexture * Texture = device->getVideoDriver()->getTexture("../media/portal2.bmp");
device->getVideoDriver()->makeColorKeyTexture(Texture,
position2d<s32>(64,64),
zeroTexels);
device->getVideoDriver()->makeColorKeyTexture(Texture,
position2d<s32>(64,64),
zeroTexels);
(void)smgr->addCameraSceneNode();
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->draw2DImage(Texture,
position2di(40, 40),
rect<s32>(0, 0, Texture->getSize().Width, Texture->getSize().Height),
0,
SColor(255,255,255,255),
true);
driver->endScene();
char screenshotName[256];
(void)sprintf(screenshotName, "-makeColorKeyTexture-%s.png",
zeroTexels? "old" : "new");
bool result = takeScreenshotAndCompareAgainstReference(driver, screenshotName);
device->drop();
return result;
}
bool makeColorKeyTexture(void)
{
bool result = doTestWith(EDT_SOFTWARE, false);
result &= doTestWith(EDT_BURNINGSVIDEO, false);
result &= doTestWith(EDT_SOFTWARE, true);
result &= doTestWith(EDT_BURNINGSVIDEO, true);
return result;
}
......@@ -38,6 +38,7 @@
<Add directory="..\lib\gcc" />
</Linker>
<Unit filename="b3dAnimation.cpp" />
<Unit filename="burningsVideo.cpp" />
<Unit filename="collisionResponseAnimator.cpp" />
<Unit filename="disambiguateTextures.cpp" />
<Unit filename="drawPixel.cpp" />
......@@ -47,6 +48,7 @@
<Unit filename="guiDisabledMenu.cpp" />
<Unit filename="line2dIntersectWith.cpp" />
<Unit filename="main.cpp" />
<Unit filename="makeColorKeyTexture.cpp" />
<Unit filename="md2Animation.cpp" />
<Unit filename="planeMatrix.cpp" />
<Unit filename="sceneCollisionManager.cpp" />
......
......@@ -173,6 +173,10 @@
RelativePath=".\b3dAnimation.cpp"
>
</File>
<File
RelativePath=".\burningsVideo.cpp"
>
</File>
<File
RelativePath=".\collisionResponseAnimator.cpp"
>
......@@ -209,6 +213,10 @@
RelativePath=".\main.cpp"
>
</File>
<File
RelativePath=".\makeColorKeyTexture.cpp"
>
</File>
<File
RelativePath=".\md2Animation.cpp"
>
......
......@@ -171,6 +171,10 @@
RelativePath=".\b3dAnimation.cpp"
>
</File>
<File
RelativePath=".\burningsVideo.cpp"
>
</File>
<File
RelativePath=".\collisionResponseAnimator.cpp"
>
......@@ -207,6 +211,10 @@
RelativePath=".\main.cpp"
>
</File>
<File
RelativePath=".\makeColorKeyTexture.cpp"
>
</File>
<File
RelativePath=".\md2Animation.cpp"
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment