Let material code handle premultiplied alpha and srgb

This commit is contained in:
Benau
2017-01-03 16:35:37 +08:00
parent 0129c539b9
commit 05a29fe7da
5 changed files with 94 additions and 24 deletions

View File

@@ -33,6 +33,8 @@
#include "graphics/irr_driver.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/shaders.hpp"
#include "graphics/stk_texture.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/texture_manager.hpp"
#include "io/file_manager.hpp"
#include "race/race_manager.hpp"
@@ -60,6 +62,7 @@ Material::Material(const XMLNode *node, bool deprecated)
m_shader_type = SHADERTYPE_SOLID;
m_deprecated = deprecated;
m_installed = false;
m_srgb_texture = true;
node->get("name", &m_texname);
if (m_texname=="")
@@ -399,11 +402,11 @@ Material::Material(const XMLNode *node, bool deprecated)
m_high_tire_adhesion = true;
} // Material
//-----------------------------------------------------------------------------
video::ITexture* Material::getTexture(bool srgb, bool premul_alpha)
video::ITexture* Material::getTexture()
{
if (!m_installed)
{
install(srgb, premul_alpha);
install();
}
return m_texture;
} // getTexture
@@ -414,10 +417,12 @@ video::ITexture* Material::getTexture(bool srgb, bool premul_alpha)
* \param is_full_path If the fname contains the full path.
*/
Material::Material(const std::string& fname, bool is_full_path,
bool complain_if_not_found, bool load_texture)
bool complain_if_not_found, bool load_texture,
bool srgb)
{
m_deprecated = false;
m_installed = false;
m_srgb_texture = srgb;
init();
if (is_full_path)
@@ -488,7 +493,7 @@ void Material::init()
} // init
//-----------------------------------------------------------------------------
void Material::install(bool srgb, bool premul_alpha)
void Material::install()
{
// Don't load a texture that are not supposed to be loaded automatically
if (m_installed) return;
@@ -503,10 +508,23 @@ void Material::install(bool srgb, bool premul_alpha)
else
{
m_texture = irr_driver->getTexture(m_full_path,
false, //isPreMul(),
false, //isPreDiv(),
m_complain_if_not_found);
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
m_texture = STKTexManager::getInstance()->getTexture
(m_full_path, m_srgb_texture,
m_shader_type == SHADERTYPE_ALPHA_BLEND ||
m_shader_type == SHADERTYPE_ADDITIVE ?
true : false/*premul_alpha*/,
false/*set_material*/, m_srgb_texture/*mesh_tex*/);
}
else
#endif
{
m_texture = irr_driver->getTexture(m_full_path,
false, //isPreMul(), false, //isPreDiv(),
m_complain_if_not_found);
}
}
if (m_texture == NULL) return;
@@ -748,9 +766,12 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
{
ITexture *tex;
ITexture *glossytex;
STKTexManager* stm = STKTexManager::getInstance();
if (m_gloss_map.size() > 0 && UserConfigParams::m_dynamic_lights)
{
glossytex = irr_driver->getTexture(m_gloss_map);
glossytex = stm->getTexture(m_gloss_map, false/*srgb*/,
false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
else
{
@@ -763,7 +784,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
ITexture *colorization_mask_tex = getUnicolorTexture(SColor(0, 0, 0, 0));
if (m_colorization_mask.size() > 0)
{
colorization_mask_tex = irr_driver->getTexture(m_colorization_mask);
colorization_mask_tex = stm->getTexture(m_colorization_mask,
false/*srgb*/, false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
m->setTexture(2, colorization_mask_tex);
}
@@ -819,24 +842,32 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m->setTexture(1, glossytex);
return;
case SHADERTYPE_SPLATTING:
tex = irr_driver->getTexture(m_splatting_texture_1);
tex = stm->getTexture(m_splatting_texture_1,
true/*srgb*/, false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
m->setTexture(3, tex);
if (m_splatting_texture_2.size() > 0)
{
tex = irr_driver->getTexture(m_splatting_texture_2);
tex = stm->getTexture(m_splatting_texture_2,
true/*srgb*/, false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
m->setTexture(4, tex);
if (m_splatting_texture_3.size() > 0)
{
tex = irr_driver->getTexture(m_splatting_texture_3);
tex = stm->getTexture(m_splatting_texture_3,
true/*srgb*/, false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
m->setTexture(5, tex);
if (m_splatting_texture_4.size() > 0)
{
tex = irr_driver->getTexture(m_splatting_texture_4);
tex = stm->getTexture(m_splatting_texture_4,
false/*srgb*/, false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
m->setTexture(6, tex);
m->setTexture(7, glossytex);
@@ -874,7 +905,11 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_normal_map_tex.size() > 0)
{
if (UserConfigParams::m_dynamic_lights)
tex = irr_driver->getTexture(m_normal_map_tex);
{
tex = stm->getTexture(m_normal_map_tex, false/*srgb*/,
false/*premul_alpha*/, false/*set_material*/,
true/*mesh_tex*/);
}
else
tex = getUnicolorTexture(SColor(0, 0, 0, 0));
m->setTexture(3, tex);

View File

@@ -266,8 +266,11 @@ private:
bool m_installed;
/** If Layer 1 texture is srgb. */
bool m_srgb_texture;
void init ();
void install (bool srgb = false, bool premul_alpha = false);
void install ();
void initCustomSFX(const XMLNode *sfx);
void initParticlesEffect(const XMLNode *node);
@@ -276,7 +279,8 @@ public:
Material(const std::string& fname,
bool is_full_path=false,
bool complain_if_not_found=true,
bool load_texture = true);
bool load_texture = true,
bool srgb = false);
~Material ();
void unloadTexture();
@@ -290,7 +294,7 @@ public:
void isInitiallyHidden(scene::IMeshBuffer* who);
/** Returns the ITexture associated with this material. */
video::ITexture *getTexture(bool srgb = false, bool premul_alpha = false);
video::ITexture *getTexture();
// ------------------------------------------------------------------------
bool isIgnore () const { return m_ignore; }
// ------------------------------------------------------------------------

View File

@@ -335,7 +335,8 @@ Material *MaterialManager::getMaterial(const std::string& fname,
bool is_full_path,
bool make_permanent,
bool complain_if_not_found,
bool strip_path)
bool strip_path,
bool srgb)
{
if(fname=="")
{

View File

@@ -76,7 +76,8 @@ public:
bool is_full_path=false,
bool make_permanent=false,
bool complain_if_not_found=true,
bool strip_path=true);
bool strip_path=true,
bool srgb=false);
void addSharedMaterial(const std::string& filename, bool deprecated = false);
bool pushTempMaterial (const std::string& filename, bool deprecated = false);
bool pushTempMaterial (const XMLNode *root, const std::string& filename, bool deprecated = false);

View File

@@ -99,6 +99,35 @@ void STKTexture::reload(bool no_upload, video::IImage* pre_loaded_tex)
else
new_texture = pre_loaded_tex;
unsigned char* data = (unsigned char*)new_texture->lock();
const unsigned int w = new_texture->getDimension().Width;
const unsigned int h = new_texture->getDimension().Height;
unsigned int format = GL_BGRA;
#if defined(USE_GLES2)
if (!CVS->isEXTTextureFormatBGRA8888Usable())
{
format = GL_RGBA;
for (unsigned int i = 0; i < w * h; i++)
{
char tmp_val = data[i * 4];
data[i * 4] = data[i * 4 + 2];
data[i * 4 + 2] = tmp_val;
}
}
#endif
if (m_premul_alpha)
{
for (unsigned int i = 0; i < w * h; i++)
{
float alpha = data[4 * i + 3];
if (alpha > 0.0f)
alpha = pow(alpha / 255.f, 1.f / 2.2f);
data[i * 4] = (unsigned char)(data[i * 4] * alpha);
data[i * 4 + 1] = (unsigned char)(data[i * 4 + 1] * alpha);
data[i * 4 + 2] = (unsigned char)(data[i * 4 + 2] * alpha);
}
}
if (!no_upload)
{
const bool reload = m_texture_name != 0;
@@ -110,15 +139,15 @@ void STKTexture::reload(bool no_upload, video::IImage* pre_loaded_tex)
{
glTexImage2D(GL_TEXTURE_2D, 0, m_srgb ? GL_SRGB_ALPHA : GL_RGBA,
new_texture->getDimension().Width,
new_texture->getDimension().Height, 0, GL_BGRA,
GL_UNSIGNED_BYTE, new_texture->lock());
new_texture->getDimension().Height, 0, format,
GL_UNSIGNED_BYTE, data);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
new_texture->getDimension().Width,
new_texture->getDimension().Height, GL_BGRA, GL_UNSIGNED_BYTE,
new_texture->lock());
new_texture->getDimension().Height, format, GL_UNSIGNED_BYTE,
data);
}
new_texture->unlock();
glGenerateMipmap(GL_TEXTURE_2D);