Add multiply texture modifier
authorsapier <sapier at gmx dot net>
Sat, 14 Jan 2017 22:16:58 +0000 (23:16 +0100)
committerparamat <mat.gregory@virginmedia.com>
Mon, 30 Jan 2017 16:37:17 +0000 (16:37 +0000)
Allows colorizing of textures using a color multiplication method.

doc/lua_api.txt
src/client/tile.cpp

index 9a1cb6bace39f92e73e11c333bcda0d469c40683..219882f465f7db2906ac457621b43b27eab99142 100644 (file)
@@ -419,6 +419,13 @@ the word "`alpha`", then each texture pixel will contain the RGB of
 `<color>` and the alpha of `<color>` multiplied by the alpha of the
 texture pixel.
 
+#### `[multiply:<color>`
+Multiplies texture colors with the given color.
+`<color>` is specified as a `ColorString`.
+Result is more like what you'd expect if you put a color on top of another
+color. Meaning white surfaces get a lot of your new color while black parts don't
+change very much.
+
 Sounds
 ------
 Only Ogg Vorbis files are supported.
index 539c29445e92fe081adc564898a87c3aeabb47e6..fbc0f1709fc987205508a69e723faae99bbe8daf 100644 (file)
@@ -555,7 +555,11 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
 // color alpha with the destination alpha.
 // Otherwise, any pixels that are not fully transparent get the color alpha.
 static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
-               video::SColor color, int ratio, bool keep_alpha);
+               const video::SColor &color, int ratio, bool keep_alpha);
+
+// paint a texture using the given color
+static void apply_multiplication(video::IImage *dst, v2u32 dst_pos, v2u32 size,
+               const video::SColor &color);
 
 // Apply a mask to an image
 static void apply_mask(video::IImage *mask, video::IImage *dst,
@@ -1656,6 +1660,30 @@ bool TextureSource::generateImagePart(std::string part_of_name,
                                                << filename << "\".";
                        }
                }
+               /*
+               [multiply:color
+                       multiplys a given color to any pixel of an image
+                       color = color as ColorString
+               */
+               else if (str_starts_with(part_of_name, "[multiply:")) {
+                       Strfnd sf(part_of_name);
+                       sf.next(":");
+                       std::string color_str = sf.next(":");
+
+                       if (baseimg == NULL) {
+                               errorstream << "generateImagePart(): baseimg != NULL "
+                                               << "for part_of_name=\"" << part_of_name
+                                               << "\", cancelling." << std::endl;
+                               return false;
+                       }
+
+                       video::SColor color;
+
+                       if (!parseColorString(color_str, color, false))
+                               return false;
+
+                       apply_multiplication(baseimg, v2u32(0, 0), baseimg->getDimension(), color);
+               }
                /*
                        [colorize:color
                        Overlays image with given color
@@ -1960,7 +1988,7 @@ static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst
        Apply color to destination
 */
 static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
-               video::SColor color, int ratio, bool keep_alpha)
+               const video::SColor &color, int ratio, bool keep_alpha)
 {
        u32 alpha = color.getAlpha();
        video::SColor dst_c;
@@ -1994,6 +2022,27 @@ static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
        }
 }
 
+/*
+       Apply color to destination
+*/
+static void apply_multiplication(video::IImage *dst, v2u32 dst_pos, v2u32 size,
+               const video::SColor &color)
+{
+       video::SColor dst_c;
+
+       for (u32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
+       for (u32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
+               dst_c = dst->getPixel(x, y);
+               dst_c.set(
+                               dst_c.getAlpha(),
+                               (dst_c.getRed() * color.getRed()) / 255,
+                               (dst_c.getGreen() * color.getGreen()) / 255,
+                               (dst_c.getBlue() * color.getBlue()) / 255
+                               );
+               dst->setPixel(x, y, dst_c);
+       }
+}
+
 /*
        Apply mask to destination
 */