Lesson 04 (Textures) updated Wed, 03/20/2019 - 02:33

Handout (Right click and save as): 
     In this lesson we'll be looking at textures and texture effects. I'll only be covering full nodes, in a future lesson we'll get to nodeboxes and meshes and how to texture them. Up until now all our nodes have used just one texture, but we have more options than that. Many nodes have different textures on their faces, such as tree trunks. Minetest gives us control over every face of a node and there are several stages of customization that we have.

     When creating a node with different textures on the faces you'll want to set paramtype2 as 'facedir' we'll look at the other options of paramtype2 in the future, but for the time being setting this will make the node rotate to place in the direction the player is looking. Skipping this step will result in the node always facing the same direction.

     The textures are defined in the tiles table. As we've already seen if we define one tile each face will show the same texture. The draw order of the textures in the table is as follows.

{Top, Bottom, Right, Left, Front, Back}

     If you want all the sides to be the same texture, you can just define three tiles, and the left front and back faces will all use the right face's texture. This actually works in many cases, such as tree trunks. If you define any less than six tiles the tiles you didn't define will use the last texture listed.

     Let's create a new node that uses six different textures. Feel free to use the textures I provide in the resource pack, or create your own. For ease of typing I just used 1-6 as my file names, but of course you can use anything you'd like. It would be a good idea to prefix the names with the mods name, to make sure they don't accidentally get used in any other mod.

     Placing our newly created node in the world we see that it has different textures on each face, and furthermore we can place it while facing all four directions and we always have the backside facing towards us.

     This covers how to use different textures for all the faces of a node, but there is more to discuss about textures. Texture Modifiers, these let us change textures in code, and often allow for us to create an easier/better experience when updating textures or texture packs.

     The most commonly used effect is texture overlaying, which is done with a caret. We'll start by putting an overlay on one of our basic nodes. All we have to do is add a caret after the base texture and add the overlay texture filename after that.

     To start with we'll add a simple overlay to our fake diamond. heart.png is the texture used for the health status bar, so we'll use that and overlay it over the diamond block texture like this.
tiles = {"default_diamond_block.png^heart.png"}

     Starting the game we can place some of those blocks and we'll see that the heart is drawn over the diamond block texture on all sides. What if the overlay should only be on a single face though? that's simple to do. Let's go ahead and add the heart image to the top of our first node. Just like previously we'll just add the ^heart.png after the first tile.

     Launching the game we can see that the heart is only drawn on the top of the first node. Of course if one wanted they could do an overlay on each face, or do different overlays on each face, it's completely open to your desires.

     The benefit in using overlays is that if you ever want to change a texture you only have to change one, it also makes is easier for people making texture packs. The stone with ores is a good example. Minetest game has a handful of ores and they are all an overlay texture over the default_stone.png texture. If somebody wanted to change what the stone looks like they only need to change one texture, rather than having to try and change the stone parts of all of the ore textures.

     There is much more we can do, and if we want we can even put multiple modifiers together on one face, though it will likely be necessary to enclose portions of the modifiers within parenthesis to achieve the result we want. All modifiers with the exception of overlays and groups use an opening square brace and a modifier name and set of variables to define what should be done to the texture. We still need to use the caret before the square brace though, or we'll get an error about the texture not existing.

     The heart image is looking a little dark in my opinion, but only on the first node, so let's change that. We can use the brighten modifier which will make the colors of the pixels brighter. We only want to brighten the heart though, the base texture is perfect and we don't want to make that brighter. We'll use a group for the heart image and it's modifier and then overlay that over the base texture. I believe we can use a numerical value from 0-255.

     Launching the game we'll see that our hearts on the first node are looking a little pink now, but the heart on the diamond block still looks normal. The modifiers only affect the node and tile that they are used on, so we can use a base texture and do different things with it on a multitude of nodes, saving ourselves some file space and time.

     I don't really care for how the heart looks though, I wanted the dark reds to be a little lighter, but didn't want it to turn pink. Let's change the brighten to colorize. While brighten only take a numerical value the colorize modifier takes two variables, a color string, and a numerical value. We can either use a variety of RGB formats, or use any HTML color name. So rather than launching an image editor to see what the RGB value is for red, we can just use the word red.

     We can change the numerical value to represent how much red we want added, setting the value to 255 will result in a solid red heart, this doesn't affect the alpha though. We can use this to completely change the color of the heart if we'd like, by simply changing the color. In the upper example you can see how the colorize effect works on a greyscale gradient. The last example in each row uses the multiply modifier, this takes a color value, but no numerical value. Multiplying works well for coloring greyscale images, making the color vary in brightness dependent on the greyscale image. You can adjust the brightness of color that you are multiplying to achieve different shades in your final texture.

     To demo how to use different modifiers on base images and their overlays lets do one more change to our node, well three actually, let's change the green back to red, and add a transform to both images.

     Notice how both images are isolated between parenthesis, and the modifiers are strung together with carets.

     There are many more things we can do, such as rotating and flipping images, turning specific colors to alpha, removing alpha, and copying a vertical portion of one image onto another. Of course we can combine these modifier as well. I could go for hours and hours covering all the different things we can do, but that would get boring, so I'll just let you explore and fool around with the different modifiers. You can find an entire list along with short descriptions of what they do and how to use them in the lua api.

     Let's take a look at animated textures next. You've probably noticed that a few textures in game are animated, water most specifically, but the fronts of furnaces also have an animated texture when something is being cooked. Minetest let's you use vertical frames or a sheet of images. When using vertical frames you need to define how wide and tall each individual images is in the image, and it will automatically detect how many individual frames there are. Using a sheet you need to define how many frames wide and tall the sheet is. Using animated textures requires quite a bit more code in the node registration, but it's really not that difficult.
   tiles = {
         name = "default_furnace_front_active.png",
           animation = {
               type = "vertical_frames",
               aspect_w = 16,
               aspect_h = 16,
               length = 1.5

     Like a static image we need to define the texture name, I'm using the furnace animation, because I didn't want to create my own animation. Following the name we have a table with animation data. This image is in the vertical frame layout, so we have how wide and high, in pixels, each frame should be. When using the vertical_frames type you specify the entire loops length in seconds, but when using a sheet you define each frames length.

     We can use have a single animated face on a node, with the rest of the faces being static, we do this just like a multiple textured node, and place the entire table with the name and animation in the correct location.
tiles = {'default_diamond_block.png', 'default_diamond_block.png',
         name = "default_furnace_front_active.png",
           animation = {
               type = "vertical_frames",
               aspect_w = 16,
               aspect_h = 16,
               length = 4
     Global textures are a neat way to add a little variance to textures without creating multiple nodes. Node with this option will pull a texture from a larger sheet depending on where they are placed in the world. To start we need an image that has a a number of tiles that can evenly divide sixteen. We define a single texture, an align_style of world, and a scale. The scale is the number of nodes the texture will span. The inventory image will show the entire texture by default, but you can easily create an inventory image with the inventorycube modifier. You'll need to define three faces, and can easily pull them from the tilesheet using the sheet modifier and the scale value. This example uses a horrible texture, but does make the feature very noticeable.

     Before I wrap this up I think it's important to talk a little bit about file formats and resolutions. Minetest will read many image formats, but PNG is the most widely used and what I recommend, if for no other reason than its lossless nature which lets you edit and save the image as many times as you want without the texture ever becoming muddied and blurry. Minetest game uses textures that are sixteen pixels wide and tall, but there are texture packs in other resolutions, 32x32 is fairly common, there is even a 512x512 texture pack. Of course at a high resolution like that you'll need a decent system to run the game smoothly. The important thing to keep in mind when working on your textures is that the resolution should always be evenly divisible by two and you should probably keep all your textures the same resolution, to avoid having nodes that look out of place because they are a different a resolution. 

     Check out the lua api page for more information on what's available. https://github.com/minetest/minetest/blob/master/doc/lua_api.txt search for Texture Modifiers to find the section.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.