Tiny code Truchet 3x3 pixels patterns
This article is a follow-up of my
Tiny bit-field based text renderer article with slightly
different usage.
Introduction
There is a well-known one line
extremely short BASIC program which show a skewed maze when run
on a 1982 C64 8-bit home
computer, the
clever trick is that it only use two characters, "/" and "\",
drawn randomly across the characters grid.
The C64 maze use a bundled character set known as PETSCII, each
characters comprise of an 8x8 pixels block, it is not a correct
maze as it has no beginning nor end but it still looks like
it.
The inspiration for this i guess was Truchet tiles
which was first described in a 1704 memoir by Sébastien Truchet.
These kind of patterns also has a much deeper history and can
be seen in many historical works such as stitching. (immediate
example is Sashiko)
Many cool patterns can be generated with small amount of code
with the same method by computing a selection of characters across
a grid, the selection can be made from all combinations of pixels
of says a 3x3 grid for simplicity, the immediate advantage is that
the font is entirely computed so there is no needs to store glyph
data, the character data can be encoded in as low as a byte with a
"font" offset :
TIC-80
(fantasy computer) maze using two characters computed from the 3x3
pixels binary matrix shown below the maze
By selecting different characters many patterns
can be made which may be useful to produce details (through
layering / modulation ?) in generated pixels art for games or
intros with small code / performance cost :
Many tricks could be applied to ramp up the
diversity of the patterns such as colors, spatial distribution
(gradient
noise ?), adding small offset, skewing, layering (with blending
?), shadowing (drop shadow), modulating with logical operators etc.
and combining these methods; random is good enough but specific
patterns distribution (scheme) must be done for more intricate
patterns.
with colors variation (constrained to 4 random
nearest colors), selection of patterns with logical operators /
function (4), can looks like cheap noise (5)
In codegolf context the
characters can also be computed specifically by adapting the code
to the selected characters and applying a transformation (such as a
Reflection),
the character may also be simply taken from RAM, this might be
cheaper.
Note that these characters can also be seen in
many parts of the world historically
when they are scaled up such as elements in Huari crafts /
Andean arts.
another kind of Truchet tiles made of two
quarter circles (with background logical OP fill for fun)
Tool
Here is a TIC-80 interactive experiment which was
used to produce all the images in this article, you can try it online (tool code is
bundled into the cart) :
TIC-80 Code
Here is some LUA code (TIC-80 platform) producing the maze in
the first image of this article :
w=3 -- grid width
h=3 -- grid height
n=w*h -- pixels count
c=2^n -- number of combinations (2 colors)
function cb(i,x,y,d,s,f)
-- s: scale
-- f: skew
for k=0,w*s-1 do
for p=0,h*s-1 do
j=k//s+(p//s+p//s+p//s)
b=i&(1<<j)
if f then -- skew
b=b>0 and pix(x+k+p,y+p-k,d) -- skewing may
need offsetting ? : pix(x+(k-p)//2+s+s//2,y+(p+k)//2,d)
else
b=b>0 and pix(x+k,y+p,d)
end
end
end
end
function TIC()
cls()
-- show full set (all combinations)
x=0
y=0
for i=0,c-1 do
yoff=73
cb(i,x,yoff+y,12,1)
x=x+w+1
if x>=126 then
x=0
y=y+h+1
end
end
-- maze
g={84,273} -- / and \
math.randomseed(0)
for y=0,23 do
for x=0,240/3 do
gi=math.random(2)
cb(g[gi],x*3,y*3,2,1)
end
end
end
The cb function is the character generator, it takes an
index (0 to 511) and plot the content of a character taken from the
set of all combinations of a
3x3 binary matrix, the data is contained in the index and the
character is computed and drawn from there.
The character generator function is also able to
scale (integer factor) and skew the character (45° rotation),
skewing works best when scaled.
A 2x2 binary matrix also works although the maze
example looks more limited.
Dither and smoothing
A way to get more interesting look is to average per tile or
for all pixels, i especially like averaging per tile with a custom
pattern and adding a slight offset to the resulting color, it looks
like cheap dithering :
different averaging methods applied: raw (1),
per tile (2), per pixels (3), with color offset
3x3 Truchet
tiles: raw (1), per tile (2), per pixels (3), no color
offset
same as above with color offset (3)
some more patterns
per tile and by adjusting color offset
(animation)
-- averaging made to be applied for each
tile, it affect tile pixels : 1,0 0,1 2,1 1,2
-- change pattern for different "dither" style
function smooth1(x,y,o)
r=(pix(x,y)+pix(x+1,y-1)+pix(x+2,y)+pix(x+1,y+1))/4
pix(x+1,y,r+o)
r=(pix(x-1,y+1)+pix(x,y)+pix(x+1,y+1)+pix(x,y+2))/4
pix(x,y+1,r+o)
r=(pix(x+1,y+1)+pix(x+2,y)+pix(x+3,y+1)+pix(x+2,y+2))/4
pix(x+2,y+1,r+o)
r=(pix(x,y+2)+pix(x+1,y+1)+pix(x+2,y+2)+pix(x+1,y+3))/4
pix(x+1,y+2,r+o)
end
-- per pixel (applied on all pixels) using a kernel :
https://en.wikipedia.org/wiki/Kernel_(image_processing)
function smooth2(x,y,o)
l1=pix(x-1,y)
u1=pix(x,y-1)
d1=pix(x,y+1)
r1=pix(x+1,y)
cr=pix(x,y)
r=(l1+u1+d1+r1+cr)/5
pix(x,y,r+o)
end
fun result per pixel with the above kernel,
might also be due to boundary handling, looks like stone cracks (1)
or a circuitry (2)
Isometric projection
References
- 10 PRINT, a book about the one-line C64 BASIC program, i especially likes the part which focus on computing history (loosely related to these patterns) such as Jacquard loom, stitch-work, magnetic core memory, textiles and craft from parts of the world and punched card.
- Truchet tiles on Wikipedia
- Shane work on
Shadertoy has some very cool GPU accelerated artworks
back to top