Tutorials

Your first texture

Draw a small plant as a character grid, render it, lint it and look at it in 3D.

In this tutorial you draw a small single-block plant, a sprout, from nothing. Along the way you will use the four commands that make up nearly every TextureScript session: palette, grid, lint and shoot.

You need texturescript on your PATH (see Install TextureScript). You do not need Minecraft: everything here works without a game jar.

Make a folder

mkdir sprout && cd sprout

Choose the colours

A texture's colours come from a palette file. You do not pick every shade: you pick a dark and a light anchor for each material and say how many shades you want. TextureScript fills in the rest.

Create sprout.palette:

sprout.palette
material leaf  dark #266325  light #55ab2d  shades 4  keys abcd
transparent .

This declares one material, leaf, with four shades named a (darkest) to d (lightest), and uses . for empty pixels. The two anchors are vanilla's own crop-leaf greens.

Run palette to derive the shades:

texturescript palette sprout.palette --out palette.txt --swatch swatch.png

palette.txt now holds the palette section of a grid:

palette.txt
palette
. transparent
# leaf: 4 shades #266325 -> #55ab2d
# leaf: dark L44 C11 h143, light L66 C18 h138; vanilla foliage: dark L31-57, light L45-79, chroma <= 24
a #266325
b #347a2a
c #43922d
d #55ab2d

The comment lines compare your anchors with the range measured on vanilla foliage. Both sit inside it, so there is no warning. Open swatch.png if you want to see the four shades.

Draw the grid

A grid file is the palette section followed by grid and 16 rows of 16 characters. Create sprout.grid by pasting palette.txt and then drawing below it:

sprout.grid
palette
. transparent
# leaf: 4 shades #266325 -> #55ab2d
# leaf: dark L44 C11 h143, light L66 C18 h138; vanilla foliage: dark L31-57, light L45-79, chroma <= 24
a #266325
b #347a2a
c #43922d
d #55ab2d
grid
................
................
................
................
................
.......dd.......
......dccd......
..d...dcc...d...
..cd...cb..dc...
...cd..bb.dc....
....cc.bb.cb....
.....cbbbcb.....
......bbbb......
.......bb.......
.......aa.......
.......aa.......

Notice the shape: a two-pixel stem on columns 7 and 8 that darkens towards the soil, two leaves stepping up and out from it, and lighter shades at the top. The bottom row is the soil line, so the stem touches it.

Render it

texturescript grid sprout.grid out/sprout.png
rendered out/sprout.png (16x16, 5 palette entries)

Three files appear in out/:

  • sprout.png, the 16×16 texture itself;
  • sprout_x16.png, the same image enlarged sixteen times, for looking at;
  • sprout.txt, the grid as ASCII, for checking pixel positions exactly.

Open sprout_x16.png. This is how you judge shape.

See what a mistake looks like

Delete one dot from row 10 of sprout.grid, so the row is 15 characters wide, and render again:

REFUSED sprout.grid:20: row is 15 wide, expected 16 like the first row

TextureScript names the file and line and writes nothing. A wrong row width is the most common refusal, so get used to counting characters. Put the dot back.

Lint it

texturescript lint out/sprout.png --palette sprout.palette
OK   alpha     binary
OK   budget    4 colours
OK   palette   all colours are palette shades; leaf 4
OK   noise     isolated-pixel fraction 0.067 (fail above 0.5) at (11,9) (10,10) (9,11)
OK   coverage  18% opaque
OK   outline   no outline, as for vanilla crops
PASSED: 0 fail, 0 warn

Each line is a rule measured on vanilla textures. --palette adds a check that every colour comes from your palette. A FAIL must be fixed; a WARN is a question worth asking. The sprout passes everything. The lint rules page lists them all.

Look at it in 3D

A flat sprite is not what the player sees. In the game a plant is drawn on crossing planes, so it overlaps itself. To see that, describe a tiny scene.

First, a .stages file that turns the grid into a one-stage crop:

sprout.stages
palette sprout.palette
grid lower sprout.grid
stages 1
map lower
................
................
................
................
................
.......00.......
......0000......
..0...000...0...
..00...00..00...
...00..00.00....
....00.00.00....
.....000000.....
......0000......
.......00.......
.......00.......
.......00.......

The map marks every opaque pixel with the stage at which it appears; with one stage, that is always 0. The growth stages tutorial does this properly.

Then the scene, sprout.toml:

sprout.toml
camera = { yaw = 30, pitch = 22, distance = 5 }
floor = "minecraft:grass_block"

[[plot]]
label = "sprout"
stages = "sprout.stages"
model = "cross"
at = [0, 0]

model = "cross" plants the sprite on two diagonal planes, like a sapling or a flower.

Take two screenshots from different angles:

texturescript shoot sprout.toml out/shot.png --cam 30,22,4 --cam 120,10,4
out/shot.png: 2 shots (1 variant × 2 cameras)

Open out/shot.png. If you have no Minecraft installed, the grass floor is listed as missing and your sprout floats on sky; that is expected. With the game installed, it stands on grass.

If you can see a browser, try the live view instead:

texturescript view sprout.toml

Leave it running, change a leaf in sprout.grid and save. The sprout in the browser changes in place.

What you have learned

You chose two anchors and let palette derive the shades, drew a grid with those keys, rendered it, read a refusal, linted the result and judged it on the block model. That loop of draw, render, lint and look is the whole method.

Next, grow a crop through its stages.

Copyright © 2026