forked from Mirrorlandia_minetest/minetest
Minimap: gamma-correct average texture colour calculation (#9249)
This calculates the average texture colour while heeding the sRGB colourspace.
This commit is contained in:
parent
206e131854
commit
7a1464d783
@ -2229,6 +2229,48 @@ video::ITexture* TextureSource::getNormalTexture(const std::string &name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// For more colourspace transformations, see for example
|
||||||
|
// https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl
|
||||||
|
|
||||||
|
inline float linear_to_srgb_component(float v)
|
||||||
|
{
|
||||||
|
if (v > 0.0031308f)
|
||||||
|
return 1.055f * powf(v, 1.0f / 2.4f) - 0.055f;
|
||||||
|
return 12.92f * v;
|
||||||
|
}
|
||||||
|
inline float srgb_to_linear_component(float v)
|
||||||
|
{
|
||||||
|
if (v > 0.04045f)
|
||||||
|
return powf((v + 0.055f) / 1.055f, 2.4f);
|
||||||
|
return v / 12.92f;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3f srgb_to_linear(const video::SColor &col_srgb)
|
||||||
|
{
|
||||||
|
v3f col(col_srgb.getRed(), col_srgb.getGreen(), col_srgb.getBlue());
|
||||||
|
col /= 255.0f;
|
||||||
|
col.X = srgb_to_linear_component(col.X);
|
||||||
|
col.Y = srgb_to_linear_component(col.Y);
|
||||||
|
col.Z = srgb_to_linear_component(col.Z);
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::SColor linear_to_srgb(const v3f &col_linear)
|
||||||
|
{
|
||||||
|
v3f col;
|
||||||
|
col.X = linear_to_srgb_component(col_linear.X);
|
||||||
|
col.Y = linear_to_srgb_component(col_linear.Y);
|
||||||
|
col.Z = linear_to_srgb_component(col_linear.Z);
|
||||||
|
col *= 255.0f;
|
||||||
|
col.X = core::clamp<float>(col.X, 0.0f, 255.0f);
|
||||||
|
col.Y = core::clamp<float>(col.Y, 0.0f, 255.0f);
|
||||||
|
col.Z = core::clamp<float>(col.Z, 0.0f, 255.0f);
|
||||||
|
return video::SColor(0xff, myround(col.X), myround(col.Y),
|
||||||
|
myround(col.Z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
video::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
video::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
||||||
{
|
{
|
||||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||||
@ -2243,9 +2285,7 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
|||||||
return c;
|
return c;
|
||||||
|
|
||||||
u32 total = 0;
|
u32 total = 0;
|
||||||
u32 tR = 0;
|
v3f col_acc(0, 0, 0);
|
||||||
u32 tG = 0;
|
|
||||||
u32 tB = 0;
|
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
u16 step = 1;
|
u16 step = 1;
|
||||||
if (dim.Width > 16)
|
if (dim.Width > 16)
|
||||||
@ -2255,17 +2295,14 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
|||||||
c = image->getPixel(x,y);
|
c = image->getPixel(x,y);
|
||||||
if (c.getAlpha() > 0) {
|
if (c.getAlpha() > 0) {
|
||||||
total++;
|
total++;
|
||||||
tR += c.getRed();
|
col_acc += srgb_to_linear(c);
|
||||||
tG += c.getGreen();
|
|
||||||
tB += c.getBlue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
image->drop();
|
image->drop();
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
c.setRed(tR / total);
|
col_acc /= total;
|
||||||
c.setGreen(tG / total);
|
c = linear_to_srgb(col_acc);
|
||||||
c.setBlue(tB / total);
|
|
||||||
}
|
}
|
||||||
c.setAlpha(255);
|
c.setAlpha(255);
|
||||||
return c;
|
return c;
|
||||||
|
Loading…
Reference in New Issue
Block a user