Textures

Mods should generally prefix their textures with modname_, e.g. given the mod name foomod, a texture could be called:

foomod_foothing.png

Textures are referred to by their complete name, or alternatively by stripping out the file extension:

  • e.g. foomod_foothing.png
  • e.g. foomod_foothing

Supported texture formats are PNG (.png), JPEG (.jpg), Bitmap (.bmp) and Targa (.tga). Since better alternatives exist, the latter two may be removed in the future.

Texture modifiers

There are various texture modifiers that can be used to let the client generate textures on-the-fly. The modifiers are applied directly in sRGB colorspace, i.e. without gamma-correction.

Texture overlaying

Textures can be overlaid by putting a ^ between them.

Example:

default_dirt.png^default_grass_side.png

default_grass_side.png is overlaid over default_dirt.png. The texture with the lower resolution will be automatically upscaled to the higher resolution texture.

Texture grouping

Textures can be grouped together by enclosing them in ( and ).

Example: cobble.png^(thing1.png^thing2.png)

A texture for thing1.png^thing2.png is created and the resulting texture is overlaid on top of cobble.png.

Escaping

Modifiers that accept texture names (e.g. [combine) accept escaping to allow passing complex texture names as arguments. Escaping is done with backslash and is required for ^ and :.

Example: cobble.png^[lowpart:50:color.png\^[mask\:trans.png

The lower 50 percent of color.png^[mask:trans.png are overlaid on top of cobble.png.

Advanced texture modifiers

Crack

  • [crack:<n>:<p>
  • [cracko:<n>:<p>
  • [crack:<t>:<n>:<p>
  • [cracko:<t>:<n>:<p>

Parameters:

  • <t>: tile count (in each direction)
  • <n>: animation frame count
  • <p>: current animation frame

Draw a step of the crack animation on the texture. crack draws it normally, while cracko lays it over, keeping transparent pixels intact.

Example:

default_cobble.png^[crack:10:1

[combine:<w>x<h>:<x1>,<y1>=<file1>:<x2>,<y2>=<file2>:...

  • <w>: width
  • <h>: height
  • <x>: x position
  • <y>: y position
  • <file>: texture to combine

Creates a texture of size <w> times <h> and blits the listed files to their specified coordinates.

Example:

[combine:16x32:0,0=default_cobble.png:0,16=default_wood.png

[resize:<w>x<h>

Resizes the texture to the given dimensions.

Example:

default_sandstone.png^[resize:16x16

[opacity:<r>

Makes the base image transparent according to the given ratio.

r must be between 0 (transparent) and 255 (opaque).

Example:

default_sandstone.png^[opacity:127

[invert:<mode>

Inverts the given channels of the base image. Mode may contain the characters "r", "g", "b", "a". Only the channels that are mentioned in the mode string will be inverted.

Example:

default_apple.png^[invert:rgb

[brighten

Brightens the texture.

Example:

tnt_tnt_side.png^[brighten

[noalpha

Makes the texture completely opaque.

Example:

default_leaves.png^[noalpha

[makealpha:<r>,<g>,<b>

Convert one color to transparency.

Example:

default_cobble.png^[makealpha:128,128,128

[transform<t>

  • <t>: transformation(s) to apply

Rotates and/or flips the image.

<t> can be a number (between 0 and 7) or a transform name. Rotations are counter-clockwise.

0  I      identity
1  R90    rotate by 90 degrees
2  R180   rotate by 180 degrees
3  R270   rotate by 270 degrees
4  FX     flip X
5  FXR90  flip X then rotate by 90 degrees
6  FY     flip Y
7  FYR90  flip Y then rotate by 90 degrees

Example:

default_stone.png^[transformFXR90

[inventorycube{<top>{<left>{<right>

Escaping does not apply here and ^ is replaced by & in texture names instead.

Create an inventory cube texture using the side textures.

Example:

[inventorycube{grass.png{dirt.png&grass_side.png{dirt.png&grass_side.png

Creates an inventorycube with grass.png, dirt.png^grass_side.png and dirt.png^grass_side.png textures

[lowpart:<percent>:<file>

Blit the lower <percent>% part of <file> on the texture.

Example:

base.png^[lowpart:25:overlay.png

[verticalframe:<t>:<n>

  • <t>: animation frame count
  • <n>: current animation frame

Crops the texture to a frame of a vertical animation.

Example:

default_torch_animated.png^[verticalframe:16:8

[mask:<file>

Apply a mask to the base image.

The mask is applied using binary AND.

[sheet:<w>x<h>:<x>,<y>

Retrieves a tile at position x,y from the base image which it assumes to be a tilesheet with dimensions w,h.

[colorize:<color>:<ratio>

Colorize the textures with the given color. <color> is specified as a ColorString. <ratio> is an int ranging from 0 to 255 or the word "alpha". If it is an int, then it specifies how far to interpolate between the colors where 0 is only the texture color and 255 is only <color>. If omitted, the alpha of <color> will be used as the ratio. If it is 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.

[png:<base64>

Embed a base64 encoded PNG image in the texture string. You can produce a valid string for this by calling minetest.encode_base64(minetest.encode_png(tex)), refer to the documentation of these functions for details. You can use this to send disposable images such as captchas to individual clients, or render things that would be too expensive to compose with [combine:.

IMPORTANT: Avoid sending large images this way. This is not a replacement for asset files, do not use it to do anything that you could instead achieve by just using a file. In particular consider minetest.dynamic_add_media and test whether using other texture modifiers could result in a shorter string than embedding a whole image, this may vary by use case.

Hardware coloring

The goal of hardware coloring is to simplify the creation of colorful nodes. If your textures use the same pattern, and they only differ in their color (like colored wool blocks), you can use hardware coloring instead of creating and managing many texture files. All of these methods use color multiplication (so a white-black texture with red coloring will result in red-black color).

Static coloring

This method is useful if you wish to create nodes/items with the same texture, in different colors, each in a new node/item definition.

Global color

When you register an item or node, set its color field (which accepts a ColorSpec) to the desired color.

An ItemStack's static color can be overwritten by the color metadata field. If you set that field to a ColorString, that color will be used.

Tile color

Each tile may have an individual static color, which overwrites every other coloring method. To disable the coloring of a face, set its color to white (because multiplying with white does nothing). You can set the color property of the tiles in the node's definition if the tile is in table format.

Palettes

For nodes and items which can have many colors, a palette is more suitable. A palette is a texture, which can contain up to 256 pixels. Each pixel is one possible color for the node/item. You can register one node/item, which can have up to 256 colors.

Palette indexing

When using palettes, you always provide a pixel index for the given node or ItemStack. The palette is read from left to right and from top to bottom. If the palette has less than 256 pixels, then it is stretched to contain exactly 256 pixels (after arranging the pixels to one line). The indexing starts from 0.

Examples:

  • 16x16 palette, index = 0: the top left corner
  • 16x16 palette, index = 4: the fifth pixel in the first row
  • 16x16 palette, index = 16: the pixel below the top left corner
  • 16x16 palette, index = 255: the bottom right corner
  • 2 (width) x 4 (height) palette, index = 31: the top left corner. The palette has 8 pixels, so each pixel is stretched to 32 pixels, to ensure the total 256 pixels.
  • 2x4 palette, index = 32: the top right corner
  • 2x4 palette, index = 63: the top right corner
  • 2x4 palette, index = 64: the pixel below the top left corner

Using palettes with items

When registering an item, set the item definition's palette field to a texture. You can also use texture modifiers.

The ItemStack's color depends on the palette_index field of the stack's metadata. palette_index is an integer, which specifies the index of the pixel to use.

Linking palettes with nodes

When registering a node, set the item definition's palette field to a texture. You can also use texture modifiers. The node's color depends on its param2, so you also must set an appropriate paramtype2:

  • paramtype2 = "color" for nodes which use their full param2 for palette indexing. These nodes can have 256 different colors. The palette should contain 256 pixels.
  • paramtype2 = "colorwallmounted" for nodes which use the first five bits (most significant) of param2 for palette indexing. The remaining three bits are describing rotation, as in wallmounted paramtype2. Division by 8 yields the palette index (without stretching the palette). These nodes can have 32 different colors, and the palette should contain 32 pixels. Examples:
    • param2 = 17 is 2 * 8 + 1, so the rotation is 1 and the third (= 2 + 1) pixel will be picked from the palette.
    • param2 = 35 is 4 * 8 + 3, so the rotation is 3 and the fifth (= 4 + 1) pixel will be picked from the palette.
  • paramtype2 = "colorfacedir" for nodes which use the first three bits of param2 for palette indexing. The remaining five bits are describing rotation, as in facedir paramtype2. Division by 32 yields the palette index (without stretching the palette). These nodes can have 8 different colors, and the palette should contain 8 pixels. Examples:
    • param2 = 17 is 0 * 32 + 17, so the rotation is 17 and the first (= 0 + 1) pixel will be picked from the palette.
    • param2 = 35 is 1 * 32 + 3, so the rotation is 3 and the second (= 1 + 1) pixel will be picked from the palette.
  • paramtype2 = "color4dir" for nodes which use the first six bits of param2 for palette indexing. The remaining two bits are describing rotation, as in 4dir paramtype2. Division by 4 yields the palette index (without stretching the palette). These nodes can have 64 different colors, and the palette should contain 64 pixels. Examples:
    • param2 = 17 is 4 * 4 + 1, so the rotation is 1 and the fifth (= 4 + 1) pixel will be picked from the palette.
    • param2 = 35 is 8 * 4 + 3, so the rotation is 3 and the ninth (= 8 + 1) pixel will be picked from the palette.

To colorize a node on the map, set its param2 value (according to the node's paramtype2).

Conversion between nodes in the inventory and on the map

Static coloring is the same for both cases, there is no need for conversion.

If the ItemStack's metadata contains the color field, it will be lost on placement, because nodes on the map can only use palettes.

If the ItemStack's metadata contains the palette_index field, it is automatically transferred between node and item forms by the engine, when a player digs or places a colored node. You can disable this feature by setting the drop field of the node to itself (without metadata). To transfer the color to a special drop, you need a drop table.

Example:

minetest.register_node("mod:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    paramtype2 = "color",
    palette = "palette.png",
    drop = {
        items = {
            -- assume that mod:cobblestone also has the same palette
            {items = {"mod:cobblestone"}, inherit_color = true },
        }
    }
})

Colored items in craft recipes

Craft recipes only support item strings, but fortunately item strings can also contain metadata. Example craft recipe registration:

minetest.register_craft({
    output = minetest.itemstring_with_palette("wool:block", 3),
    type = "shapeless",
    recipe = {
        "wool:block",
        "dye:red",
    },
})

To set the color field, you can use minetest.itemstring_with_color.

Metadata field filtering in the recipe field are not supported yet, so the craft output is independent of the color of the ingredients.

Soft texture overlay

Sometimes hardware coloring is not enough, because it affects the whole tile. Soft texture overlays were added to Minetest to allow the dynamic coloring of only specific parts of the node's texture. For example a grass block may have colored grass, while keeping the dirt brown.

These overlays are 'soft', because unlike texture modifiers, the layers are not merged in the memory, but they are simply drawn on top of each other. This allows different hardware coloring, but also means that tiles with overlays are drawn slower. Using too much overlays might cause FPS loss.

For inventory and wield images you can specify overlays which hardware coloring does not modify. You have to set inventory_overlay and wield_overlay fields to an image name.

To define a node overlay, simply set the overlay_tiles field of the node definition. These tiles are defined in the same way as plain tiles: they can have a texture name, color etc. To skip one face, set that overlay tile to an empty string.

Example (colored grass block):

minetest.register_node("default:dirt_with_grass", {
    description = "Dirt with Grass",
    -- Regular tiles, as usual
    -- The dirt tile disables palette coloring
    tiles = {{name = "default_grass.png"},
        {name = "default_dirt.png", color = "white"}},
    -- Overlay tiles: define them in the same style
    -- The top and bottom tile does not have overlay
    overlay_tiles = {"", "",
        {name = "default_grass_side.png"}},
    -- Global color, used in inventory
    color = "green",
    -- Palette in the world
    paramtype2 = "color",
    palette = "default_foilage.png",
})