aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHybridDog <3192173+HybridDog@users.noreply.github.com>2021-11-26 19:30:49 +0100
committerGitHub <noreply@github.com>2021-11-26 19:30:49 +0100
commit7a1464d783742512fdc6e0a083ffadd0ce63c1b4 (patch)
treea2edcfe570d40162362ca87b5600eb46f6ef0360 /src
parent206e131854392ed2d39b3456f7a1b5a54bd1bff9 (diff)
downloadminetest-7a1464d783742512fdc6e0a083ffadd0ce63c1b4.tar.gz
minetest-7a1464d783742512fdc6e0a083ffadd0ce63c1b4.tar.bz2
minetest-7a1464d783742512fdc6e0a083ffadd0ce63c1b4.zip
Minimap: gamma-correct average texture colour calculation (#9249)
This calculates the average texture colour while heeding the sRGB colourspace.
Diffstat (limited to 'src')
-rw-r--r--src/client/tile.cpp55
1 files changed, 46 insertions, 9 deletions
diff --git a/src/client/tile.cpp b/src/client/tile.cpp
index 2f57503d3..da03ff5c8 100644
--- a/src/client/tile.cpp
+++ b/src/client/tile.cpp
@@ -2229,6 +2229,48 @@ video::ITexture* TextureSource::getNormalTexture(const std::string &name)
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::IVideoDriver *driver = RenderingEngine::get_video_driver();
@@ -2243,9 +2285,7 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
return c;
u32 total = 0;
- u32 tR = 0;
- u32 tG = 0;
- u32 tB = 0;
+ v3f col_acc(0, 0, 0);
core::dimension2d<u32> dim = image->getDimension();
u16 step = 1;
if (dim.Width > 16)
@@ -2255,17 +2295,14 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
c = image->getPixel(x,y);
if (c.getAlpha() > 0) {
total++;
- tR += c.getRed();
- tG += c.getGreen();
- tB += c.getBlue();
+ col_acc += srgb_to_linear(c);
}
}
}
image->drop();
if (total > 0) {
- c.setRed(tR / total);
- c.setGreen(tG / total);
- c.setBlue(tB / total);
+ col_acc /= total;
+ c = linear_to_srgb(col_acc);
}
c.setAlpha(255);
return c;