Applied and fixed MiniBjorn's support for pre-mul textures by setting adjust-image=premultiply or
adjust-image=divide in material.xml But big question: can't we just modify the textures externally and use them, instead of doing this at runtime? git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7712 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -763,69 +763,77 @@ void IrrDriver::removeCameraSceneNode(scene::ICameraSceneNode *camera)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a texture from a file and returns the texture object.
|
||||
* \param filename File name of the texture to load.
|
||||
* \param is_premul If the alpha values needd to be multiplied for
|
||||
* all pixels.
|
||||
* \param is_prediv If the alpha value needs to be divided into
|
||||
* each pixel.
|
||||
*/
|
||||
video::ITexture *IrrDriver::getTexture(const std::string &filename)
|
||||
video::ITexture *IrrDriver::getTexture(const std::string &filename,
|
||||
bool is_premul,
|
||||
bool is_prediv)
|
||||
{
|
||||
#undef PREMULPNGS
|
||||
#ifndef PREMULPNGS
|
||||
video::ITexture* out = m_scene_manager->getVideoDriver()->getTexture(filename.c_str());
|
||||
#else
|
||||
video::IImage* img = m_scene_manager->getVideoDriver()->createImageFromFile(filename.c_str());
|
||||
// PNGs are non premul, but some are used for premul tasks, so convert
|
||||
// http://home.comcast.net/~tom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]
|
||||
if(StringUtils::hasSuffix(filename.c_str(), ".png")) // FIXME check param, not name
|
||||
video::ITexture* out;
|
||||
if(!is_premul && !is_prediv)
|
||||
out = m_scene_manager->getVideoDriver()->getTexture(filename.c_str());
|
||||
else
|
||||
{
|
||||
if ((img->getColorFormat() == irr::video::ECF_A8R8G8B8) && img->lock())
|
||||
// FIXME: can't we just do this externally, and just use the
|
||||
// modified textures??
|
||||
video::IImage* img =
|
||||
m_scene_manager->getVideoDriver()->createImageFromFile(filename.c_str());
|
||||
// PNGs are non premul, but some are used for premul tasks, so convert
|
||||
// http://home.comcast.net/~tom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]
|
||||
// FIXME check param, not name
|
||||
if(is_premul &&
|
||||
StringUtils::hasSuffix(filename.c_str(), ".png") &&
|
||||
(img->getColorFormat() == irr::video::ECF_A8R8G8B8) &&
|
||||
img->lock())
|
||||
{
|
||||
core::dimension2d<u32> dim = img->getDimension();
|
||||
for(uint x = 0; x < dim.Width; x++)
|
||||
for(unsigned int x = 0; x < dim.Width; x++)
|
||||
{
|
||||
for(uint y = 0; y < dim.Height; y++)
|
||||
for(unsigned int y = 0; y < dim.Height; y++)
|
||||
{
|
||||
video::SColor col = img->getPixel(x, y);
|
||||
uint alpha = col.getAlpha();
|
||||
uint red = alpha * col.getRed() / 255;
|
||||
uint blue = alpha * col.getBlue() / 255;
|
||||
uint green = alpha * col.getGreen() / 255;
|
||||
unsigned int alpha = col.getAlpha();
|
||||
unsigned int red = alpha * col.getRed() / 255;
|
||||
unsigned int blue = alpha * col.getBlue() / 255;
|
||||
unsigned int green = alpha * col.getGreen() / 255;
|
||||
col.set(alpha, red, green, blue);
|
||||
img->setPixel(x, y, col, false);
|
||||
}
|
||||
}
|
||||
} // for y
|
||||
} // for x
|
||||
img->unlock();
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Other formats can be premul, but the tasks can be non premul
|
||||
// So divide to get the separate RGBA (only possible if alpha!=0)
|
||||
else if() // FIXME, use param "DE-PREMUL requested" to match above
|
||||
{
|
||||
if ((img->getColorFormat() == irr::video::ECF_A8R8G8B8) && img->lock())
|
||||
} // if png and ColorFOrmat and lock
|
||||
// Other formats can be premul, but the tasks can be non premul
|
||||
// So divide to get the separate RGBA (only possible if alpha!=0)
|
||||
else if(is_prediv &&
|
||||
(img->getColorFormat() == irr::video::ECF_A8R8G8B8) &&
|
||||
img->lock())
|
||||
{
|
||||
core::dimension2d<u32> dim = img->getDimension();
|
||||
for(uint x = 0; x < dim.Width; x++)
|
||||
for(unsigned int x = 0; x < dim.Width; x++)
|
||||
{
|
||||
for(uint y = 0; y < dim.Height; y++)
|
||||
for(unsigned int y = 0; y < dim.Height; y++)
|
||||
{
|
||||
video::SColor col = img->getPixel(x, y);
|
||||
uint alpha = col.getAlpha();
|
||||
unsigned int alpha = col.getAlpha();
|
||||
// Avoid divide by zero
|
||||
if (alpha) {
|
||||
uint red = 255 * col.getRed() / alpha ;
|
||||
uint blue = 255 * col.getBlue() / alpha;
|
||||
uint green = 255 * col.getGreen() / alpha;
|
||||
unsigned int red = 255 * col.getRed() / alpha ;
|
||||
unsigned int blue = 255 * col.getBlue() / alpha;
|
||||
unsigned int green = 255 * col.getGreen() / alpha;
|
||||
col.set(alpha, red, green, blue);
|
||||
img->setPixel(x, y, col, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for y
|
||||
} // for x
|
||||
img->unlock();
|
||||
}
|
||||
}
|
||||
*/
|
||||
video::ITexture* out = m_scene_manager->getVideoDriver()->addTexture(filename.c_str(),
|
||||
img, NULL);
|
||||
#endif
|
||||
|
||||
} // if premul && color format && lock
|
||||
out = m_scene_manager->getVideoDriver()->addTexture(filename.c_str(),
|
||||
img, NULL);
|
||||
} // if is_premul or is_prediv
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (out == NULL)
|
||||
{
|
||||
|
||||
@@ -112,7 +112,9 @@ public:
|
||||
bool OnEvent(const irr::SEvent &event);
|
||||
|
||||
void setAmbientLight(const video::SColor &light);
|
||||
video::ITexture *getTexture(const std::string &filename);
|
||||
video::ITexture *getTexture(const std::string &filename,
|
||||
bool is_premul=false,
|
||||
bool is_prediv=false);
|
||||
scene::IMesh *createQuadMesh(const video::SMaterial *material=NULL,
|
||||
bool create_one_quad=false);
|
||||
scene::IMesh *createTexturedQuadMesh(const video::SMaterial *material, const double w, const double h);
|
||||
|
||||
@@ -56,6 +56,17 @@ Material::Material(const XMLNode *node, int index)
|
||||
node->get("clampV", &b); if (b) m_clamp_tex |= VCLAMP;
|
||||
node->get("transparency", &m_alpha_testing );
|
||||
node->get("lightmap", &m_lightmap );
|
||||
std::string s;
|
||||
node->get("adjust-image", &s );
|
||||
if(s=="premultiply")
|
||||
m_adjust_image = ADJ_PREMUL;
|
||||
else if (s=="divide")
|
||||
m_adjust_image = ADJ_DIV;
|
||||
else if (s=="" || s=="none")
|
||||
m_adjust_image = ADJ_NONE;
|
||||
else
|
||||
printf("Incorrect adjust-image specification: '%s' - ignored.\n",
|
||||
s.c_str());
|
||||
node->get("alpha", &m_alpha_blending );
|
||||
node->get("light", &m_lighting );
|
||||
node->get("sphere", &m_sphere_map );
|
||||
@@ -77,7 +88,8 @@ Material::Material(const XMLNode *node, int index)
|
||||
node->get("anisotropic", &m_anisotropic );
|
||||
node->get("backface-culling", &m_backface_culling );
|
||||
node->get("disable-z-write", &m_disable_z_write );
|
||||
std::string s("");
|
||||
|
||||
s="";
|
||||
node->get("graphical-effect", &s );
|
||||
if(s=="water")
|
||||
m_graphical_effect = GE_WATER;
|
||||
@@ -162,6 +174,7 @@ void Material::init(unsigned int index)
|
||||
m_clamp_tex = 0;
|
||||
m_alpha_testing = false;
|
||||
m_lightmap = false;
|
||||
m_adjust_image = ADJ_NONE;
|
||||
m_alpha_blending = false;
|
||||
m_lighting = true;
|
||||
m_anisotropic = false;
|
||||
@@ -201,7 +214,8 @@ void Material::install(bool is_full_path)
|
||||
const std::string &full_path = is_full_path
|
||||
? m_texname
|
||||
: file_manager->getTextureFile(m_texname);
|
||||
m_texture = irr_driver->getTexture(full_path);
|
||||
m_texture = irr_driver->getTexture(full_path,
|
||||
isPreMul(), isPreDiv());
|
||||
|
||||
// now set the name to the basename, so that all tests work as expected
|
||||
m_texname = StringUtils::getBasename(m_texname);
|
||||
|
||||
@@ -96,7 +96,11 @@ private:
|
||||
|
||||
/** Set to true to disable writing to the Z buffer. Usually to be used with alpha blending */
|
||||
bool m_disable_z_write;
|
||||
|
||||
|
||||
/** Some textures need to be pre-multiplied, some divided to give
|
||||
* the intended effect. */
|
||||
enum {ADJ_NONE, ADJ_PREMUL, ADJ_DIV}
|
||||
m_adjust_image;
|
||||
/** True if lightmapping is enabled for this material. */
|
||||
bool m_lightmap;
|
||||
float m_friction;
|
||||
@@ -158,6 +162,12 @@ public:
|
||||
|
||||
bool isTransparent () const { return m_alpha_testing || m_alpha_blending || m_add; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this materials need pre-multiply of alpha. */
|
||||
bool isPreMul() const {return m_adjust_image==ADJ_PREMUL; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this materials need pre-division of alpha. */
|
||||
bool isPreDiv() const {return m_adjust_image==ADJ_DIV; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the fraction of maximum speed on this material. */
|
||||
float getMaxSpeedFraction() const { return m_max_speed_fraction; }
|
||||
|
||||
Reference in New Issue
Block a user