It is common to operate on matrices and pixelmaps by reading and
writing the (i,j)-th element or pixel. There is, however, a dual
approach: rather than manipulate pixels we manipulate functions that
manipulate pixels. The result is surprisingly concise and lucid, let
alone coordinate- and storage-independent.
The pure functional library of texture generators has been used in teaching, of functional programming and of computer graphics. The Clastic web site and the tutorial show many intricate and exquisite textures, described declaratively, combinatorially -- often by an order of magnitude shorter than in the traditional, imperative, pixel-shoving approach. Furthermore, the sequences of combinators can be subjected to automated deforestation based on fusion laws.
The coordinate-free way of describing textured objects reminds one of the coordinate-free formalism of Geometric Algebra and of the General Covariance principle of Relativity (or, the General Coordinate Invariance principle).
Clastic uses programming version of Clean for Windows OS. The examples below are paraphrased in Haskell.
This summary was posted, with a comment, as Re: Not quite enough abstraction on the SRFI-25 mailing list on Mon, 28 Jan 2002 21:10:10 -0800 (PST). That SRFI-25 thread includes Brad Lucier's message urging more abstraction in programming with vectors and matrices.
<http://users.info.unicaen.fr/~karczma/Work/Clastic_distr/clastic.html>
The Clastic Web site (what used to be. Please use Archive.org)
It refers to the tutorial with many beautiful pictures.
f(x,y). A rendering engine passes the function
coordinates of a point and expects in return the color value at that
point. The values of x and y of two consecutive invocations of
f(x,y) are generally unpredictable. The function f(x,y) does not
have access to a pixelmap and cannot examine pixel values. Texture
mapping algorithms belong to the passive category. Such algorithms --
shaders -- are used in animation and ray tracing pipelines.
Clastic is an exploratory tool for passive raster graphics. The tool
can generate regular (geometric) or random textures described as
relationships between 2D points and their colors. In Clastic, a
texture is a function R²→R³: a function from points to RGB color
vectors. The relationship is described purely declaratively.
circle (x,y) = if x*x + y*y <= 1.0 then tx (x,y) else rgb_white (x,y)which creates a circle filled with the texture
tx(x,y) on a white
foreground. However, if we define a texture combinator
fmask h f g = \x -> if (h x == 0.0) then g x else f xand an overloaded function
step x | x < zero = zero
| x > zero = one
| otherwise = half
then we can write the circle as
circle = fmask (\p -> step (1.0 - norm2 p)) tx rgb_whiteor even
circle = fmask (step . (sone .- norm2)) tx rgb_whitewhere
sone p = 1.0
norm2 (x,y) = x*x+y*y
and .- is subtraction lifted to (Float,Float)->Float functions.
What is remarkable about the last circle definition is that
point coordinates do not appear at all. The shader circle is
defined as a pure combination of primitive textures. This
coordinate-free style of programming is strongly encouraged by Clastic.
In Clastic, we transform things rather than coordinates. The
coordinates should be hidden inside higher-order operators such as
translate, rotate, scale; inside primitive textures such as rgb_white;
inside `soft objects' Point->Float such as sone; and inside blending
combinators such as fmask and over.
As the paper and the Clastic tutorial show, combining a few primitives yields surprisingly complex textures such as impressive geometric patterns, tesselations and wallpaper including Escher reptiles, and woven patterns.
Integer->Float functions
with the property that function values do not visibly correlate even for
neighboring arguments. The ``random noise'' generators let Clastic
produce dithering, fractal patterns (e.g., clouds), turbulence, and
more complex marble-like textures and bump-maps.