clastic - greyc · images we mean images resulting of a ... object io subsystem. we modified one...

74
Clastic Texture Generator Package in Clean Version 01.10 User’s Tutorial Jerzy Karczmarczuk University of Caen, France [email protected] October 2001

Upload: dangkhanh

Post on 28-Jul-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

ClasticTexture Generator Package in Clean

Version 01.10

User’s Tutorial

Jerzy KarczmarczukUniversity of Caen, France

[email protected]

October 2001

Contents

1 Introduction 51.1 What is it? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 The structure of the package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.3 Additional Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.3.1 Shortcomings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3.2 The name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2 Interfacing 102.1 Your first Clastic textures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.2 Primitive interface elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.3 More elaborate interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3.1 What can we see on other examples? . . . . . . . . . . . . . . . . . . . . . . . . . . 122.3.2 What does this interface? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 General Utilities 163.1 List utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.2 Numerics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Function algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.5 Viewports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.6 Colours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

4 Basic textures 204.1 Primitives and standard combinators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4.1.1 DSP-style primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204.1.2 Basic transformations and combinations . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.2 More elaborate combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.2.1 Weaving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.3 A few words on optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5 Random Textures 275.1 Basic noise generators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275.2 Noise transformations and combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.3 Fractal noise and turbulence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.4 Random placement of objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

6 Deformations and Mappings 336.1 Some simple truths from the Group Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . 336.2 Deformation is a local transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336.3 How to transform deformers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356.4 General warping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2

CONTENTS 3

7 Textures in 3 Dimensions 387.1 What are they for and how to show them . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387.2 Visualization of 3D textures in Clastic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407.3 Light and bumps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

8 Tesselations 448.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

8.1.1 Small optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458.2 Plane symmetries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

8.2.1 Important entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468.2.2 Wallpaper groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

8.3 Tile generators in Clastic. Unit cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498.4 Symmetry P3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

8.4.1 A simple case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518.4.2 A tribute to Escher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

8.5 Symmetry P3ml: a kaleidoscope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538.6 Parquets PGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548.7 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

9 Differential Structures 569.1 Who needs derivatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569.2 What is Automatic Differentiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569.3 Generalizations and simplifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

9.3.1 A simple example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

A System requirements 61

B Further work and wishes 62B.1 Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62B.2 Redaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62B.3 Interfacing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62B.4 Base layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63B.5 Bitmap handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63B.6 Random stuff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63B.7 Mappings and deformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64B.8 Non-local texturing procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64B.9 Tesselation package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64B.10 Differential stuff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65B.11 General utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

C List of Useful Data Structures and Procedures 66C.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66C.2 General utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66C.3 Function algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67C.4 Colours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68C.5 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68C.6 Basic generators and transformers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69C.7 Mappings and deformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70C.8 Random stuff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70C.9 Tesselation utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71C.10 More math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71C.11 More examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

CONTENTS 4

C.12 Viewing routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Chapter 1

Introduction

1.1 What is it?

Clastic is a collection of functional tools written in Clean [7]. It may be used to synthesize procedural 2-dimensional images [1], and in a lesser extent, to process some imported bitmap pictures as well. By proceduralimages we mean images resulting of a visualization of mathematical algorithms: showing triples of real valuesas colours, depicting the domains of mathematical relations, e.g. showing the interior or the boundary ofa curve, etc. By processing we mean geometric deformations, algebraic manipulations in the colour space,perturbing with noise, adding some 3D effects, etc. In its spirit, Clastic is similar to the system PAN of ConalElliott [10], and we acknowledge with pleasure that some parts of it inspired us, the reader will find in Clasticsimilar functional cliches as in PAN, although the differences between Haskell and Clean type systems aresometimes important. But our system was born and evolved independently, as a part of a complex and generalpedagogical project: the usage of functional tools for image synthesis. The idea of procedural textures iscovered very well by the literature, see already cited book [1], but also [2, 3, 13, 14] and many others.

So, let’s be sincere. We wrote this package mainly for ourselves, without special “public” ambitions,with plenty of personal idiosyncrasies, and far (yet) from any stability. We will be more than grateful forany criticism. In particular: we believe that the package might be useful for some people interested in imagesynthesis, not necessarily experts in the Clean language. But in its current version, if you don’t know Cleanyou will have problems with Clastic. This is a package rather for the developers and experimentors, than forthe final user. This description should be readable by non-specialists in image-synthesis, but who have somebasic notions of this domain, and who have some reasonable mathematical, mainly geometrical culture.

Clastic was meant as a library ofshader modulesfor a ray tracer, written also in Clean (this was a studentproject at the University of Caen, Normandy, France). The tracer works, and will be described elsewhere, Clas-tic is to be used separately. It defines the appropriate data structures, and more than three hundred procedures,but in its current form it is not a collection ofsoftware componentsfor texturing, ready to plug into a fullyfledged, ambitious rendering engine. It is just a collection of generators and transformers.

Clastic isnot a drawing program, but atexturing library. This means that its basic activity as of a texturegenerator is the following: an external interfacing function (rendering engine, testing loop, etc.) provides aPoint in intrinsic texture space; this may require first some mapping from some other coordinate systems.A concrete generator, a function of typePoint→ Colour yields the colour for this point. Points areusuallyreal, Cartesian, and the scaling and truncation when rendering the image in the pixel space is ensured bythe interface, and by the parametrization of theViewport — a virtual window which handles the conversionbetween the texture space and the pixels.

Clastic was written and tested using Clean for Windows (NT, 2000), and the testing interface uses itsObject IO subsystem.We modified one minor thing in the standard package, in the original, theBitmapdata structure is abstract (opaque).We export it from osbitmap.dcl . The details are given in the Appendix(A). The modified fileosbitmap.dcl has been included in the folderExtras . Put it in your Clean I/O

5

1.2 The structure of the package 6

Windows directory.However, Clasticin principle may be used under other operating systems, the package is sufficiently mod-

ular. You may program and generate a texture, and export a bitmap using standard file output. Currently onlyBMP format is supported, but this will be generalized as soon as possible. The actual generators, deformers,combinators etc. are completely platform-independent functional objects. The visual interface is also modular,first a device-independent bitmap (Windows DiB) is constructed in a scanning loop over all the rendered pixels.The result is a byte array, the image of a.bmp file, which may be output by a standard IO routine. Only whenthe user wants to visualize directly on the screen the rendered image, the Windows specific IO is used. This isdescribed further on.

Our main paradigms and objectives were:

1. To exploit the polymorphism and the type class-based overloading in order to define in a generic andvery compact manner procedures which operate upon textures implemented as functional entities of aspecific mathematical flavour. You don’t see what do we mean? You will learn from the examples andtheir style. . .

2. To play with higher order constructs in order to facilitate such operations as generic blending, nesting,combined deformations, tiling, etc. Some other projects are in gestation: generic weaving, and sometextures based on differential geometry.

3. To keep as far as possible a certain independence of concrete Point domain (not only Reals, but alsoelements of algebraically treatable differential manifolds, see sect. (9)). To give the utmost importanceto thegeometric invarianceproperties to objects which manipulate vectors (e.g., transformers). This isimportant from the pedagogical point of view.

4. To have some more creative liberty than provided by better known interactive texture generators, suchas Corel Texture, or SynTex [9] (a very nice, modular package of Synthetic Realms, Calgary, Canada,who offer an instructive evaluation version). Those packages usually offer a predefined set of elementarytextures and limited ways to combine them, but on the other hand they are distributed with many inspiringexamples.

5. To make everything reasonably clear and easy to use. But the package isnot designed to be the ultimatetool for generating textures. This is a pedagogic, experimental work. If you need just some textures,you might waste quite a time to harness Clastic, and it is better to use one of very abundant texturingapplications on the market, or to use the RenderMan shaders [4, 5, 6]. If you want tolearn how tocompose and how to transform textures in a (as far as possible) geometrically invariant, generic way —Clastic may be for you, although the current version isvery imperfect.

6. To rewrite in a compact and universal way several “standard” RenderMan shaders in order to learn whatclasses of primitives and of manipulators are actually used in practice, and should be optimized. Thiswork is starting only now.

7. Finally, we wanted to learn how to construct reasonable, non-trivial GUIs in Clean on a concrete example.

8. And,really, we wanted to write this tutorial describing how to make procedural textures, presenting clas-sical techniques, some less known tricks, covering the geometrical issues such as symmetries, generationof random noise, etc. This task is far from the completion, and we have to underline thatThis text is nota reference manual. Rather, it is a tutorial based on our manuscript lecture notes.

1.2 The structure of the package

This is the first, draft version of the package, a study rather than a finished product. Its identification “01.10”reflects its creation period: year.month. So, its structure reflects its historical evolution, several functions belong

1.2 The structure of the package 7

to inappropriate modules, the name conventions are — to say it mildly — very inhomogeneous, some code isrepeated, and the interface is still awful. The package is autonomous in the sense that it uses onlyStdEnv ,StdLib andObject IO system packages, it contains thus a voluminous collection of small utilities. In fact,is uses also theNotice object from the Gui Utilities which are part of the I/O examples, not of the mainlibrary (Notices are also defined in Peter Achten’s I/O Tutorial; we will probably incorporate a version we needdirectly into Clastic). We put it in the folderExtras .

Everything is exported. The package is composed of following modules, all of them having names whichbegin withCT. . . :

A. CTexture. This is a dummy module which imports all other. Only this one has to be declared in the im-port clause, unless you want to check the examples which are gathered in an independent set of modules.

B. CTGeneral. Plenty of numeric constants (such asDPi or Sqrt2 and other simple numeric routines,basic universal classes (including general vector-like functionalities), and some list utilities.

C. CTUtils . Other mixed routines, for example list sorting. Also, some utilities to plot 1-dim functions inorder to test them. It might (should) evolve one day into a reasonable scientific plotting/visualizationpackage, which we all badly need. We won’t discuss it further.

D. CTFunalg. The overloading of arithmetic to functional objects, some very primitive functionals such asgeneric, domain-independent transformations) translation, scaling), the reduction of argument to a giveninterval (for replicated patterns), some masking etc. Some of these functions should belong perhaps toCTBase.

E. CTVector. Standard 2D and 3D vector routines. Instantiation of overloaded arithmetic, scalar and vectorproducts, rotation, a primitive decomposition of a vector in a non-cartesian system, conversion to polarcoordinates, and that (basic only) stuff that goes together with any 2D geometric-oriented computations.

F. CTBase. This is the foundation of the package, the main “primitive” textures. Transformations oftextures (translations, rotations, etc.), polygons, interpolators, bands/stripes, disks, checkerboards, etc.

G. CTColour . Definition of Real colours— records with real RGB in [0 – 1]. The package uses onlythat; the conversion to standard 3-byte RGB entities is done while rendering. (This might change a bitwhen we complete the sub-package with caching of intermediatereplicatedpatterns; they will probablybe stored as bitmaps). We define here some conversion functions such ashsvtorgb , and procedureswhich handle colour maps and gradients.

H. CTRandom. This module defines a collection of random texture generators, as the name suggests. . .We define a purely functional noise function (Perlin type) in a rather generic way, permitting its usage in1-, 2-, and 3-dimensional case. Scalar and vector noise is constructed. Fractal sums and turbulence aredefined as well. This module needs more work. . .

I. CTMapping . Some typical deformations and 3D mappings (mainly for testing volumic textures). Somegeneral ways showing how to transform deformers (or deform transformers if you are anarchist) areimplemented here.

J. CTView. This is our essentialabstractinterface, the definition of the rendering viewport with conversionfrom real coordinates to integer (pixel) measures. But also some 3D objects are defined here, the abstractcamera, and a “ViewScreen”: a standard focal camera, and its associated viewport. Additionally in thismodule you will find all procedures which handle bitmaps independently of the specific Windows IOprocedures (so, bitmaps are{#Char} arrays which may be read and written to files, no relation todisplay contexts nor handles, although the format used is particular: it is the Windows DiB).

K. CTWindow . This is the Windows-dependent part of the interfacing. Opening windows, some Dialogs,displaying something on Pictures, etc. Plenty of technical stuff.

1.3 Additional Information 8

L. CTMath . A set of mathematical utilities less general than mentioned above. Currently the packagecontains the arithmetic overloading for rational numbers, complex numbers and theAutomatic Differ-entiation stuff which will be discussed in details later.

M. CTTile . This is not the generation of “seamless” textures out of finite chunks, useful as Web pagebackgrounds (abused by nasty people who don’t care about their “clients” eyes. . . ), but some universalmethods of replicating patterns, not necessarily rectangular, with non-trivial “wallpaper” symmetries.The package is far from being finished, but it has some interesting genericity worth seeing. Requiressome, perhaps not so rudimentary knowledge of geometry.

Of course, if you wish generate seamless background patterns, Clastic has plenty of tools, only you willhave to program everything.

This paper describes the package from the user perspective, beginning with a simple user’s guide permitting toproduce a few simple textures, and then passing to the gory details.

All package modules are gathered in a directory Clastic which should be declared in the set of pathssearched during the compilation. It contains a folder with examples, and this documentation.

1.3 Additional Information

Clastic is distributed asthankware. You shouldn’t try to convince yourself that you didn’t read this, that youdon’t understand what does it mean, or that you have forgotten it immediately.

More concretely: the onlyusagerestrictions you should care about, come from the legal status of the Cleanlanguage and its official libraries. Of course, there is also a non-negligible danger of violating some patentsgenerously accorded by the US Patent Office I was not aware of, such as the basic vector algebra, constructionof random number generators, illicit usage of the word “warping”, etc.

This was supposed to be a very bad joke, but after having seen a recent patent granted for an antenna whichemits signals with the speed greater than the speed of light, I am not sure of anything. The US movie and musicstars will soon patent their genetic code, although they are not authors of their DNA (with possible exceptionof Michael Jackson).

And now seriously: you are allowed, and even encouraged to modify these files, and to share them, butnotunder identical names: the nameClastic, and the names of its modules. Please, mark explicitly changedmodules, and choose different names, and then do whatever you wish. Incompatible versions of any multi-module program is a disease which can and should be avoided. . . If you think that your modifications maybe useful for other people, send them to me, I hope that Clastic lives longer than 1 year, and that its possibleupdates have some sense. Anyway I use it for teaching image synthesis, for generating texture examples.

Just to be safe, I declare hereby that I am not responsible for any damage of your computer, your washingmashine, your pancreas or your marriage etc. if you decide to use Clastic for any purpose.

1.3.1 Shortcomings

There are always some things badly done, and some planned (dreamt) improvements are listed in the Appendix(B). But some other shortcomings are difficult to eliminate.

• The package is slow. It is simply not true that Clean speed is comparable with a highly tuned “C” codein such a context. The arrays (accessing, but mainly generation) are slower. Run-time checks elsewhereseem to slow down the speed as well. And, of course, the dynamic memory management has its price.The usage of high-order functions generates some call indirections which cannot be neglected. Class-based overloading is heavily used, and this is also expensive.

• According to the I/O system authors, bitmaps which are output to screen are not garbage-collected,which makes it difficult to make in one run many tests; the memory may get eventually clogged, and theprogram will fail. Perhaps the bitmaps (within the Windows layer) may be somehow reused, but we have

1.3 Additional Information 9

no idea how. For the moment we didn’t have any drastic problems with this. We simply cannot generatetoo many textures simultaneously.

Once more, if you “just” need textures, use other rendering software. Now even POVRay [15] is evolving fastin the direction permitting to plug-in some dynamic shaders.

1.3.2 The name

(This is just to prevent some people from searching dictionaries. . . ) According toThe Concise Oxforddictio-nary,clastic is a geological term, meaning: “composed of broken pieces of older rocks; conglomerate”. Wehope the reader sees the analogy. If not, there is always anex post, sham development of this word asCleanAppliance forSynthesis ofTextures (Ingenuous, andClumsy).

Chapter 2

Interfacing

2.1 Your first Clastic textures

First of all, you would use our simple interfaces, but they are not provided as texture design facilities (thisshall come perhaps later, if somebody is interested), only as testing/display tools. The design begins with theprogramming, the designis programming.

Go to theExamplesfolder, and launch the moduleexample0.icl . Don’t forget thatClastic shouldbe on the compiler search path, and to replace the modifiedosbitmap.dcl file. It shouldn’t harm any otherprogram!

In order to program a texture you should define themainfun function, which is of typePoint→ Colour.The simplest possible texture may be given as

mainfun = const RGreen // Just a green rectangle...

which is rather dull. . . The fileexample0 contains two related examples, which generate the results shownon Fig. (2.1).

Fig. 2.1: Your first textures:xfun1 andxfun2

The functions which generate these images are defined as not too simple, but elementary periodic functionsproducing real values:

xfun1 (V2 x y) = sin(x+sin(y+sin x)) - sin(y+sin(x+sin y))

xfun2 (V2 x y) = floor(sin(x+sin(y+sin x))) - floor(sin(y+sin(x+sin y)))

10

2.2 Primitive interface elements 11

These real values are converted into colours through:

mainfun = interpol RGold RBlue Linear o sscaled 0.1 xfun1

wheresscaled s is a function which expands/shrinks the space textured by the functionT (~x). The call tosscaled s T yieldsT (1/s~x). The operatoro is the functional composition.

We note the following:

• In order to change the window size, or the viewport parameters, you have to recompile the examplemodule. This is not very friendly, although quite easy.

• The interpolation functioninterpol Col0 Col1 Method realArg attributesCol0 to 0, andCol1 to 1. If the argumentrealArg gets outside this limit, you may get strange “negative” results, ashere. It can be useful for you as a pretentious artist, or as a motivation to learn the clamping procedures.

• Periodic functions, especially multi-periodic entities can produce resultsverydifficult to guess.

You may now generate some of your own textures, for example a real (0 or 1) checkerboard, rotated by 0.2 ra-dians:xfun = rotated 0.2 checkers interpolating subsequently any colours you wish, or concentricrings given byxfun = symteeth o norm , wherenorm computes

√x2 + y2 andsymteeth generates

an infinite sawtooth pattern with symmetric slopes. (Choose your scaling factor as you wish, say 0.2). This isjust to show you the basic usage of the texturing functions, the main issue in this section is the interfacing.

2.2 Primitive interface elements

In the moduleexample0 the standard “main” function of CleanStart , called hereTexture is defined as

texturwin "Title string" tecport mainfun

• The functiontexturwin declared in the Clastic moduleCTWindow creates and opens a windowattached to the viewporttecport , which contains the geometric attributes of the texture space, andthe related conversion functions. The window is opened by a standardstartIO SDI Void ...routine.

• This function constructs the “look” function for the window by launchingmakeDib tecport main-fun , wheremakeDib is a function declared in the moduleCTView . It is a loop which uses the viewportgeometry, and constructs a standard, uncompressed BMP image — a{#Char} array with the appro-priate header, and all the pixels. This can be done independently of the windowing procedures, and theresult may be dumped onto a file. The moduleCTView contains the functionwriteBmp which takesthe DiB, the file name and a file-system environment, and writes the bitmap.

• The Device-Independent Bitmap image is fed into thedrawDib function declared inCTWindow, sinceit uses thePicture structure. The result is a!*Picture -> *Picture function which is theWindowLook main work horse. Since the DiB is constructed separately, off-screen, the window regen-eration is simple and fast, the system redraws the bitmap. On the other hand, you don’t see the progress.In a new version we shall include a visual gauge to show something, but updating Pictures pixel by pixelis extremely inefficient.

• The viewport is made through the call

tecport =: mkvport wsize hsize xmin ymin xmax ymax

which constructs aViewport object. This is just a data structure, a record containing the size inthe virtual and in the pixel space, some precalculated scale factors and conversion functions, that’s all.In some unspecified future it may be augmented with some masks, additional buffers facilitating themanipulation of transparency, perhaps some global colour correction functions, etc. For the moment thiswas not needed.

2.3 More elaborate interface 12

2.3 More elaborate interface

We see thus that we need at least the possibility to re-run the program with different viewport parameterswithout recompilation and re-linking. Launch (but read first!) the programexample1.icl in the folderExamples . This will open a MDI interface, permitting to open many windows with different sizes, savebitmaps, and also load bitmaps for visualization.

Please read this text together with the code. We show here some figures, but the definitions are oftenomitted.

There are a few different functions predefined:mfun1 . . . , you may add a few more, or modify the existingdefinitions. The interface supports longer lists. Those functions should define legal textures, exactly as in theprevious example, but you can close a window, open a new one with different geometry, and do whatever theinterface menus permit you.

Open from the menu “File” a “New viewport” dialog, theStandardone (3D Viewports and associatedtextures will be discussed later. In this set of examples this will simply refuse to work). Choose the dimensionsof the window, and the size of the virtual viewport. If you check theSquare option, you will get a squarewindow and viewport, only the right column is read. Choose your function.

The first function is a simple checkerboard. Generate it using default parameters, then check the anti-aliasoption in the menu “Control”, and generate the same texture again. The difference in quality is visible, but therendering is 5 times slower. (See the functionaalias in the moduleCTView ; in a more reasonable packageit should be parameterized in a more flexible way, now it is a simple regular super-sampling with 5 points.) Fortypical tests keep this option desactivated.

Make some textures, save them on the disk, and verify them by loading the bitmaps back from the disk.For the moment this “Control” option recognizes only BMP files, and does not permit any manipulation of theloaded images, but you can use it as a primitive previewer of BMP files on the disk.

Attention! As you see, the list of textures within the functiontextureset is not just a list of functions,it contains mnemonic titles, and the texture generators are tagged byT2, they are objects belonging to aspecial typeTexture , whose instances may be also 3D textures tagged withT3.

2.3.1 What can we see on other examples?

1. The second texture is a mathematical relationr < 1.2 + cos(9φ), where(r, φ) are the polar coordinatesof a point. No Boolean condition is explicitly used, but the functionstep (theθ function of Heaviside)useful to delimit the interior of closed implicit curves. Most geometric patterns will be constructed usingsuch primitives.

Let’s underline the fact thatimplicit representationof graphical entities is not only natural for somespecific style of modelling [12], but is natural for the texturing as well.

2. The next one is the contour of this flower. This texture is an example of usage of the Automatic Dif-ferentiation algorithm;contour computes the gradient of a function, and shifts the region boundary(the curve) by a specific amount in the direction of this gradient, which is of course orthogonal to thecurve. A simple subtraction produces the zone near the original curve. The rendering is slow. In general,we implemented the AD stuff for fun and experiments (and its elegance), but in the texturing contextprobably the brutal numeric approach may be sufficient (if well parameterized).

3. Next three examples illustrate some random noise generators.

• The basic 2D noise functiongrnoise2 (gradient Perlin noise [13, 14], described later) is quitedull, shown on Fig. (2.3) at the left (this does not belong to the examples in the code). However, ajudicious usage of a colour map produces the example on the right. This may be further modifiedusing e.g. displacement maps discussed later, here we just took the standardgrnoise2 whichproduces real values about 0, rescaled it by a large factor (10), took the fractional part of theresult with the asymmetric sawtooth functiongfrac , and interpolated the colours. This is a fairlygeneral, commonly used technique. See the result on Fig. (2.3).

2.3 More elaborate interface 13

Fig. 2.2: Interior and contour of a curve

Fig. 2.3: Basic noise

• The functionturbulence2 n κ ω0 constructs the fractal “positive” noise with the formula

t(p) =n∑i=1

(12

)κ ∣∣η(2iω0)∣∣ (2.1)

whereη is the basic noise function. You can produce many interesting patterns with this and similarcompound noise functions. here we passed it through a simple non-linear transformation in orderto generate some simple clouds, as shown on Fig. (2.4).

4. The last example shows the usage of external bitmaps (e.g. photos) as textures. An image is read, andconverted into a texture function. In order to do that you must define some fake viewport for it, anddefine the default background colour outside the bitmap in the virtual space. This is very imperfect, weshould have used some kind of masking, alpha (transparency) channel, etc. Stay tuned.

Once the conversion done, the texture generated from a bitmap can be used as any other. In the currentversion only the bi-linear interpolation of pixels is operational, which means that you should not try todistort the bitmap too much, otherwise the quality loss will be big. You can do something anyway, e.g.use the lense distorter (discussed later), as on Fig. (2.5) at the right. (Please don’t show this to my

2.3 More elaborate interface 14

Fig. 2.4: Turbulent textures

daughter, otherwise my life will be in danger. . . ) In future we must implement the bicubic interpolation,and — more important — some filtering routines.

Fig. 2.5: Images as textures

2.3.2 What does this interface?

TheStart function istxdialog textureset , wheretextureset generates a list of pairs: (mnemonicname, tagged texture function). A texture function is specified as previously. The generatortexturesettakes World as its argument, which permits to open some image files in order to construct the appropriatetextures. The functiontxdialog , defined inCTWindow starts a MDI interface, and passes to the local stuffthe texture set, and some Identifiers. It constructs also alocal process statewhich contains a private list of openwindows, or rather a list of descriptors which contain the windows Ids, and references to the stored bitmaps,which permits in such a way to save them on disk.

The texture creation dialog imports the default viewport parameters fromDefaultpars defined inCTViev .It should be coded in a more clever way, e.g. keeping the last user specifications in some other part of the localstate. The rest is a fairly standard GUI stuff, but the code is so untidy and spaghettious that we recommendvividly to read it and to understand it, in such a way your soul will get some bonus in the Purgatory.

2.3 More elaborate interface 15

We pass now to the description of some accessories and to the general mathematical framework of the package.

Chapter 3

General Utilities

Not all procedures defined inCTGeneral and other auxiliary modules have direct relation to texturing. Someof them are there because we needed them for testing or for experiments. E. g., we borrowed from Haskell agenericShow class in order to convert all kind of stuff into Strings, and to output a combined String in a moreefficient way than just by concatenation (although in a lazy language this might not be a big economy). Fortypes – members of the classShowwe defineshow, more or less equivalent totoString , andshowS x swhich convertsx to string, and concatenates the result with the strings . This avoids the concatenation whencombining many partial results.

We have also some generic manipulators of composite data structures: generalized mapping and “zipping”facilitating the application of component-wise functions to vectors, or to construct some folds.

class fmap t :: (a->b) (t a) -> (t b)class fzip t :: (a a->a) (t a) (t a) -> (t a)

However, the bulk of the moduleCTGeneral is devoted to some numeric goodies. More specific math canbe found in the moduleCTMath, which contains among other things the arithmetic of rational and of complexnumbers. This will not be discussed here, but we want to underline:we tried to define most of numeric stuffin a way independent on actual numeric domain. This means that in several procedures the Real constantsare hidden withinfromReal x . The genericity of the package is improved, but it costs some speed.

3.1 List utilities

Lists are of limited usage in the package. We needed such generators ascycle (standard in Haskell) inorder to construct “infinite” colour maps, and such functions asmap2 mapping functions over a list of lists (arectangular grid), useful for some (not ready yet) discrete operations on textures, and for the generation of 3Dparametric surfaces, which belong to another package, in construction. The moduleCTUtils contains thequicksort and binary tree sorting procedures useful here as well, sometimes better than the merge-sort routineincluded in the standardStdOrdList module.

The arithmetic:+,−, ∗, / is overloaded, defined for lists element-wise. This is useful for the manipulationof n-dim vectors which exploit lists.

This collection will grow, but we don’t want to put here irrelevant procedures which too often pollutelibraries of list-processing utilities.

3.2 Numerics

The “numerics” is not so numeric. . . An important place is given to anabstract algebraic layer. We definethe operator (Constructor class) (*>) which multiplies a scalar by a vector (belonging to a space spanned onscalars of this type). Also the division of a vector by a scalar(>/) is defined as a class.

16

3.3 Function algebra 17

Such polymorphic entities are defined:

class norm2 t :: (t a) -> a | *,+ anorm :: (a !b) -> !b | * , + , sqrt b & norm2 anorm x = sqrt (norm2 x)normalize :: (a !b) -> a b | >/, norm2 a & *,+,/, sqrt bnormalize v = v>/norm v

as well, as generic scalar product and projections:

class (<.>) infix 9 t :: (t a) (t a) -> a | *,+ a

axproj :: (a !b) (a !b) -> a b | *,+ b & *>,<.> aaxproj n v = (v<.>n) *> n

perp :: (a !b) (a !b) -> a b | *>,<.> a & * , + , - bperp n v = v - (v<.>n) *> n

which should work for any, 2D or 3D vectors, based on any scalar domain. This avoids a substantial codereplication and increases the readability.

Common numeric constants as 0, 1, 2, 1/2 and 3 are made polymorphic under such names (what a sur-prise. . . ) aszero andone — present already in the standard clean libraries, to which we addhalf , two ,etc. In such a way a “clamping function”, the constrained linear interpolator:

clerp v0 v1 t | t<zero = v0| t>one = v1= (one-t)*>v0 + t*>v1 // or v0 + t*>(v1-v0)

becomes polymorphic. There is a small problem with such a style: the basic domain (Reals), although obvi-ously a Vector Space, cannot be used as such here, the operator(*>) won’t compile. The solution might begiven by multiparametric classes with functional dependencies, but we have to wait a little bit for that.

The “abstract” numeric layer contains other goodies: a generic linear iterator which appliesn times anoperator to a value, a generic dichotomic iterator for associative operators permitting to construct the powerfunctionxn with logarithic complexity inn, etc. The functionatan2 useful for computations in polar coordi-nate systems is overloaded as well.

There are some integer utilities such as the Extended Euler algorithms, and also some (usually) real func-tions, e.g. the Hermite interpolatorh(x) = 3x2 − 2x3, defined of course in an overloaded style.

3.3 Function algebra

The arithmetic operations are overloaded in the domain of functions. The package contains a full plethora ofsuch definitions:

instance + (a -> b) | + bwhere

(+) f g = \x -> f x + g x

instance one (a->b) | one bwhereone = \_ -> one

instance fromReal (a->b) | fromReal bwhere

fromReal c = -> fromReal c

3.4 Vectors 18

etc., and a number of functionals which modify their function argument by acting on the argument of the latter,e.g.,

translated a f x = f (x-a)scaled c f = \x -> f (x/c) // Just to vary the style a bit

All this is quite simple, the only interesting feature here is that due to the overloading of arithmetic operationsthese functionals:translated or scaled may act not only on scalars, but on any vectors. Admittedly,overloading the division (coordinate-wise) for vectors is a little bizarre, but harmless.

The user code may be quite compact, and written in a combinatorial style. For example, in order to replicatef(x) from the interval [0–1] to the entirex space, you may writef o gfrac , wheregfrac computes thefractional part of a numeric object (more general than a Real). Such composition is predefined in the packageastrain f ; there are also other replicators.

Not everything from the world of numbers can be easily overloaded to functional objects. The relations(<) etc. according to their official signatures yield Booleans, and they cannot return functions. But computingthe minimum or maximum of two functions as functions is fairly useful, we define thus

minf f g = \x -> min (f x) (g x)maxf f g = \x -> max (f x) (g x)

The names have been changed, because the standard definitions:min x y :== if (x<y) x y are notapplicable. We will need our functions to define some masking functionals, for exampleposit f = maxzero o f cuts out the negative values returned by a function.

3.4 Vectors

We shall use principally 2- and 3-dim vectors, structures of types

:: Vec3 a = V3 !a !a !a:: Vec2 a = V2 !a !a

and a reasonable set of operations acting upon: arithmetic, scalar and cross products, projections, rotation,decomposition into coordinates in a non-cartesian system, conversion between cartesian and polar coordinates,etc. We have some useful constants, such asX2axis etc., and linear equation solvers, with matrices repre-sented by tuples of vectors.

The domain of vector elements is usually the real axis, but — we underline it again — the generality issuch that almost all library functions work with vectors containingdifferential scalars, objects permitting tocompute very easily all the gradients, defining such functions ascontour , constructing shaded 3D reliefs,etc.

Most textures are defined on vectors, and it is recommended to use the invariant notation, avoiding theseparation of arguments into coordinates. The code is much proper and less bug-prone. For example, therotation of a vector~u about a (normalized) axis~n in 3D does not need matrices, but is based on the followingobservation, which yields the Rodrigues formula:

• In 2D the rotation is given by(xy

)→(x′

y′

)=(

cos(α) − sin(α)sin(α) cos(α)

)(xy

)(3.1)

or: x′ = cos(α)x− sin(α)y; y′ = sin(α)x+ cos(α)y.

• In 3D we begin by separating the vector~u in a component parallel to~n: ~u|| = (~u ·~n)~n, and the remainingpart, perpendicular to the axis:~u⊥ = ~u− ~u||.

3.5 Viewports 19

• The parallel component remains invariant under the rotation, and the perpendicular one remains in itsplane orthogonal to the axis; the problem became 2-dimensional. But we don’t have (rather: we don’twant to use) a concrete coordinate system, so we use the vector itself as the “x” component, and findanother one by~u3 = ~n ∧ ~u.

• The result is:~u|| +(

cos(α)~u⊥ + sin(α)~u3

).

3.5 Viewports

As mentioned already, the textures are constructed in a “virtual” space, mapped into pixels at the last possiblemoment. This virtual space is based on Reals, without any genericity. We define the structure

:: Viewport = {width::!Int,height::!Int,xmin::!Real,xmax::!Real,ymin::!Real,ymax::!Real,xscale::!Real,yscale::!Real, vpix::(!RVec2->Point2),...

}

See the details inCTView . The texturing area is defined byxmin –xmax, ymin –ymax. These, and the ren-dering windowwidth andheight are only input attributes. The scales:w * (x-xmin)/(xmax-xmin)etc., and the remaining parameters — various conversion functions, are precomputed during the creation of theviewport.

We introduce this structure here, because in concrete texturing applications the user may need somethingmore: the position of a camera in 3D, some default lights, some specific (e.g. hyperbolic) mappings, somemasks or colour transfer functions, etc. It is recommended to gather all these information in one data struc-ture. On the other hand it should be fairly independent of the rendering process, of system-dependent windowattributes etc. The 3D layer will be discussed later.

3.6 Colours

The standard Clean I/O system operates upon colours (datatypeColour ) defined as 3-byte RGB records. Weuse real colour components, and we predefine several constants, such asRBlue , Red, RGrey, RDark-Green , etc. Colours are generic records:

:: RealCol a = tr::a,tg::a,tb::a

which makes it easier to compute gradients in colour space, but for the moment this genericity is not exploited,we use Reals.

Colours constitue a vector space: they can be added, multiplied by a scalar, interpolated, etc. There aresome functions permitting the conversion between RGB and HSV, and some other utilities, such as saturationroutine, etc.

Chapter 4

Basic textures

4.1 Primitives and standard combinators

The basic principle of shader construction is the same as everywhere else in software construction: buildreusable blocks, combine them together, avoid explicit multi-branch decisions, put related entities together,etc. In the discussed context typical imperative constructions are far from ideal, and if you read the sources ofsome RenderMan shaders, you will see that it is not easy to exploit the work done by others. But you will learnalso some basic combination techniques which we have adopted as well. A word of warning: the methodologypresented below economiseshuman, not computer time. If one day you will need to generate very efficientlymany textures, even in real time for an interactive animation, you will have to optimize everything, but you willknow alreadywhatshould be optimized.

We have seen already that the separation between the interior and exterior of a closed curve givenimplicitlyas the solution off(p) = 0, where positive values are assigned to the interior, is provided by theθ (step )function of Heaviside, e.g.step o (one - norm) generates the unit disk:

√x2 + y2 < 1. Of course, a

consciencious user will writenorm2 (x2 + y2) rather thannorm , the square root here is useless. Plenty ofother functions which belong to the standard panoply of DSP (Digital Signal Processing) packages are definedin the package.

4.1.1 DSP-style primitives

Sincestep etc. are often used shifted, the package provides a parameterized version of it,xstep a : θ(x−a).We have the parameterizedsmoothstep a b which yields 0 for the argumentx smaller thana, 1 for

x > b, and uses the Hermite interpolator (3t2 − 2t3) for t = (x− a)/(b− a) between 0 and 1.The functionpulse filters (attributes 1 to it; zero outside) the interval [0–1], andxpulse a b — a more

general domain. Fromsmoothstep we may constructsmoothpulse by subtraction, and sometimes it isuseful to use a continuous, piece-wise linearfilteredpulse block:

filteredpulse c0 c1 dx x= max zero ((min (x+dx) c1 - max (x-dx) c0)/(two*dx))

(This last function is used in some RenderMan shaders.) In general, discontinuous functions may be verycumbersome when computing gradients, and for the visual comfort one may introduce also some smoothinginto piece-wise differentiable functions, defining for example:

filteredabs dx x= if (dx<x || x< ~dx) x (half*(dxh+x*x/dx))

Periodic functions may be constructed — as already mentioned — by taking the fractional part of the argument.If we need something more symmetric, we might usesymtrain defined and plotted below. Of course nothingprevents you from using trigonometric functions.

20

4.1 Primitives and standard combinators 21

Here we see some plots of primitive blocks, and periodicity generators:

ramp = max zero o min one

sawtooth = pulse*id

filteredpulse

smoothpulse

trainpulse

symteeth = symtrain abs

There is no need to supply the package with hundreds of such functions, they can be constructed very easily.They are 1-dimensional functions, and in order to use them as textures we might use predefined lifters such as

xstripe f = \(V2 x _) -> f x

and its partnerystripe , which generate horizontal or vertical bands. In order to get something more compli-cated, the primitives may be combined, or used in a sufficiently sophisticated way. For example, the followingdefinitions generates (differently scaled) checkerboards:

yetanotherchecker (V2 x y) = step (sin x * cos y)morecheckers (V2 x y) = abs (trainpulse x - trainpulse y)

and the only requirement demanded from the user is a bit of geometric imagination, as always. . .

4.1.2 Basic transformations and combinations

We mentioned already thetranslated transformer which shifts the argument of a function:translateda f x = f (x-a) . In general, one rule must be respected in these transformations: they actcontravari-antly on the texture argument. If you want to rotate left a texture, apply its generator to the argument rotatedright. The scaling by a scalarc divides the texture argument by it.

This means that for general transformations (especially local deformations) the situation is difficult, wehave to find theinverse transformation applied to the argument. More formally, ifζ(~p) represents the texturerendering, with~p being the current point, and if we wish to apply a transformation (e.g., a rotation)R, theresulting texture is obtained through

(Rζ) (~p) = ζ(R−1~p)

(4.1)

The generic layer of the package contains thus only the simple transformations: translations, scaling, rotations(with some special rotations by 45, 60 or 90 degrees defined separately for efficiency), and transpositions. Wehave e.g. a generic disk centered anywhere and with any radius:disk cntr r2 = step o (fR r2 -translated cntr norm2) , wherefR is just an abbreviation for often usedfromReal .

There exists also the primitive tiling functionalreduced which takes fractional parts ofx and ofy, andthen applies the texture generator. Often more complicated manipulations are needed, but we shall come tothem later.

There aren’t any specific “texture combinators”, all functional compositions can be used. The simplest2-dimensional “Constructive Solid Geometry”, i.e., Boolean combinations of objects: union, intersection, etc.depends on the representation of objects. If thestep function is used to assign every object its characteristicfunction, the producta · b gives the intersection of two objectsf andg at the point~p, wherea = f(~p), and

4.1 Primitives and standard combinators 22

b = g(~p). The union results froma+ b− a · b, and the complement is simply defined ascomplement tx =one-tx .

We may use also decisional masks. The package contains such functions:

cmask c u v = if (c<>zero) u vfmask h f g = \x -> cmask (h x) (f x) (g x)

Sometimes it is more natural to operate with objects defined implicitly byf(~p) ≥ 0. Then the union is given bymax f(~p) g(~p) (it suffices that one value is positive to be inside the object), the intersection usesmin (only ifboth are positive, the outcome is positive), and the complement is the negation. This is a well known techniqueused in the implementation of 3D CSG objects. Because of this freedom of representation, the appropriatecombinators are not included in the package; they can be defined by 1-liners adapted to users’ needs.

As an example we shall construct a regularn-star. The technique presented below is conceptually extremelyeasy, but the rendering is rather slow, don’t use this model in a serious work. The Fig. (4.1) shows first a wedge

Fig. 4.1: A star is born

constructed as the union of two half-planes. Everything is defined here:

lspace (V2 _ y) = (step o ~) y // Lower half-plane

intersect = foldl (*) oneunion = foldl (\x y -> x+y-x*y) zero

wedge alpha = translated (V2 0.0 0.5)(union [rotated alpha lspace,rotated (~alpha) lspace])

which gives the result at the left of Fig. (4.1). At the right we see the result of iterating the intersection betweenrotated wedges:

star n alpha# wd = wedge alpha# beta = Dpi/fromInt n= intersect (map (\k -> rotated (fromInt k * beta) wd) [0 .. (n-1)])

A bit faster solution would be to apply the texture generators first, and then compose the values at a givenpoint. A muchfaster solution, which we leave to the reader (for the moment), consists in finding the angle inthe polar representation of the current point; for each angle there exists one straight line (with two possibleslopes wrt. the central ray passing by the current point) which delimits the star. We shall return to this strategyin the section devoted to tesselations.

4.2 More elaborate combinations 23

Fig. 4.2: Yin-Yang pattern

We end this section showing how to generate the oriental pat-tern shown on Fig. (4.2), which can be considered as an appetizerfor more complicated symmetry considerations. The followingfunction

c2symmetry trf ax tx p=cmask (step(ax<.>p)) (tx p) (trf(tx(~p)))

is an central symmetry transformer written in invariant fashion. Ifthe current point (vector) and the axis point in more or less similardirection (angle between them is less than90◦), then the textureis applied, otherwise this texture is transformed, and applied tothe inverted point. In our case the additional transformation is thecomplement. Here is the definition of the texture:

yinyang tx1 tx2 bg# yin = posit (unitdisk - disk (0.5*>Y2axis) 0.25)# yang = c2symmetry complement X2axis yin= fmask unitdisk

(fmask yang (const tx1) (const tx2))(const bg)

and, as we see, it is used in:yinyang RBlue RRed RWhite .Since this is a tutorial, and the main problem in the generation of procedural images is the human imagina-

tion and experience, we pass to a few less obvious examples.

4.2 More elaborate combinations

A simple radial gradient function, e.g.0.8− 0.9√

(x+ 3.2)2 + (y − 2.8)2, coded as

g = fR 0.8 - fR 0.09 * translated (V2 (-3.2) 2.8) norm

may be used to simulate a matte sphere, as we see on the left side of Fig. (4.3), where it is masked by a disk ofradius 5.

Fig. 4.3: Halftoning

But the same function may be used differently, it modulate a highly periodic function (dense checkerboard-like pattern) in the following way:

4.2 More elaborate combinations 24

hftone p=:(V2 x y) = sin(omega*x)-cos(omega*y)+2.0 - 4.0*g p

whereomega is sufficiently big (say, 30). This function yields positive results when the peaks of the periodicpatterns are greater than the appropriately scaled “density”g, otherwise it is negative, and can be masked out.

The function:

gmod = fmask disk5(cmix RBlack RWhite (one - step o hftone))(const RWhite)

generates the halfone pattern at the right of Fig. (4.3). The possible variations are very numerous, you mayuse different grid functions (e.g. hexagonal), use three slightly shifted grids for three colours, and use a bitmapimage as the density source in order to produce a coarse, halftoned “newspaper style” texture (and make someugly T-shirts out of it), etc.

Fig. 4.4: Hexagonal masking pattern

Oh, you don’t know how to make hexagonal pattern, such asthis on the Fig. (4.4)? This is not too difficult, you need only toproduce a checkerboard-style, periodic pattern in a non-cartesiancoordinate system. The pattern shown has been obtained by thefunction

tsfun (V2 x y) =symteeth (2.0*x) +symteeth (x+Sqrt3*y) +symteeth (x-Sqrt3*y) - 1.5

where the additive constant, here 1.5 specifies (through thresh-olding) the size of the dots, it should be replaced by the densityto be modulated, and the functionstep should be applied, aspreviously.

We acknowledge having borrowed the tricks above from anice piece of software:GrafEq of Pedagoguery Software [11],

a package very helpful for the visualization of mathematical relations.More complicated examples of non-trivial symmetries and pattern replication we shall see in the section

(8), we show now how to make simple “weaved” motifs.

4.2.1 Weaving

As elsewhere, we want to develop some universal, generic tools rather than just produce some concrete patterns.The structure we discuss is considered to be discrete rather than continuous, but its rendering is a standard realtexture.

The model is a simple “loom” with a “canvas” containing vertical threads, stripes of any colour (or morecomplex texture structure), and a set of horizontal threads which are going to be interlaced with the threads ofthe canvas. We might complicate it, construct some fabrics with hexagonal symmetry, use specific topology forring armours or baskets, etc., but there is no place for such details in this tutorial.

Our virtual loom has to consider the following details:

1. The colour assignments for the threads. We shall use two lists, horizontal and vertical, rendered “infi-nite” in both directions by appropriate periodic indexing functions (rather than using laziness in order toconstruct cycles).

2. The topology of the fabric, or the interlacing order. This will be represented by a functionΓnm whichdepends on vertical and horizontal indices, and takes the decision which thread: horizontal or verticalshould be visible (masking the other one). In our case a two-valued function suffices, ourΓ (calledloomin the weaving procedure) returns a Boolean.

4.3 A few words on optimization 25

Fig. 4.5: Weaving

3. The geometry in real texture space: the width of threads and of the empty space between them. Fig. (4.5)at the left shows a simple checkerboard interlacing with two vertical and three horizontal threads. Eachthread together with his empty part has width equal to 1.

4. The decorations; the background texture, the texturing of the threads, and special effects near the crossingedges, such as on Fig. (4.5) at the right.

Fig. 4.6: Darkening mask

This last effect needs the introduction of some specific masks whichchange the colour of the neighbourhood of a thread, but without touchingthe background. We use the mask shown on Fig. 4.6. If the width of theparabolic section is zero, the mask is switched-off.

Clastic defines a generic interlacing generator:

modinterlace (row_mod,row_edge,col_mod) n m= row (m + n pmod col_mod)

whererow m = m pmod row_mod < row_edge

which called with parameters (2,1,2) generates the simplest even-odd interlacing pattern, and with (4,2,4) —a Scottish Tartan pattern. As we have already mentioned, thread sets are represented by lists of textures,e.g.,[CYellow,CRed,CBlue] whereCYellow = const RYellow is a texture function returning aconstant colour.

The rest is the user imagination. On Fig. 4.7 we show two weaving patterns in details, and a Tartanbased on some simplified Stewart of Galloway pattern. These examples are included in the fileexam-ples/example2.icl , and the weaving procedures are gathered inside the moduleCTExamples .

4.3 A few words on optimization

• A shader may execute sometimes very complicated operations, and thefundamentalissue is to avoid tocompute for each pixel quantities which do not depend on the current point. The RenderMan shaderscontain specific type qualifiers:uniform which means that the declared quantity remains the samefor all pixels (or rather: texture space coordinates), and a reasonable shader compilershouldpermit itspre-computation.

We don’t need a special compiler tricks, since a decent functional language permits easily the construc-tion of closures. So, we may define

4.3 A few words on optimization 26

Fig. 4.7: A loom at work

textgen cpar1 cpar2 ... = fxwhere

... constant computations

...fx point = ...

or something similar. With some experience one applies such style almost automatically.

• Another place where serious economies remain hidden is to avoid computations which are bound to fail.This is an issue very well known in 3D modelling. If an object: a 2D texture item, or a 3D surface issmall wrt. to the modelling/texturing space, but fairly complicated, i.e. its implicit procedural descriptionis costly, it is useful to enclose this object in abounding boxor bounding sphere(disk).

If the current point is found to be outside the bounding volume, the actual generator is not launched atall. We will use that e.g. to optimize a regular star pattern.

• Finally, for dense replications of complicated patterns it might be interesting to introduce some cacheor memoizing mechanism. We are working on it. We will have also to convert several functions intomacros.

A lazy functional language is full of traps for a beginner. A potential user should know how to enforce strictness,how to avoid redundant pattern matching, etc. No place to discuss all that here.

Chapter 5

Random Textures

5.1 Basic noise generators

Most practically used textures are irregular. Wood, stone, water surface, human or animal skin, etc., all thisrequires some degree of randomness, often superposed on regular patterns: brick walls, “realistic” tissues,dusty windows, etc. We shall need several different, often quite complex random patterns, and differently used:introducing colour variations, deforming the contours (displacement maps), placing randomly some objects,etc. The basic layer is rather simple; most random noise functions used in typical shaders are based on the s.c.Perlin’s noise, a pseudo-random function with narrow spectrum (bumps and valleys of similar size). How is itobtained?

The basic algorithm which made the fame of Ken Perlin consists in generating a sufficiently long list ofrandom numbers, and storing them in an array. The array corresponds to the texture space: 2-dimensional for2-dim. textures, 3-dimensional for volumic noise, etc. The set of indices of a given element corresponds to apoint with integer coordinates. In order to obtain a value for any point with real coordinates, an interpolationof nearest neighbours’ values is used. If just real values are interpolated using some smoothing function, e.g.the Hermite polynomial, the noise pattern reflects too much the shape of the lattice; there are visible “square”artefacts. Perlin attached to each integer vertex arandom vector, and interpolated scalar products of it with thevector describing the point in its elementary lattice cell (square, cube. . . ). The result is presented on the Fig.(5.1), at the left. The width of the textured zone is 12 units.

Fig. 5.1: Perlin’s noise and its “relief” visualisation

At the right we see the same noise, but viewed as a bump-map shading. The noise is treated as a height-

27

5.1 Basic noise generators 28

field. Using our AD package we computed the normal to the surface, and added some light. The details aredescribed in the section (9). We see that perhaps the basic noise is not ideal, the “edges” between peaks arelong and omnipresent, while we should expect many isolated peaks as well. But nobody (and only nobody) isperfect. . . If you look well you will see also some small artefacts at the edges of cells, coming from the factthat in these regions the interpolated data switch.

We decided not to use precomputed random numbers stored in arrays, but to use apure function whichbehaves very irregularly, without visible correlation between values returned for neighbouring arguments (in-teger, of course). The behaviour of that kind, where the result of a process does not depend “reasonably” onits input, but is very unstable, and exhibits everywhere irregular fluctuations, is known in physics asergodicity.The trajectories of non-linear dynamic systems are usually ergodic, which makes it very difficult or impossibleto predict its future behaviour, but permits to use statistical reasoning. In fact, the thermodynamics is a nice,deterministic theorybecausethe underlying microscopic dynamics is crazily ergodic.

We tested a few functions, finally we discovered that the function chosen by Hugo Elias in his noise tutorial[14]

ergodic n# n = (n<<13) bitxor n= toReal((n*(n*n*15731+789221)+1376312589) bitand 2147483647)

/ 2147483648.0

is very reasonably crazy. The results are in the interval [0–1], but Clastic contains a few other similar functions,differently parametrized, and returning values between -1 and 1, etc. For those readers who doubt that thisfunction is really ugly, we have the Fig. (5.2), which displays the values forn from 0 to 200.

Fig. 5.2:

Now we have to interpolate such a noise for real coordinates, as shown on Fig. (5.3) for the 2-dimensionalcase.

Fig. 5.3: Constructing Perlin Noise

Using the basic ergodic noise we attach a random vector~ri toeach integer vertexPi of a unit lattice cell. Four scalar products(Q − Pi) · ~ri are computed, and the result is its weighted sum.The weight functions are not Hermite cubics (3x2 − 2x3) as inthe original Perlin algorithm, but more smooth quinticsq(x) =10x3 − 15x4 + 6x5, having the properties:q(0) = 0, q(1) = 1,q′(0) = q′(1) = q′′(0) = q′′(1) = 0. The vanishing of secondderivatives is necessary in order to have smooth gradients of thenoise function at the edges of unit cells.

In principle this is all. In practice we have a few more noisefunctions, e.g., 2- and 3Dvectornoise which permits to generaterandom displacements of texture elements. The implementationis similar to the scalar case.

5.2 Noise transformations and combinations 29

5.2 Noise transformations and combinations

You can do whatever you wish (including differentiation) with the noise functions. Even a dull, featureless,basic noise within a small region (dimensions of order 1) can give interesting patterns, if a sufficiently sensitivecolour map is used. This is our function, which uses the basic noise functionnoise2 (a scaled and shiftedversion ofgrnoise2 which produces positive values only)

wnoise p# r = 12.0 * noise2 p= interpol RDarkBrown RLightBrown Hermite (gfrac r)

Fig. 5.4: Some random textures

On Fig. 5.4 we see the result of this transformation, followed by an even simpler usage of the random generator,which needs only ergodic noise on integer coordinates. The “Truchet” pattern is a random mosaic obtained bychoosing one random number within each unit cell, and using it to choose a simple geometric pattern, or itstranspose. They are defined inCTExamples , and used inexamples/examples2.icl .

Much more interesting forms are generated if we sum the contributions of noise functions with varyingfrequencies, which generates a “fractal noise”, or “turbulence” discussed in the next section, but even withoutthis summing, we can choose a big scaling factor in order to have unit cells comparable to pixels, and constructin such a way a 2-dimensional white noise, which can be used e.g. to dither any density function, for examplea texture produced by an image, as we see at the right of Fig. 5.4. Full details of this “complicated” procedurethe reader will find as the 8-th item in this set of examples. The dithering procedure is just:

dither factor tx p# r = grnoise2 (factor*>p) + 0.5| tx p > r = RWhite= RBlack

and it is easy to see what is needed to augment the number of spread colours, or to change the ditheringresolution.

5.3 Fractal noise and turbulence

This is an extremely important category of noise functions, used to simulate all kinds of “natural” phenomena,which are known to be multi-scale, possessing wide spectra of spatial frequencies.

The “fractal sum” noise is defined by

F (~p) =n∑i=0

(12

)iκη(aiω0~p

)(5.1)

5.4 Random placement of objects 30

and the “turbulence” replacesη(. . .) by |η(. . .)|, whereη is the standard noise function, anda is the “lacunarity”factor, usually about 2 (slightly different, in order to avoid some periodic artefacts enhanced by the fact that thebasic generatorη is seldom ideal. The number of octavesn varies usually between 4 and 10, andω0 is chosenaccording to the texture scaling wished by the user.

Practically, our generator in the moduleCTRandomincludes in the summing loop an offset of~p whichvaries between octaves, in order to avoid spurious correlations. Some researchers propose other “randomiza-tion” techniques such as rotations, etc., but we are not trying to build the best noise generators in the world. Wemust admit that in the current version the generators are awfully slow, it takes several seconds to generate evena 250x250 turbulent pattern, and when we want to compute its gradients using the Automatic Differentiationroutines, the time is multiplied by 4.

Fig. 5.5: Fractal noise and turbulence

On Fig. 5.5 we see an example of a fractal noise, called sometimes “plasma clouds”, although the nickname“plasma” (which has nothing to do with the meaning given to this word by physicists) is usually linked withthe recursive subdivision algorithm. For texturing that algorithm is less appropriate than the spectral techniqueused here, because of its non-locality.

At the right we see a turbulent pattern, with the same number of octaves (6), and the fractality exponentκequal to 0.8. Some filamentary structures are clearly visible. More filaments can be obtained by enhancing thecontrast, or, more generally, by the usage of an appropriate colour map. Turbulence can be used to generatelightnings or other electric discharges, and to hundreds of other textures, as advocated by Perlin.Some interesting effects can be obtained by applying non-linear transformation to turbulent noise, we have seenalready how to make hmmm. . . almost realistic clouds. We will see later some more random, wide spectrumnoise examples used asdeformation generators. Fig. 5.6 shows the same noise functions as previously, butpassed through the gradient machinery in order to visualize them as 3D profiles.

5.4 Random placement of objects

For a “local” generation protocol, the random placement of an object bigger than a point is not natural. Butrandom scattering of some graphic objects on the texturing zone is a useful technique, so at least one simplemethod should be discussed here.Clastic implements a method called “bombing”, which is a variant of jittering: the object is placed in its“regular” position, modified by a random displacement vector.

Concretely, for the current point~p we retrieve integer indices of its unit cell, which are fed into the randomvector generator resulting in a pair of displacements(dx, dy). Then, the texture generator with the objectbelonging to a unit cell (or, as we often do, to a [-1 – 1] square) is applied to a reduced and shifted point.

5.4 Random placement of objects 31

Fig. 5.6: Fractal noise and turbulence shown as reliefs

Fig. 5.7: Random placement of extended objects

There are severe problems with this simple-minded method, as we see on Fig. 5.7 at the left. If the objectcrosses its cell boundary it might get truncated, since the region beyond the boundary belongs to another textureinstance.

Fig. 5.8: Neighbours for jittering

Because of the locality of texturing machinery, there are no ideal solu-tions of this difficulty, the simplest one consists in verifying for each cellalso its 8 neighbours, and Clastic implements this technique. But someeasy optimisation is also possible. The central cell is divided into quad-rants, and each quadrant verifies only its 3 neighbours, as shown on Fig.5.8.

The 3 possible contributions are combined, so in order to avoid moredifficulties

• the graphic objects should be small,

• the displacement should also be rather small, and

• they are binary inside/outside entities, and simple union may be used to combine them.

The result of an improved method is shown on Fig. 5.7 at the right. More complex combinations are also

5.4 Random placement of objects 32

possible, although the corresponding combinators would be much more involved than just binary unions. Anadditional random generator assigned to each cell may desactivate the rendering altogether, or change the objectcolour, or make it undergo any parameterized transformation.

Most examples discussed in the last section are coded in the fileExamples/example2.icl , and useauxiliary functions in the moduleCTExamples .

Chapter 6

Deformations and Mappings

6.1 Some simple truths from the Group Theory

We know already that one possible manipulation of a texture is to act on its definition domain, and that thistransformation acts contravariantly, which is a source of difficulty: it is not possible in general to invert a giventransformation, especially if it islocal, i.e., if it depends on the current point.

Anyway, it seems appropriate to say a few more words on the equation (4.1), which we repeat here:

(Rζ) (~p) = ζ(R−1~p). (6.1)

whereζ is a texture. We have abused the language a bit.R means here a transformation which acts on points,and on textures, which is frustrating for mathematically-oriented readers, and even more for somebody whowants to implement it. The type checker will be really unhappy. So, let’s put a bit of order on that, and changethe notation.

We know that (typical) geometric transformations of space can be composed and inverted, i.e., they form agroup. All people who effectivelyusethe Group Theory (e.g., physicists) have to think not only about such agroup from the abstract point of view, but on itsrepresentation, which acts on other objects than just points(here: textures or deformers, i.e. some functional objects).

Say, we have the transformationsR acting on points, and implying the transformations of a set of objectsζsomehow related to these points. For a given transformationR we define itsrepresentation— an operatorTR

which acts onζs. The fundamental property of a representation is that it constitutes a group homomorphic tothe original:R1R2 generatesTR1R2 = TR1TR2 , and — if applicable —R−1 → TR−1 = (TR)−1.

Now, textures are functions from points to reals, or to colours which are geometricscalars, their codomaindoes not feel directly a geometric transformation of points. It is easy to prove that ifζ ′ = TRζ is a functionwhich acts as we have suggested:ζ ′(p) = ζ

(R−1p), then it is a correct definition of a representation:

(TR1R2ζ) (p) = (TR1TR2ζ) (p) = (TR2ζ)(R−11 p)

= ζ(R−12 R

−11 p)

= ζ((R1R2)−1p

). (6.2)

This is the only non-trivial representation in the domain of scalar functions.But sometimes we need more complicated representations. In particular, we may need totransform trans-

formers, for example applying the same warp to different regions of space (thus: translate a warp), and deform-ers are different kind of objects than textures, their codomain contain vectors (points), not scalars, andtheirtransformation rules will be more difficult. The details are described in section (6.3).

6.2 Deformation is a local transformation

Even if it is difficult to invert practically an arbitrary operation, many deformations are quite simple to imag-ine, we simply must think directly in terms of the inverse transformation. Clastic uses a very simple func-tional: transf trfun txtr = \p-> txtr (trfun p) , wheretrfun is a transformer function of

33

6.2 Deformation is a local transformation 34

typePoint→ Point. (A combinatorial maniac will write:transf trfun txtr = txtr o trfun , oreventransf = flip (o) , whereflip is a well known combinator which changes the order of argumentsof a binary function:flip f x y = f y x .)

Fig. 6.1: Simple deformations in polar coordinates

Fig. 6.1 shows a simple-minded transformation which consists in translating the polar angle by a value which isdependent onr. Clastic library has two such transformers, one:whirl (shown on the left picture) very similarto the notorious torsion deformation included in such packages as Photoshop or Paintshop, andvortex , amore “physical” one, where the 2-dim “matter” rotates around the central point (and is eventually aspired byit), obeying the law of area (“matter”) conservation, which fixes the relation between the torsion angle and thecurrent radius. Thevortex deformer is defined as follows:

vortex rmin2 dr2 dph p=:(V2 x y)# r2=x*x+y*y| r2<rmin2 = p# r=sqrt r2# cf=x/r# sf=y/r# df = dph/r# cs = cos df# ss = sin df= sqrt(r2+dr2) *> V2 (cf*cs-sf*ss) (sf*cs+cf*ss)

A very typical, a bit more concrete than a generaltransf ormation is thedisplacement: the applied operatorproduces a result which is added to the original argument of the texture. Clastic defines a generic functional:

displace dspl tx p = tx (p+dspl p)

If you wish:

displace dspl tx = tx o (id+dspl)

where id is the identity combinator, is a more compact formulation of it. Atransf ormer trf used in:transf trf texture is converted into a displacer by addingid to it. Nice to have the arithmetic over-loaded to functions. . .

Random displacements, especially turbulent ones are particularly useful to generate irregular wood grain,distorted marble veins, etc. We will use our fractal sum function in order to generate displacements, so thebasic noise generator should producevectors(the fractal sum functional is generic, and may be reused). Theexamples of this section may be found in the fileexamples/examples3.icl .

On Fig. 6.2 we see the following examples.

6.3 How to transform deformers 35

Fig. 6.2: Some random displacement effects

1. a brownish, wood-like simple noise pattern, which has been already shown on Fig. 5.4, but which hasadditionnally been perturbed by a turbulent (i.e. multi-frequence) displacement.

2. A simple vertical band which begins to desintegrate because of its perturbations.

3. A perturbed high-frequency, non-uniformly scaled noise. This may simulate hair or other irregular fibre-like structures.

Some more interesting effects may be obtained if the deformer action is very inhomogeneous and localized,even more than the torsion transformation.

Fig. 6.3: Lense effect explained

Another characteristic deformer is a spherical “lense” effectwhich we have already seen, applied to a texture retrieved from abitmap, on Fig. 2.5. Fig. 6.3 explains it better then the code, butif somebody wants to see the details, everything is in the moduleCTMapping . Thelense deformer generates the displacement,and it should be used underdisplace rather thantransf .

Another example of the lense deformer is the pattern visu-alised on the cover page. Both lense and torsion deformers — asdefined — are centered at zero.

So, there is one important point which will be discussed now:how to apply shifted, rotated, etc. deformers to textures. This isnot the same as translating etc. the textures themselves.

6.3 How to transform deformers

The necessity to compose transformations is self-evident. Clastic library contains a few utilities for commontasks, e.g. the rotation of a texture about a given point which includes a rotation and two translations: directand inverse. It may be defined as

rotatedAbout p0 angle // of a texture= translated p0 o rotated angle o translated (~p0)

which is a pure transformer, defined independently of its argument. We will now generalize such constructions.Suppose we want to apply a translated lense to a texture, with~u being the translation vector, but without

moving the texture. Analyzing the sense of (6.2) we see that we can proceed as follows:

• Translate the texture by~u, i.e., apply the inverse transformation to the texture argument. This will shiftthe location~p = ~u to zero. In general, transform the argument:~p→ R

−1~p.

6.4 General warping 36

• Apply the original deformerG (“anchored” at zero).

• Translate the resulting texture back, by−~u, or, in general, applyR−1 to the resulting texture (orR to itsargument.

In fact, we don’t need to distinguish conceptually the “main” deformer, say,G, and the auxiliary transformationR. The final effect is the composition of three transformations:RGR

−1, and the appropriate representation inthe domain of textures is immediate, we applyζ

(RG−1R−1~p).

For arbitraryR the problem is difficult, since we have to operate with both, direct and inverse transfor-mations, and current version of Clastic does not provide generic solvers adapted to it. But typical globaltransformations such as translations or rotations are easy to invert, and the package defines such simplisticfunctionals, as

trfshift u dform p = u + dform (p-u)

with dform being the deformer function. It is straightforward to see that this definition is equivalent to

trfshift u dform = ((+) u) o dform o ((+) (~u))

exactly as expected. This is not the end of the story, but almost. Iin order to apply the modified deformer to atexture, we define

trftranslate p0 = transf o (trfshift p0)

or, if you are a more normal person:

trftranslate p0 deformer = transf (trfshift p0 deformer)

Anologously, we have

trfturn ang tfun = rot2cs ca sa o (tfun o rot2cs ca (~sa))where

ca=cos angsa=sin ang

for rotated deformers, applicable — of course — to anisotropic transformations e.g., for already shifted de-formers. Fig. 6.4 shows a shifted local deformer, already well know lense, and also an iterated, 5-fold shiftedand rotated whirl, which produces a celtic-style multi-spiral. As mentioned, the code of these (and further)examples is included in the package distribution.

6.4 General warping

We address here the following question: how to “push” locally a texture in a given direction. Suppose we wantto displace the zero of the coordinate system by a vector~v. The neighbouring points should follow it, but theamount of translation decreases with the distance, and points far away are not affected. We should get a resultshown on Fig. 6.5 at the left.

We might imagine applying the following (direct!) transformation of points:

~p→ ~p+ exp(−k|~p|2

)~v (6.3)

which satisfies our general requirements. The problem is that we need the inverse transformation. . . . Moreover,if the central displacement~v is too big with respect to the range of the effectively deformed zone, about1/

√k,

the transformation is not reversible at all, the texture would “fold”, as a membrane pulled too far with respectto its elasticity, and some information would be lost.

We will thus consider that the displacement vector is small. More consequent warping can be obtained byiterating small steps. The displacement of an arbitrary point, not necessarily the origin of the coordinate systemhas been already discussed.

6.4 General warping 37

Fig. 6.4: Transformed deformers

Fig. 6.5: Warping, simple and compound

Clastic in its current version implements a warper based on Eq. (6.3), but it is relatively easy to change it.Relatively, since the procedurewarp p inverts the above formula using Newton iteration, and the Jacobian isconstructed manually. In the next version it should be semi-automatic, with the aid of the AD package.

The moduleCTExamples containswarp , but alsowarpfold — a composite warper which applieswarp along a trajectory (list of points). The result is shown at the right of Fig. 6.5.

Chapter 7

Textures in 3 Dimensions

7.1 What are they for and how to show them

Although we see only the surface of objects — if they are opaque, the appearance of this surface may reflectthe 3D structure of the enclosed volume. Objects made of stone, wood, or any other structured material shouldbe visualized as such, and Clastic provides some tools to make 3D textures also.

Tools are simple, since Clastic is not a 3D modelling package! But we have a reasonable collection of 3Dvector algebra tools, and a definition of acamera: an object parameterized by its position, the “look-at” vector(points along this direction will be mapped to the center of the rendering rectangle), its “focal length”, the “up”vector which defines which direction is vertical on the screen, and some auxiliary, derived attributes. (Actually,we have a small ray tracer.)

Fig. 7.1: 3D checkerboard, 3 different visualizations

The camera etc. will be described in the next section, here we simply point out the fact that we can visualizea 3D texture by cutting it with any plane, for example,proj2 tx3 is a normal, 2D texture reconstructed froma 3D densitytx3 by puttingz to zero:

proj2 tx3 (V2 x y) = tx3 (V3 x y zero)

For any other (visualization) plane the projection is just a little more complicated. Suppose that the pair(~n, c)defines an implicit plane in the space, the set of points~x which fulfil the equation~n · ~x = c, where~n is the(normalized) normal to the plane, pointing from the plane to the “camera” (arbitrarily, or infinitely distant inthis case, since the default projection is parallel, orthogonal to the surface), andc— its distance from the origin.

We consider that this plane defines our virtual viewport, and that we “look at it” along its normal. Thismeans that the viewport coordinates~p define vectors perpendicular to~n. The center of the viewport (x, y = 0)

38

7.1 What are they for and how to show them 39

corresponds in the 3D space to the vectorc~n, and that the axis~Z = ~n. We underline once more that theprojection being orthogonal, the position of the “camera” along~n has no meaning.

This is not enough to establish the “anti-projection” which generalizes the definitionproj2 above, sincewe still have the freedom of choice of the axes~X, ~Y perpendicular to~n. Wemustspecify which vector is the“up” one, and it will be our~Y axis. The procedure goes as follows:

• Declare~Z = ~n.

• Choose any vector~U non-collinear with~n. Construct the~Y axis by computing~U⊥ with respect to~Z,and normalizing it.

• Complete the triad by~X = ~Y ∧ ~Z.

The definitions of a parallel and a perpendicular projection of a vector~v wrt. a normalized axis~n are just:

~v|| = (~n · ~v)~n , (7.1)

~v⊥ = ~v − ~v|| . (7.2)

This permits to lift~p = (x, y) from the viewport to the 3D space. We get:~x = x ~X + y~Y + c~Z. This will becoded as

proj_plane n c up0 tx3 = t2where

upar = (up0<.>n)*>nyax = normalize (up0-upar)xax = yax /\ nt2 (V2 x y) = tx3 (x*>xax + y*>yax + c*>n)

Of course, instead of choosing an arbitrary normal vector we can also rotate the texture itself. The appropriatetransformer is defined similarly to the 2D case, it suffices to know how to rotate a 3D vector. The decompositionin (7.2 will help us to derive the Rodrigues formula, without the necessity to construct matrices, and produceother unreadable pieces of code.

Obviously, if a vector~v is decomposed into parallel and perpendicular components wrt. the rotation axis~n , only the perpendicular part is transformed, and the problem becomes 2-dimensional. The only “difficulty”is that in using an invariant notation we do not have the “X” nor “Y ” axes given explicitly. The idea is to usethe vector itself(its perpendicular projection) as one of axes, and construct the other one by taking the vectorproduct of the first one and the rotation axis. The code follows.

rot3 ang = rot3_cs co siwhere

co=cos angsi=sin ang

rot3_cs co si n v# vpar = (v<.>n) *> n // Invariant part# vperp = v-vpar // Perpendicular; Axis 1# v3 = n / vperp // Axis 2= vpar + co*>vperp + si*>v3

In such a way, from a “3D-checkerboard” (cubes of alternating colours) we obtain the Fig. 7.1, at the right.We could easily provided a few other planar projections, e.g., from a point camera, but we will choose now

the projection surfaces more complicated than just a plane, as texture testing tools. The rendering of 3D objectsis very far from the aims of this package.

7.2 Visualization of 3D textures in Clastic 40

7.2 Visualization of 3D textures in Clastic

Clastic implements a simple ray tracer. Simple, means simple: no recursive ray projection (no reflections norrefractions), no optimisation. It is there just to permit the visualization of 3D textures on some predefined singleobjects. In the current versions we have a sphere, a cube and a cylinder.

As already mentioned, the moduleCTView defines a camera object with enough properties in order to de-duce the parameters of the associated viewport. The camera together with its viewport, an attached backgroundtexture, and an (optional) light source constitute aViewscreen object, which is constructed by our interface(or manually, if you wish so). It handles the focal (“perspective”) projection from 3D onto the viewport. Thetracer procedure takes a 3D texture, the viewscreen, and a mapping which describes the single object, andconstructs a 2D standard texture.

The most important element here is the mapping: a cube, a sphere or a cylinder, as mentioned above. Suchan object is centered at zero. Here is the definition of the spherical mappingspherepoint viewscreenpoint2 -> (intersection,normal,viewline) :

spherepoint view = smap whereray = view.ray // Straight line generatorpos = view.cam.posps2 = norm2 pos // distance sq. camera --- originsmap p

# v = ray p // concrete, this ray# sc = pos<.>v# dl = sc*sc+1.0-ps2| dl<zero = (False,zero,zero,zero)# rpos = (sc + sqrt dl)*>v# xx = pos - rpos= (True,xx,xx,rpos)

The reader may have a look onCTMapping in order to find the mappings corresponding to other objects (andperhaps construct his own).

A 3D texture is a function of type:Point Point Point→ Colour. The second argument is the normal at agiven point, and the third: thevision line, the vector pointing from the current point to the camera. This mightfacilitate the implementation of the specular light reflections, bump-mapping, and related effects.

Fig. 7.2: More 3D textures

On Fig. 7.2 we see a marble sphere (coded inExamples/example4.icl ), and two wood-like objectswhose code is not given since it is based on our old, well known turbulent displacement, only in 3 dimensions.The normal is not used.

7.3 Light and bumps 41

7.3 Light and bumps

Since the interface of Clastic is just a visualizer, there was no point in implementing exquisite lighting effects.However, in order to see better the geometry of a 3D object the light is very useful. Clastic implementsthus a simple-minded lighting, composed of the ambient and of diffuse terms, and additionally attenuates thetransition between lit and unlit zones (sharp shadows would look silly). The diffuse term is just an attenuationfactor: ~L · ~NC, where ~N is the normal to the surface,~L — the direction of the light source, andC — thecolour of the source. This factor combined with a constant “ambient” term multiplies the intrinsic colour of thetexture.

Adding some specularity, e.g. the Phong or Blinn algorithm is trivial, and will be probably added to thenext version. The 3D texture function, and some interfacing protocols are already prepared for that. But, again,don’t expect any wonders, if you need something serious, it must be ensured by a different layer of proceduraltexturing: volumic shaders, light shaders, etc. Perhaps some next version of the package will contain suchelements, but then a fully-fledged rendering engine will be necessary to test all that.

So, the next and last example of this section is the construction of a bump-mapped surface illuminated in amore complex way. The default light available through the interface dialog should be desactivated.

Making “3D effects” which add interesting visual aspects to flat (or spherically dull) surfaces, ia a wholebranch of science, art, and dirty cheating. The fileExamples/example4.icl shows how to apply theBlinn “bump-mapping” technique to simple surfaces.

Fig. 7.3: Bump-mapping

Fig. 7.3 shows our “marble” sphere distorted visually by a 3D noise function, and a reconstruction of aplanet surface from a colour map and a height field. The bump-mapping is a pure illumination effect, thegeometry of the surface is not modified.

The bump-mapping algorithm goes as follows. Fig. 7.4 shows what happens if the original, smooth surface(blue line)S0 is deformed, by, say, adding a small height displacement field to it, prodicing the surfaceS.

Fig. 7.4: Distortion of the normal

The mathematical details depend on the way the surface is represented: parametrically or implicitly. Stan-dardway of dealing with bump mapping is parametric. A surface is a two-argument vector function, giving the

7.3 Light and bumps 42

coordinates of a point in terms of a local 2D coordinate system:~x = ~S(u, v). Then, the vectors:

~Su =∂~S

∂u; ~Sv =

∂~S

∂v(7.3)

form the axes of this local system, they are tangent to the surface. Then, obviously the normal is given by~N =~Su ∧ ~Sv. Usually it should be normalized; after the normalization of this vector we name it:~N. Suppose nowthat the deformed surface is obtained by anormaldisplacement of the original by a small quantity:~S(u, v) =~S0(u, v) + ~N0h(u, v), whereh is a scalar function, small wrt. typical scales of graphic structures within thescene. Ifh is really small as compared to its derivatives, it is easy to see that we can approximate:

∂~S

∂u=∂~S0

∂u+∂h

∂u~N0 , (7.4)

and

~N = ~N0 +∂h

∂u

(~N0 ∧

∂~S0

∂v

)− ∂h

∂v

(~N0 ∧

∂~S0

∂u

). (7.5)

Higher terms inh are neglected. If we can compute the derivatives, analytically or numerically, we have thenormal. We normalize it, and we use some light sources in order to find the resulting shading. The normaliza-tion necessary for every sampled point is quite costly, and there are some acceleration methods available (thecomputations need not be exact, we have already cheated a lot. . . ). We shall not treat these problems here.

Since our 3D objects are very simple: sphere, etc., we could have used this algorithm. The angularparametrization is straightforward. But we wanted to implement the technique identical to what we have donewith 2D, textural objects, i.e., to use implicit techniques.

If the surface is given in theimplicit representation, i.e., as an equationS(~x) = 0, then the (unnormalized)normal vector~N is just the gradient ofS. In order to deform it — not necessarily for the bump mapping, butin general — the technique used is our well known contravariant transformation of the coordinates:

S(~x) = S0

(~x− h(~x)~N0

). (7.6)

The modified normal is given then by

~N = ~N0

(1− ~∇h

(~N0 · ~N0

)), (7.7)

or~N = | ~N0|

(~N0 − ~∇h

). (7.8)

Fig. 7.5: The Astronomic Reality

We need thus just to compute the gradient of the height field, butdifferently than in the parametric case. Of course it should benormalized. This is what we have exploited in our examples.The gradient may be calculated through finite differences, ana-lytically, or using AD. The moduleexample4.icl uses finitedifferences (the gradient is defined in the moduleCTVector )just to see whether they do not introduce too much noise.

There is nothing in the package which is specific to spheresor other simple surfaces, and even if the bitmap which representsthe bump height field is adapted to spherical mapping, we can useit in different context.

Fig. 7.5 shows the true shape of our Moon, which is badlyknown because of atmospheric distortion and other religious prej-udice.

The last two textures inexample4.icl are again 2D ob-jects. We used the inverse spherical mapping in order to reconstruct a 2D “height field” from a 3D texture

7.3 Light and bumps 43

(here: a horrible fractal (turbulent) spherical relief, with even more horrible colours) retrieved from the 3Dsurface which should be bumped. It should be rendered in a rectanglex : [0, 2π], y = [0, π]. See the distortionnear the polar region, characteristic for the Mercator or other similar projections.

Fig. 7.6 shows the result. This is a common technique, useful for some synthesis tasks. If the manipulationof a 3D texture is costly, and we know in which contexts it will be used, it is often possible to construct anappropriate map, and to use it instead of the original. Reflection maps, environment maps etc. are examples ofthis strategy.

Fig. 7.6: A Fractal Planet and its maps

Chapter 8

Tesselations

8.1 Introduction

Tilings are omnipresent. Mosaics, rugs, wallpaper, bricks, decorative sidewalks (such as the notorious wigglypattern on the Copacabana beach), etc. So, this is an important part of the texturing technology. Clasticimplements some useful tools, but the work is very far from being complete, and it will continue for some time.An obvious feature of this domain is that something interesting is obtained by experimentation, and the numberof “regular” techniques is small. Anyway, in order to progress, one has to know a lot about plane symmetriesand tesselation in general, and this is not always easy [16, 17, 18, 21]. . .

If you have a “drawing” program, i.e., a set of routines which place some graphic objecs where you need them,making replicated pattern with translational, rotational or mirror symmetries is essentially straightforward, youwrite an appropriate iterative loop, provided you know how to transform objects.

For a texturing application the life is a bit harder. If the textured zone contains several identical objects,e.g. it is a star polygon, such as that we constructed in the section (4.1.2) using the CSG method, for everypixel of the image all the contributions from individual patterns have to be checked, which may be extremelyexpensive. In general case nothing can be done, but if the objects placed are replicas of the same entity whichmay be transformed according to some symmetry considerations, the situation changes.

Fig. 8.1: Another star making

The serious way of dealing with that resides inreducingtheargument (point) of the texture generator, finding the “original”,and from the relation between the actual point and its reduction,deduce the transformation to be applied.

In such a way, the correct way to render a star should followthe idea shown on Fig. 8.1. If the current point is located in thesector between the lower green ray and the red dotted line, thetexture applied is the dashed half-plane. If the point is above thedotted ray, apply the mirror inversion of the half-plane wrt. thedotted ray, otherwise, if the point is outside the sector betweengreen lines, rotate it back,togetherwith the texture definition.

This is the entire code of a regular star (1 inside, 0 outside).The code is quite long because of the parametrization; this func-tions computes the star for anyn, and for any two “radii”, asshown on the Fig. 8.1. Moreover, it is as invariant as possible,without the separation of point coordinates. The functionangle(V2 x y) returnsatan2 x y .

regstar n r0 r1 = rstarwhere

44

8.2 Plane symmetries 45

alpha = Dpi/fromInt n // Elementary sectoralph2 = alpha/2.0hax = rot2 alph2 X2axis // Dotted half-sector axisp0 = r0*>haxnrm = rot90 (normalize (p0 - r1*>X2axis))hplane p = step (nrm<.>(p-p0)) // Half-plane. Below is reflectedreflected v = hplane ((2.0*v<.>hax)*>hax - v)rstar p

# a = angle p# turn = floor(a/alpha) * alpha# ared = a - turn // Angle reduced to the 1st sector| ared <= alph2 = rotated turn hplane p // No reflection needed= rotated turn reflected p // But here: yes

This definition belongs to the standard Clastic panoply. The reader will find it in the moduleCTBase.

8.1.1 Small optimization

If you want to render many such stars, you may accelerate the painting using bounding disks. Ifr =√x2 + y2

is greater thanr1, the point is outside the star, and there is nothing more to compute.Here we can also use theinterior bounding disk: ifr is smaller thanr0, then the point isinsidethe star.

This technique can be applied to more complicated figures where the gain would be much more important.Readers acquainted with graphic modelling should see immediately the possibility of applying a hierarchicaldecomposition of the figure in quadtrees. As compared with the standard quadtree technique, where the leavesare blocks of desired size (depending on the precision, i.e. the qudtree depth), in a functional language we mayattach to the branches — at any level — the closures which compute the details, or return a static value veryfast.

This strategy may pay itself if the figure is really complicated, because the quadtree construction andtraversal have also their costs. . .

8.2 Plane symmetries

In the construction of arbitrary geometric patterns, finite and infinite, we have to provide forall possible sym-metry reductions. In particular, we can make stars with arbitrary number of vertices. Replacing inregstarthe straight lines by something more complicated, and constant values attributed to the interior/exterior zonesby some composite textures, we may generate very nice decorative patterns of any complexity.

We shall see that for infinite textures possessing also translational symmetry (forming a kind of 2D “crystal”lattice), the freedom to choose rotational symmetry is severely limited. We learn it on the elementary geometrycourses: only triangles, squares and hexagons fill the plane. It would be preposterous to try to cover all thetheory of plane symmetries in this tutorial, so we shall sketch here a bare minimum useful for the constructionof interesting textures.

Conventionally, we classify symmetric planar patterns into:

1. Rosettes, possessing rotational symmetry of any order, and — possibly — some reflections. A regularn-star is a rosette. If it is defined with homogeneous texturing of the inside, it hasn axes of reflectivesymmetry ifn is odd, and2n such axes, ifn is even. A rosette may have only one center of rotation,because two distinct centers imply the existence of translations.

2. Friezes, 1-dimensional bands with translational symmetry, and eventually some reflections wrt. the axisof the band, or perpendicular.

3. Wallpapers, having as their symmetries the so calledwallpaper groups, containing at least 2D transla-tions, eventually rotations, reflections, andglide reflectionswhich will be defined below.

8.2 Plane symmetries 46

Here we will treat the last category. There are 17 distinct wallpaper groups, but, as we shall see, they don’t saytoo much about the actual replicated shapes.

Fig. 8.2 shows the difference between axial reflections and glide reflections. These last transformations arecomposed of reflections wrt. an axis, and a translation parallel to this axis. We remind that there is no need tospeak about focal reflection (wrt. the center of the coordinate system) in two dimensions, since this operationis identical to a rotation by 180 degrees.

Fig. 8.2: Reflection (axial), and glide-reflection

Glide reflections have nothing obvious in them, and their usage needs some imagination. But they areuseful for parquets, or similar patterns, see e.g., the central picture on Fig. 4.7. This is the Tartan weavingpattern: neighbouring diagonals with horizontal and vertical segments are in glide-reflection relation (apartfrom colours, of course).

8.2.1 Important entities

In order to understand the rest of this section the reader must become acquainted with the following.

1. Since we are considering translationally invariant textures (i.e. we shall not touch Penrose patterns, etc.),the infinite plane may be covered by discrete translations (andonly translations) of a finite (and rathersmall with respect to the texturing area) region, which we call theUnit Cell (UC). Sometimes it is called“lattice unit”. The choice of UC isneverunique, and we will see that much freedom remains after havingchosen it.

2. If the symmetry group under consideration possesses also other operations, i.e. discrete rotations, re-flections, and glide-reflections, it is possible to cover the plane usingall these symmetry operations.The smallest (or: one among smallest) regions able to generate the whole plane by applying all possibletranslations, rotations, etc., is called theFundamental Region(FR). Usually it is a fragment of the UC.

3. Neither UC nor FR do specify the replicated shape! This pattern, whose form and texture details dependon the user, may occupy neighbouring fragments of different UC and FR. We will call it theMotif (M).It cannot be arbitrary, of course, by cutting it and reassembling its parts (eventually repeated) we mustbe able to reconstruct the UC and FR.

8.2 Plane symmetries 47

Fig. 8.3: Translational block

So, the geometry of UC and FR doesn’t say anything about the internalstructure of the replicated pattern. Sometimes the same formal symmetryattributes provide just some topology constraints, and from the same groupwe might produce a hexagonal lattice and rectangular brick wall, as we shallshow later. Also, the “skeletons”, or the boundaries of the replicated regionsmay possess symmetries higher than the actual textures. E.g., a square hasa fourfold rotation center and 4 reflection axes, but if you put somethingasymmetric inside, all this symmetry is lost.

The Fig. 8.3 shows a Motif which fills the plane with just translations,as shown on Fig. 8.4, one of the most elegant semi-regular tilings. If weeliminate the colours, the pattern will acquire several rotational and reflective invariance properties. If we shearit, these symmetries will disappear once more, but the translational symmetry will remain.

Fig. 8.4: A semiregular P1 pattern

8.2.2 Wallpaper groups

We enumerate them all before passing to concrete realisations, where all the details and illustrations will beintroduced incrementally. We shall include also some simple theorems needed to construct the coordinatereducing routines. There are two popular naming schemes, the International Union of Cristallography notation,and a more recent and mathematically-oriented Orbifold notation, proposed by J.H. Conway (based on ideasof William Thurston). We will use the IUC notation. it consists of four symbols, sometimes simplified. Itidentifies

• The Cell. Usually the UC is chosen so as to have centers of the highest order rotational symmetry at itsvertices. We call it aprimitive cell; the group will contain the letterP. Sometimes, however, it is moreuseful to deal with acentered cell(C), in which there are reflection axes perpendicular to the cell sides.

• The highest order of rotation: an integer numbern.

• A symbol denoting an axis normal to the x-axis (conventional):M (mirror) indicates a reflection axis,Gindicates a glide-reflection axis (but no ordinary reflection symmetry),L indicates no symmetry axis.

8.2 Plane symmetries 48

• A symbol which denotes a symmetry axis at angleα to x-axis, withα dependent onn, the highest orderof rotation: α = 180◦ for n = 1 or 2, 45◦ for n = 4,60◦ for n = 3 or 6. SymbolM , G, or L areinterpreted as above. No symbols in the third and fourth position indicate that the group contains noreflections or glide-reflections, and the notation may be shortened.

So here is the catalogue of wallpaper groups. Please read [16, 17, 18] for the details and examples.

1. P1. Translations only, two arbitrary axes. The FR and UC are identical, and as you may imagine, this isa parallelogram. This is the most simple tiling possible, but we shall see that if the translation axes arenot perpendicular, the texturing is less trivial than we have seen while constructing a checkerboard.

2. P2 (P2LL ). The presence of the180◦ rotation (half-turn) symmetry implies that the texture is invariantwrt. the central reflection:~p → −~p. Of course, here and later:the existence of a rotation center, andthe translational symmetry imply that there are infinitely many rotation centers forming a latticecompatible with the translational grid. It is not difficult to see that the center of the UC must be a rotationcenter, since the half-turn must leave the UC invariant. But the UC remains an arbitrary parallelogram,only the FR is now reduced to a half of it (below or above one of its diagonals).

3. PM (P1ML ). We have a mirror now. Knowing that an arbitrary parallelogram transforms to somethingnon-isomorphic to it under an axial reflection, we see that the UC is a rectangle, and the translation axesmust be perpendicular. Of course, as previously, it is easy to deduce that we will have an infinite numberof reflection lines. The Fundamental Region is a half of the UC, say, the lower half of the rectangle, ifthe reflection axis is horizontal.

4. PG (P1GL). Similar to the above, only the mirror translates also the pattern horizontally.

5. PMM (P2MM ). This is a very classical tesselation, with horizontal and vertical reflection axes. Ofcourse, having two different axial reflections implies the existence of a half-turn symmetry. The UC isrectangular, rotation centers are at its corners, mid-edges, and in the center, and the FR is a quarter of theUC.

6. PMG (P2MG). Two horizontal reflection lines within the UC, accompanied by a vertical glide-reflectionline. UC rectangular, FR is a lower quarter of it.

7. PGG (P2GG). Two glide-reflections, implying a rotational180◦ symmetry as well. This is an interestingsymmetry, able to generate parquets, or specific weaving parquets, as mentioned above (see the Fig. 4.7,the picture at the center).

8. CM (C1ML ). Here the UC is a rhombus, having a reflection axis along its diagonal, and two parallelglide-reflection lines. The FR is a half of UC.

9. CMM (C2MM ). An augmented version of the above. Horizontal and vertical reflections, and also glidereflections. So plenty of half-turn symmetry centers as well. UC is a rhombus, FR is a quarter of it.

10. P4. That’s it, almost nothing more to say. Or, perhaps not. The UC must be a square, and the 4-rotationcenters are at the corners, and there is a central one too. This implies that there are also 4 2-rotationcenters, at the middle of the 4 edges of the UC. The FR is a quarter of the UC. There are no reflectionsymmetries, this group may generate “swastika” patterns.

11. P4M (P4MM ). P4 plus a mirror implies much more. There are 4 mirror planes, vertical, horizontaland diagonal (of course both). There are also four glide-reflections, also diagonal, but shifted, half-waybetween the center and a corner of the UC. The FR is one-eight of the UC. It generates more or less“classical” cross-style patterns.

12. P4G (P4GM). The UC is a square with five 4-fold rotation centers, four half-turns at the mid-edges, fourhalf-diagonal reflection axes, and 6 glide-reflections. Not very intuitive, but you have seen it already.This is the right pattern on the Fig. 2.1. The FR is one eight of the UC, but positioned differently than inthe case above. Of course, the Motif may be much more sophisticated.

8.3 Tile generators in Clastic. Unit cells 49

13. P3. The basis for higher symmetries, kaleidoscopes, and other magic patterns. If you think that UC is atringle, it isn’t. It is a parallelogram (a rhombus in fact) with axes of identical length, forming an angle of60◦ (and120◦, of course). There aresix 3-rotation centers within it, two inside, and four at the corners.The details are below, see Fig. 8.10. The FR is a smaller rhombus, occupying one third of the UC, andwhose long diagonal is the short diagonal of the UC.

14. P3ML . Ah, this one is very interesting. In fact this may be called the kaleidoscopic group. The UC isthe same rhombus as in the P3 case, but additionally there are 5 reflection axes (and some implied glidereflections as well). One of these reflection axes is the long diagonal of the rhombus, and the FR is ahalf of the P3 FR, above the long diagonal. (This is an equilateral triangle in case you still have somedoubts). The 3-fold rotations are the crossing points of the 3 reflection axes.

Actually, the mirrors suffice to generate all the rest. Three such axes form a triangle composed of mirrors,the most classical kaleidoscope. If you have never seen it, you wasted your childhood. . .

15. P3LM . This one is not very intuitive. There are 3-rotations with centers at the crossing of 3 mirrors, andalso twice as many 3-rotation centers in the middle of triangles formed by reflection axes. The FR is atriangle with angles30◦, 30◦, and120◦. This is one-third of an equilateral triangle which is a half of theUC rhombus.

16. P6. As in many cases above, the existence of a 6-rotation center implies also some others. The UC is a60 –120◦ rhombus, and the 6-centers are at its corners. But the UC contains also two 3-rotation centers,and four half-turns. The FR is one-sixth of the UC.

17. P6M (P6MM ). This is an extremely symmetrical “stained glass” pattern generator with the same rotationcenters as above, but possessing 9 reflection axes, and a large number of glide-reflections. A verbaldescription doesn’t say much. The FR is 1/12 of the UC rhombus.

8.3 Tile generators in Clastic. Unit cells

As we have already said, we will not discuss limited symmetries with just 1D translations, or only rotations.So,all textures will lie upon a geometry possessing two translation axes. In the moduleCTTile we definea genericUnitCell data structure: a record containing two axesaxS andaxT , and plenty auxiliary values,such as norms of the axes vectors (they need not to be identically normalized, although in principle we couldwork with normalized axes, and rescale everything later. But this would be extremely cumbersome). Thisrecord contains also the precalculated scalar and vector products of the axes, and several conversion functions,needed to pass between normal Cartesian coordinates and the local coordinate space. The constructor of a UC,mkunitcell needs only the two axes.

Fig. 8.5 shows a general Unit Cell, and a way to calculate the internal, normalized coordinatess andt,which belong to the interval [0 – 1]. In general case, any vector~p (not necessarily within the UC) can beexpressed through the UC axes:~p = s~S + t~T . Since the axes are not orthogonal, construction ofs andt ismore involved that just taking a scalar product of the point and one of the axes. But we can compute the skewproduct which in 2 dimensions yields a scalar:~a ∧~b = axby − aybx. Here we have

~p ∧ ~T = s~S ∧ ~T , (8.1)

etc. We have thus the non-cartesian (contravariant) decomposition given by:

s = ~p ∧ ~T/~S ∧ ~T ; t = ~S ∧ ~p/~S ∧ ~T , (8.2)

and in order to reduce any point to the UC, we apply the functionfrac to the resulting coordinates. Thereduced point is reconstructed through (8.1), and the tiling problem of any P1 texture is solved.Well, almost. . . We have already mentioned that the Motif doesn’t need to cover a UC. Fig. 8.6 shows whatmay happen. Now, the possible ways of cutting the UC into pieces and their reconstruction is a work for an

8.3 Tile generators in Clastic. Unit cells 50

Fig. 8.5: A unit cell; two sets of intrinsic coordinates

Fig. 8.6: Motif displaced wrt. the Unit Cell

artist, not for a program, although there are programs which can almost automatically “Escherize” a not verycomplicated form. In this case some rotational and reflective symmetry usuallymustbe exploited. We shallshow here just some transformations easy to produce regularly. Fig. 8.7 shows an asymmetric pattern whichwill be sometimes used to visualise the symmetry of the tiling.

Fig. 8.7: Asymmetric motif

Clastic in its current version offers a very simple tool: a generator of hexag-onal patterns (more or less) centered at the origin, otherwise arbitrary. As anextra bonus, the reducing procedure discovers whether the current point isnear the boundaries of the motif region (the black lines forming a “H” insidethe UC on Fig. 8.6), and considers it to be the “mortar” zone, filled witha different texture (which is P1-reduced, but not displaced as the remain-ing parts of the UC). The moduleCTTile contains the procedurehextexwhich takes a cell, the width of the mortar (if negative, its only effect is aslight slowing down of the rendering), and two points sufficient to specifycompletely the “H” pattern within the UC. It takes two more parameters, themain texture, and the mortar filling. This is a horribly long procedure, about30 lines. . . , but then, the construction of beehives, or of brick walls, is donein just a few lines, less than 10. We suggest to compare this with typicalRenderMan shaders. The fileexamples/example5.icl shows somesimple textures, visualized on Fig. 8.8.

This is more or less everything we can say about the translational symmetry. The situation becomes techni-cally more complex if we engage rotations and reflections, but conceptually there is nothing new, just additionalproperties permitting to reduce the current point in a more agressive way.

8.4 Symmetry P3 51

Fig. 8.8: Some tesselations with hexagonal topology

8.4 Symmetry P3

Clastic does not implement (for the moment) the full 17 wallpaper groups. First, it would be boring, the resultsare not always so pleasant.

Fig. 8.9: A simple P3 pattern

Actually, truly interesting tilings are either semi-regular, orhierarchic, with different symmetries at different scales. All thiswill be treatedmuchlater.

Then, implementing wallpaper groups quickly becomes te-dious, and doesn’t add anything to the applicative side of the tex-turing process. Finally, we have to leave something to our stu-dents and/or other readers. But something is there for your inspi-ration. In this section we treat the group with three-fold rotationcenters, and no reflections.

If we don’t play with a differently positioned motif, nor otheradditional transformations which may add some juice to our artis-tic creations (for example: colour changing between rotated in-stances of the motif), me may get a result shown on Fig. 8.9. Theconcrete code is shared between the moduleCTTile , and the fileexamples/example5.icl .

8.4.1 A simple case

Fig. 8.10 shows the UC of a P3 group. We may divide it into two equilateral triangles, each of them containingthree rotated instances of a half-FR,A orB .Again we see that the choice of the FR is not unique. At the right of Fig. 8.10 we see two different possibleFundamental Regions. There is nothing universal permitting to choose one of them for the tesselation.

The reducer procedure is not more complicated than the technique already known from the motif recon-struction, only the rotation is used instead of translations. Perhaps, from time to time it is useful to see the fullcode of such a reducing procedure, here it is:

p3reduce tx = ttxwhere

stvec =: Tricell.st_vec // A constant, standard rhombic Ucellrp0 =: stvec (one>/3.0)rp1 =: stvec (2.0*>one>/3.0) // Centers of two trianglesttx p

# q = Tricell.red_st p // Point, reduced to the Unit Cell; (s,t)

8.4 Symmetry P3 52

Fig. 8.10: The P3 symmetry, Unit Cell and Fundamental Regions

# (V2 s t)=q# rq = stvec q // Reconstruction in (x,y) space# (V2 u v) = Tricell.st_uv q // Covariant coords are here also useful| u<=0.5 && s<t = rotatedAbout rp0 PiD tx rq // PiD = 120 deg.| v<=0.5 && s>=t = rotatedAbout rp0 PiA tx rq // PiA = 240 deg.| u>1.0 && s>=t = rotatedAbout rp1 PiD tx rq| v>1.0 && s<t = rotatedAbout rp1 PiA tx rq= tx rq

8.4.2 A tribute to Escher

We might want to produce a tiling with the motif which overflows the FR, and moreover, it is would be niceto change something (e.g. colour) while passing from one instance of the motif, to another one, rotated. Let’sproduce the notorious reptile pattern on the Fig. 8.11.

Fig. 8.11: Escher lizards bred by Clastic

We see that the shape (the outline) of one of those beasts — although composed of straight segments — isnot very easy to represent as a mathematical form (we tried, and we decided not to repeat this experience. . . ).

8.5 Symmetry P3ml: a kaleidoscope 53

The position of one lizard within the UC is presented on the Fig. 8.12, and if the reader is imaginative enough,he will see that the corners of the lower triangle of the FR are three rotation centers permitting to fill the spacearound the original.

Fig. 8.12: A lizard in its geometric habitat

The lower, empty part of the grey rectangle is not completely useless. If the side of the UC is equal toone, the rectangle has well-defined “virtual” dimensions:x ∈ [O, 3/2]; y ∈ [−1/2

√3,√

3/2]. We know theposition of the rotation center in the texture space, and we shall use abitmap imageof the lizard as a replicatedpattern, of course after having transformed the image into a texture generator. The same image, or a simplifiedversion of it will serve as a mask permitting to find out whether the current point finds itself inside or outsidethe motif.So, don’t expect that any texturing package does such manipulations automatically!You must knoweverything about the geometry of your motif, choose the background mask, etc.

There is one remaining problem, which should be resolved also case by case. The motif overflows theUC, not only the FR. The reptile generator verifies thus also the UC beneath, and at the right of the main cell(without touching the rotation symmetries; in other cases one might has to look up other neighbours as well).The generator is used in the fileexamples/example5.icl . It is defined in the moduleCTExamples ,and it should be fairly easy to parameterize it to other Escherisms of this kind. Because of the imperfection ofcurrent bitmap handling, the size of the rendering window should be at least 400 – 500 pixels, otherwise theresults are ugly (but switching on the antialias helps a lot). Anyway, those lizards are ugly, the geometric shapewhich we sketched by hand using Escher model is not precise.

8.5 Symmetry P3ml: a kaleidoscope

A kaleidoscope is a set of three mirrors forming an equilateral triangle. With two (or more) reflections thereis plenty of rotation centers as well, and in principle we might not use the rotations, only the reflections. Thiswould make the reduction process slightly longer.

In fact, even the translations are redundant. The kaleidoscope generates an infinite plane only by reflections,and with some tuning just two reflections suffice to reduce any point on the plane to its original triangle, whichis its Fundamental Region. But in the current version we reduce first evrything to the Unit Cell by translations.

We have shown on Fig. 8.5 the two useful sets of non-Cartesian coordinates, the standard contravariant(s, t), and covariant(u, v). Both will be used here. Looking at the left drawing on Fig. 8.10 we may localize

8.6 Parquets PGG 54

the FR in the present case, it is the upper half of theyellow rhombus. The mirrors are given thus by the equations:

s = t ; u = 1/2 ; v = 12 . (8.3)

There is another pair of (secondary) mirrors:u = 1, andv = 1/2, and there is almost nothing more to say.When the generator finds out that exactly two reflections are needed, this is the rotation case. In realistickaleidoscopes the motif is enclosed entirely by the FR, although the ambiguity between the original reality andits mirrored instances is an immortal artistic and fantastic cliche.

On Fig. 8.13 we see two kaleidoscopes, one with our simple asymmetric motif, and other representing areptilian folk dance.

Fig. 8.13: Two kaleidoscopes

8.6 Parquets PGG

Time to introduce some glide-reflections. On Fig. 8.14 we see a classical parquet pattern. This result was pro-duced by a specific reduction procedure, which doesn’t use the standard Unit Cell data structure. It is possiblynot the most efficient algorithm, since it iterates the short movement along the diagonal, but it economises somecomputations needed to localize the point within the UC. A regular procedure which reduces the current pointto the UC, then using the glide reflection (and the half-turn, which we will avoid) with the translation equal tothe half of the UC width, seems a bit awkward here because of the particular placement of the motif.

Fig. 8.14: A PGG/PG parquet

Anyway, Fig. 8.15 shows the structure of this symmetry. The redrectangular contour delimits the UC, and the grey zone is the FR.The dashed blue line is one of glide-reflectors within this group.The widtha and the heightb of tiles may be arbitrary, althoughfor practical reasons very often on is a multiple of the other (this isthe case of “parquet” generated by our weaving algorithms; youcan exploit then the horizontal and vertical translations for thecoordinate reduction).

The dimensions of the UC rectangle are:√

2a, and√

2b, ofcourse. Its area is the sum of the areas of the horizontal and ver-tical tile. The center of the UC is a half-turn center, which iseasy, although non-trivial to see. However, if the tiles are filledwith a wood-like, not very regular texture, this symmetry is lost.So, attention! Although the title of this section is “PGG”, thegenerated parquet texture will have only the symmetry PG.

8.7 Conclusions 55

Fig. 8.15: A PGG parquet pattern

Here is the full code, with(a, b) being the tile dimensions, andtx — any texture you wish.

parquet a b tx = tx o redcellwhere

a2 =: 2.0*a; b2 =: 2.0*b // Some useful constantsapb=: a+b; amb=: a-bp0 =: V2 a (0.5*b)u =: (Y2axis-X2axis)>/Sqrt2 // Up-left diagonaltr =: (b/Sqrt2)*>u // Glide amountglidrefl p = refl p0 u p + tr // refl is defined in CTVectorredcell (V2 x y)

# su=(y+x) mod a2# di=(y-x) mod b2 // Just the standard UC reduction= redmotif (0.5*(su-di)) (0.5*(su+di))

redmotif x y // Look up the figure to understand this| x<0.0 && y<b = glidrefl (V2 (x+apb) (y+amb))| (x>=0.0 && x<a && y<b) = V2 x y| x>=a = glidrefl (V2 x y)= redmotif (x+b) (y-b) // Might repeat this, usually less than 4 times

8.7 Conclusions

Needless to say, Clastic isnot and will never be a tesselation package. We decided to built in some proceduresof this kind, since it is not easy to find such texture generators with some degree of genericity, and free tomanipulate. It is easy to find hundreds of tesselation packages, tutorials, descriptions of wallpaper groups, etc.,but if we need such a texture as a shader, permitting its arbitrary composition and mapping, the life becomesharder. Especially, it is difficult to construct interactively complex, multi-level hierarchic patterns. Feel free tomake your own experiments, and send us your results!

This work is far from being terminated. We need to code more groups, more reduction tools, and, lastbut not least, construct the hyperbolic tesselation generators as well. But everything depends on the needs ofpotential users.

Chapter 9

Differential Structures

9.1 Who needs derivatives

A cynical person might say that if you don’t know, then you don’t need them, and you might well skip thissection. But in computer graphics, as everywhere else, sometimesneedsare conditioned by theavailability oftools, and often by the knowledge of their existence.

Suppose that the functiont(~p) is a texture, a scalar function of a point. If the co-domain is the space ofreals, it may be considered as a height field. In the section 7.3 (see the eqs. (7.5) and (7.8)) we show how tocompute the normal to it, and to compute the light effects, permitting to use a real texture as a bump map.

Another example, truly planar this time, is included in the fileExamples/example1.icl , and dis-cussed in the section 2.3.1 (see Fig. 2.2). If the implicit equationf(~p) ≥ 0 defines the interior of a closedcurve, the vector~∇f(~p) is the normal~N to the contour at the point~p. Then, if we normalize~N , the function

f(~p) = f(~p− ε ~N

)becomes zero along the contour shifted byε with respect to the original. The function

contour implemented in Clastic does exactly this.More complex deformations, e.g. depending on the local curvature, need higher derivatives. In simula-

tion/animation we need often toconstructdifferential equations from some variational principle, or to computeforces (accelerations) from a given trajectory. The vorticity fields (tornadoes, galaxies) may be constructed bytaking curls of specific vector potentials.

Derivatives/gradients are used in equation solvers which use the Newton algorithm. We needed them forgeneral warping.

If you don’t know how to operate with gradients etc., your creative freedomis restricted. In principlethe easiest way to compute them in a framework similar to ours (having all generators as functions) is to usefinite difference approximation. Clastic implements simplistic gradients in 2 and 3 dimensions using finitedifferences, but it has been done just to test our AD package. Sometimes there is no choice, e.g., if the textureis given as a static bitmap. But there exist some more elegant approaches as well.

9.2 What is Automatic Differentiation

As we know, the differentiation of an elementary function, sayf(x) =(2 sin

(x2)

+ x)/(exp(−x) + 1) is

a mechanical procedure, whichusuallydoes need any specific analytical, topological knowledge, and may beperformed by a high-school pupil, or by a not particularly intelligent symbolic manipulation program, which hasaccess to the syntaxic structure of such a definition. But symbolic differentiation is quite costly, and if we needjust numerical derivatives at a given point, we can compute themeasily, efficiently, and precisely, by performingthis “symbolic” (in fact:semi-numeric, i.e. working on numbers and some data structures containing numbers(vectors, polynomials, etc., butnosymbolic names) transformation directly during the numerical evaluation ofexpressions in a program. This is AD: Automatic Differentiation, for which there exist several implementation

56

9.2 What is Automatic Differentiation 57

techniques, this is an established technology. We shall exploit the possibility to overload arithmetic operationsin Clean to some specific compound data which represent numerical expressionstogetherwith their derivatives.

For simplicity we treat scalar, one independent variable first, and discuss the generalizations (and oneimportant simplification) afterwards. Imagine that we define the following data, structurally equivalent to asimple, homogeneous list:

:: Dif a = Cst a | Dif a (Dif a)

where the typea typically is Real (but we keep it generic, it may be Complex, etc.) We define also the class ofpolymorphic differentiation functions

class dif a :: a -> a

instance dif Realwhere

dif _ = zero

etc., which transform expressions into expressions, following the rules of differential calculus.A word ofwarning! The function dif does not take a functional object as its argument, but just a “generalizednumeric” expression, and produces another object of that kind. If this is a (here: real) number, itsderivative vanishes identically. In order to produce something non-trivial we must generalize numbersto non-trivial instances of adifferential algebra. The datatypeDif a defines such an instance, the derivativeis just the second element of the tuple. More concretely:

instance dif (Dif a) | zero awhere

dif (Cst _) = zerodif (Dif _ p) = p

We see thus that in order to convert a standard numerical program into an augmented, differentiating procedure,all numeric constantsc whose derivatives are identically zero, should be lifted toCst c . This cannot be doneautomatically in Clean (in Haskell: yes); the user should code:fromReal 2.0 * sin x + fromInt1. . . , etc. The instances offromInt, fromReal are appropriately overloaded in the moduleCTMath.Such typical constants aszero, one, two, half . . . are overloaded as well.

A variablex e.g., the argument of a differentiated function, has its derivative equal to 1, so the numberxshould be lifted toDif x (Cst one) .

In several AD packages the data structure used is simpler: the “main” value, and the first derivative. But inthis case the functiondif — as defined above — cannot be applied, since the derivative of a tuple is a number,the typing is not respected. Using lists we can define aclosedalgebra, an algebraically complete domain, butwhich requires a lazy language for its implementation, since for most cases the chain of derivatives is infinite(it truncates only for polynomials) [19]. We can define thus

instance + (Dif a) | + a where(+) (Cst x) (Cst y) = Cst (x+y)(+) (Cst x) (Dif y p) = Dif (x+y) p(+) (Dif x p) (Cst y) = Dif (x+y) p(+) (Dif x p) (Dif y q) = Dif (x+y) (p+q)

instance ~ (Dif a) | ~ a where~ (Cst x) = Cst (~x)~ (Dif x p) = Dif (~x) (~p)

// Now omit ALL Cst instances; trivial

9.3 Generalizations and simplifications 58

instance * (Dif a) | +,* a where(*) (Cst x) (Dif y p) = Dif (x*y) (x*>p)(*) (Dif y p) (Cst x) = Dif (x*y) (x*>p)(*) e=:(Dif x p) f=:(Dif y q) = Dif (x*y) (p*f+q*e)

instance / (Dif a) | one,+,*,/,-,~ a where(/) (Dif x p) f=:(Cst y) = Dif (x/y) (p/f)(/) (Cst x) (Dif y p) = let ip = Dif (one/y) (~p*ip*ip)

in x*>ip(/) e=:(Dif x p) f=:(Dif y q) = Dif (x/y) (p/f - e*q/(f*f))

instance exp (Dif a) | exp,*,+ a whereexp (Dif x p) = let r = Dif (exp x) (p*r)

in rinstance ln (Dif a) | ln,one,+,*,/,-,~ a where

ln e=:(Dif x p) = Dif (ln x) (p/e)

instance sqrt (Dif a) | sqrt,one,+,*,/,-,~,fromReal awhere

sqrt e=:(Dif x p) = let r = Dif (sqrt x) (fromReal 0.5*p/r)in r

etc. The moduleCTMath defines the trigonometric functions, atan, and some others. In case of need it isstraightforward to define the Bessel, or other special functions defined recurrently, even those functions whichuses their own derivatives in the recurrence equations! We see that we usually don’t even need the functiondif – we apply the normal arithmetic and we get “for free” all the derivatives hidden in deeper elements of theDif structure. Of course, nothing is really free, but Clean is a lazy language, and those higher derivatives arenot created physically, unless you need them. Still, they occupy the memory as unevaluated thunks.

9.3 Generalizations and simplifications

We will need both.

• We need gradients, i.e. derivatives in multi-dimensional space.

• In almost all texturing applications having the possibility to compute arbitrarily high derivatives is use-less. We need over all just gradients. If we need — very seldom — second derivatives, we can alwaysuse the double embedding:Dif (Dif Real) . The general lazy package is much less efficient in thiscase, it clogs the memory.

Clastic defines thus the datatype::: Dv2 a = Dv2 !a !(Vec2 a) of expressions containing a scalarvalue, and its 2-dimensional gradient. (In the current version there is no 3-Dim. version of it simply becausewe didn’t need it; it can be added in 10 minutes.) This variant of AD has been used to define thecontourfunction. The gradient is anormal, numeric vector, it is not possible to differentiate it twice if the typea isspecified as Real.

If the arithmetic is lifted correctly, the scalar products and all the vector algebra follow. If the functions tobe differentiated are defined generically, i.e., if all numeric constants are lifted byfromReal , the only thingwhich remains is to apply a function not top=:(V2 x y) , but tomkdvec2 p , where this lifter is defined as

mkdvec2 (V2 x y) = V2 (Dv2 x (V2 one zero)) (Dv2 y (V2 zero one))

Then we can retrieve the numerical gradient just by taking the second field of theDv2 structure.

9.3 Generalizations and simplifications 59

9.3.1 A simple example

Fig. 9.1 at the left shows an ordinary, scalar noise. Nothing really fascinating, moreover just by looking atit it is difficult to say whether it has or has not some ugly artefacts coming from the fact that it is glued frominterpolated pieces.

Fig. 9.1: Noise function and the absolute value of its gradient

At the right we see the absolute value of the gradient of this noise, with pure cyan attributed to zero. Wemight suspect that the critical lines, where the gradient vanishes are perhaps too long, and that some discretegrid features remain, although we worked hard to prevent discontinuities of the noise field. These examplesand those below may be found inExamples/example6.icl .

Fig. 9.2: Gradient and curl of a noise, visualized through LIC

The left picture on Fig. 9.2 shows the same gradient, but visualized with the aid of the most classical (andawfully slow) Linear Integral Convolution algorithm, with constant kernel. The LIC code is in the moduleCTMath, don’t worry, it is just 10 lines. . . The contrast of these pictures had to be enhanced a little bit. Wesee that our noise is not perfect, as everybody would suspect anyway. So, just for your visual pleasure we havereused the same noise treated not as a scalar, but as the only non-vanishing axial (“z”) component of avectorpotential(ask some physicist what is it), and we visualized the curl of it. It shows some nice vorticity pattern.This example in not “serious”, since we had used rather primitive methods to compute the LIC contributions,

9.3 Generalizations and simplifications 60

but it is here just to show that the methods advocated here might be useful for the visualization of vectorialscientific data, starting with some potential functions.

Appendix A

System requirements

The package works (has been tested) under Clean 1.3, Windows Nt/2000 version. Memory: 64M or more. Oneminor modification of the standard IO package has been made. The fileosbitmap.dcl which exports theOSBitmap structure as an opaque, abstract entity, now unveils its contents, copied from the.icl module:

:: OSBitmap= {originalSize :: !(!Int,!Int) // The size of the bitmap

reSize :: !(!Int,!Int) // We never used this.bitmapContents :: !{#Char} // This we badly need! (J.K.)bitmapHandle :: !Int // The handle...

}

We are aware that in a sense we are violating the integrity of the standard library, but we have no remorses.Bitmap handling in the actual version of the IO subsystem is hopelessly poor, and we are convinced that inorder to develop it, either some system-dependent details must be accessible, or more powerful interfacingfunctions implemented.

The modifiedosbitmap.dcl is included in theExtras folder. Put it into the Object IO/OS Windowsfolder. It shouldn’t harm anything unless the I/O library authors decide one day to modify the Bitmap structure;then it should be straightforward to correct everything.

The Windows interface uses theNotice sub-package, defined in Object IO examples,gui utilities ,and also in the tutorial examples of Peter Achten. We put a copy of it in the folderExtras .

61

Appendix B

Further work and wishes

Oh, plenty of things to do, if the package is to be really used for concrete work. Of course, a more completeset of examples is needed. In particular we would like to code in Clean a dozen or so of typical RenderManexamples we used for our teaching.

But some mathematical, structural and interfacing utilities are needed as well. The list below should beshorter in the next versions, provided they will ever appear. . . Some of the ideas below are for a straightforwardimplementation, and others are dreams and explosions of wishful thinking, put here in order not to forget them.

B.1 Optimization

The package and this tutorial must be completed and corrected. In particular what is missing is aseriouswork on optimization. The actual version is rather slow. No caching of repetitive structures, almost nomacros/inlining, and heavy load on the garbage collector, since Clastic routines produce a good deal of in-termediate datastructures (mainly vectors). Next version might keep vectors at the user layer, but the primitiveswill most probably streamline the acces to compound data, passingx andy separately. Chains of functionsmay pass them as multiple values using CPS (provided we find that such style in Clean is implemented in asufficiently efficient way. . . ).

We should analyze better the strictness declarations, and the usage of unique objects. (But — frankly —we have no idea whether the presence or absence of attributes within the declarations change anything.) Somenice higher-order constructs within the basic layer should be simplified.

One day we have to think seriously about rewriting Clastic in Haskell. Apart from the utilitary viewpoint,this would be a really excellent exercice in type system changing and monadisation. Any takers?

B.2 Redaction

Ugh, rewrite all that! Add serious index. Gather and add all useful references, on texturing in general, randomnoise, tesselations, etc. The actual references are very incomplete.

Perhaps one day we will collect also all our exercises and include them here as well.

B.3 Interfacing

1. A progress gauge is badly needed. The actual interface may be called a lot of names, but never “con-current”. . . Actually, Clean programs under Windows are rather unfriendly, blocking the screen refresh,etc.

62

B.4 Base layer 63

2. We need more parameterization, the possibility to change some texture attributes without recompilation,and this is a prioritary upgrade. It would be nice, and not too difficult to define some data structuresrepresenting standard blocks, to write a parser for simple arithmetic and colour expressions, and permitto assemble the textures dynamically under the interface control. (This is a student project awaiting acandidate. . . Any volunteers?)

3. Clastic is not, andneverwill be an image-processing program, nor a fully-fledged visualizer, but someutilities such as post-filtering, colour shifts (e.g. gamma correction), and zooming would be quite useful.

4. A parametrizable way of generating several bitmap files from one generator, i.e., creating animations(perhaps MNGs, or just a set of images to be treated off-line by a MPEG encoder) seems interesting, andnot too difficult.

B.4 Base layer

1. We have to review seriously the manipulation of the alpha channel, transparency masks, etc. Add prim-itive combinators quite popular in image processing packages, such as mixing semi-transparent objects,trasferring only the hue, or only the luminance, etc. We didn’t do it, because we use just simple arithmeticoperations, but for a real user some shortcuts may be necessary.

2. We didn’t touch the problem of anti-aliasingseriously, when spatial frequencies of texture patterns are ofthe order of pixel size. Then some low-pass filtering should be used. Actually shrinking a bitmap textureis simply awful, but problems of that kind arise also in procedural objects.

3. Several function, especially the tesselators, still contain many cascading conditionals. Some more elab-orate periodic functions are needed.

B.5 Bitmap handling

1. Loading and saving JPEG and PNG files. This would be enough, no need really to output/input anythingelse. Full PNG might be rather difficult, must use public libraries. (This is another student project waitingfor a victim).

2. Some standard bitmap operations such as low-pass filtering (for down-resizing). Some other filters muchmore efficient directly on the pixel space, without passing first to the functional layer (waste of time forthe interpolation). Colour separation/management primitives.

3. Use bitmaps to cache replicated patters, useful for complex tesselations.

4. Some suggested, but not implemented manipulations (such as the classical algorithms for the halftoningof colour images) should be there.

B.6 Random stuff

1. Most probably we shall construct some faster noise functions, based on the original Perlin’s idea: tabulatefirst a set of random numbers assigned to the lattice (integer coordinates). Retrieving them should befaster than our ergodic functions.

2. Implement the simplectic noise suggested by Perlin (and never seen working).

B.7 Mappings and deformations 64

3. Some non-linear transformations producing random distributions with different spectral properties willbe needed one day. Poisson noise in 2 and 3D; Gaussian bumps, etc. In RenderMan shaders there isplenty of them, but badly documented (if at all), and thrown-inad hoc, for specific purposes.

4. Implement multi-frequence noise by spectral synthesis (using some base functions, e.g., trigonometric,with random phases and coefficients). This should produce more regular functions than those generatedby piece-wise interpolations.

5. Generalize the “bombing” algorithm, permitting to render fuzzy objects, which may interact (anotherway of making smoke, etc.; may be difficult.)

B.7 Mappings and deformations

In general, more examples are needed.

1. Work on hyperbolic projections, fish-eye camera, etc.

2. Add a torus to the 3D panoply.

B.8 Non-local texturing procedures

This is a highly speculative part of our dreams, but perhaps useful. A texture viewed as just a local functionfrom points to colours often does not correspond to a physical process which generates a realistic pattern.

1. Implement a differential equation solver and code some reaction-diffusion patterns. Greg Turk patternsare really very nice [22].

2. Optimize the LIC (Linear Integral Convolution) algorithm, in order to visualize vector fields. Implementthe deformed spot noise for the same purpose, it should be much faster [24].

3. Learn how to make textures using Voronoi cells, and how to implement them efficiently within ourframework.

B.9 Tesselation package

1. Complete the wallpaper package, implement all the groups. Implement also the “rosette” and “frieze”subgroups (rotations and reflections only; 1-dim translations only).

2. The reduction procedureshould transmit also the information about the “cell number”, the integral partof the coordinates, and also identify the reduced FR instance; this will enable the changing of colour orother attributes from one cell to another. We did it with the reptiles, but this was a solutionad hoc.

This is really important: a parquet where all wooden tiles are identical is bad. So, the random texturegenerator for one tile migh use the cell number in order to change something (add an offset, vary thecolour a little bit, etc.)

3. Work a bit more on generic weaving algorithms, there is plenty of nice solutions to discover; octogonaland hex lattices of threads, etc., found in Islamic or Celtic geometric decorations.

B.10 Differential stuff 65

B.10 Differential stuff

1. Complete the 3D differentiation procedures.

2. Use AD that to construct blending functions for contours; to re-parametrize deformations making themarea-preserving (a non-trivial problem).

3. Generalize the bump-mapping, include specular reflections.

B.11 General utilities

1. Code finally the 2-dim Fast Fourier stuff, and some image convolution/filtering procedures.

2. Something which is quite far from Clastic as it is now, but a project which started already (as a peda-gogical assignment): implement the pyramidal (Heeger et al.; perhaps some other, based on wavelets?)algoritm [23, 25] for theanalysis, andre-synthesisof “natural” textures.

All other suggestions are welcome. Thank you for your interest.

Appendix C

List of Useful Data Structures andProcedures

C.1 Introduction

Even if the current version of the package is a study, and much work is still needed, Clastic contains more than300 functions (and class instances), not counting some composite data types, and numerous numeric and colourconstants. The list below replaces a decent documentation, and may be useful, but it is not very well structured,nor complete. Please, look the.dcl files. In fact, most definitions are short, and the best way to learn them isjust to look at them. So, the list below should guide you rather than supply the full truth. This text is a tutorialrather than a formalistic manual. You should learn more from the text and from the examples.

C.2 General utilities

Many functions here are really trivial, but they are used in examples, so we acknowledge their existence.

• There are some abbreviations we needed, e.g.fR for fromReal .

• A large collection of numeric constants.Pi = π, Dpi = 2π, PiH = π/2, PiT = 3π/2, Pi3 = π/3, Pi4 =π/4, Pi6 = π/6, PiD = 2π/3, PiA = 4π/3, Sqrt2 =

√2, Sqrt3 =

√3, Sqrt5 =

√5, SqrtH =√

1/2, anddegrees = π/180. More constants, overloading commonly used numbers:zero, one,two, three,four, half, onethird, onequart .

• The definition of a generic Functor (fmap ) class, and a generic constructor classfzip permitting tocombine different structures element-wise.

• The classShowas in Haskell, and its instances for typical data: numbers, lists, tuples, Booleans, Maybes,vectors, etc. Contains the functionshow essentially equivalent totoString , andShowS, which takestwo arguments, the conversion of the first is concatenated with the second (this avoids the concatenationin longer print chains). Not really used in Clastic, but useful for testing.

• Auxiliary numeric functions:sqr, cube (rather silly. . . ), andsignum which returns overloadedzero, one , or one . Also: dsgn returning±1 depending on the argument parity (even is 1). Suchreal functions asfloor, nearest , andfrac returning what they should: nearest lower integer, near-est integer, and fractional part, andgfloor andgfrac — polymorphic, applicable to, and returninggeneralized numbers, e.g. differential entities.

• Plenty of related functions splitting number in their integer and fractional parts:entfr, entfrac,isplit, rsplit , positive modulopmod (standard mod is equal to rem, which seems to be a bug in

66

C.3 Function algebra 67

Clean). Functions which compute the maximum, minimum or both for 3 arguments or lists of arguments:min3, max3, minmax3, minmax .

• Other real functions, such asatan2 y x — the arctangent which yields the angle (in [0 –2π]) ofa point in polar system. The 0 – 1 interpolatorhermite x which returns3x2 − 2x3, a 5-th orderinterpolatorinpol5 : 10x3 − 15x4 + 6x5. The Catmull-Rom splinespline a−1 a0 a1 a2 x returninga cubic inx which goes froma0 to a1 whenx in [0 – 1]. A masking functioncmask c u v returningu if c is different from zero, v otherwise. An angle normalizator computing this angle mod2π.

• Some list utilities, such ascycle repeating infinitely a list andcyclst — a function generating acyclic indexing function for a finite list; more economic thancycle , used in weaving procedures.Element-wise sum, difference, product and quotient of two lists. Forward-difference generator:(∆u)l =ul+1 − ul.Also: map2 for lists of lists, and an interval generatorinterv a b n , splitting the interval [a – b]into n fragments.

• Somegenericvector procedures, applicable to 2- and 3-dimensional vectors, but also to colours, in fact toany structures which are vector-like. Aritmeticconstructor classes: <+>, <-> , which are there becausewe don’t have genuine multi-parametric classes, a generic scalar product constructor class<.> , theoverloaded:norm andnorm2 (norm squared), and the functionnormalize . Projections — paralleland perpendicular — of vectors on normalized axes:axproj andperp (very simple, actually theyshould be always inlined).

• Some linear and non-linear object interpolators:lint for numbers and vectors,cmix for functions,etc. A universal parameterised interpolatorinterpol , permitting to choose the interpolation methodamongFloor, Nearest, Linear, Hermite, Spline etc.

• Some auxiliary functions useful for treating BMP images ({#Char} tables): splitting an integer intobytes, its reconstruction.

C.3 Function algebra

• Arithmetic is lifted to functional domain, concretely such (and related) instances are defined:

instance + (a -> b) | + bwhere

(+) f g = \x -> f x + g x...instance / (a -> b) | / bwhere

(/) f g = \x -> f x / g xinstance ~ (a -> b) | ~ bwhere

~ f = \x -> ~(f x)instance zero (a->b) | zero bwhere

zero = \_ -> zeroinstance one (a->b) | one b

whereone = \_ -> one

instance two (a->b) | two b

C.4 Colours 68

wheretwo = \_ -> two

...instance abs (a->b) | abs bwhere

abs f = \x -> abs (f x)

instance fromReal (a->b) | fromReal bwhere

fromReal c = \_ -> fromReal c

etc., etc. There was no point in lifting unary operations, such asexp , etc. use just the composition.

• Functionsminf, maxf which lift min, max to functional domain (the original could not be over-loaded,minf returns a function which yields a Boolean, the type is incompatible). The functionpositf which truncates to zero iff x is negative.

• General, domain independent transformers of functions, such astranslated a f which returns\x -> f (x-a) , the functionscaled etc. All this may be used for scalars oranyvectors. More spe-cific (vectorial) transformations are in a different module. here we have generic transformerstransfanddisplace , discussed in the text.

• Replicators such astrain f which appliesgfrac to its argument. Clamping function:clamp whichlimits the range to [a – b], and ramp to: [0 – 1]. The filtering functionfmask which lifts cmask tofunctions.

C.4 Colours

• Colours are records:: RealCol a = {tr::a,tg::a,tb::a} with a usually real, between 0and 1, but we keep this generic, in order to be able to compute gradients in colour space using AD (noexample implemented yet). Colours form a vector space with all overloading you may need:zero ,adding, multiplying by scalars (instance of*> , equality, etc. FunctionsconvertCol andiconvColconvert between real colours and standard 3-byte RGBs.

• There is plenty of colour constants:RWhite, RRed, RBlue, RDarkGreen , etc., and constantcolour functions (textures):CRed = const RRed etc. The functionsaturmul saturates multi-plicatively a colour, dividing all components by the greates one (unless it is black, of course);lightenshifts up a colour, adding enough white to make one (or more) components equal to 1.

• There is a simple luminance calculator:L = 0.222R+0.707G+0.071B, and the convertersrgbtohsvandhsvtorgb between real RGB colours and the Hue-Saturation-Value space.

C.5 Vectors

• The basic definitions:

:: Vec3 a = V3 !a !a !a:: RVec3 :== Vec3 Real

:: Vec2 a = V2 !a !a:: RVec2 :== Vec2 !Real

C.6 Basic generators and transformers 69

for 2- and 3-dimensional vectors.

• Reasonably complete vector algebra. Addition, scalar product<.> , vector product in 2:skew , and 3dimensions:/\ ; the skew product in two dimensions yields a scalar. Multiplication of a vector by itsbase element (usually a number):*> . Division by a scalar:>/ . Instances ofnorm andnorm2 .

• Constants (axes):X3axis, Y3axis, Z3axis, X2axis,Y2axis . Of courseX3axis = V3 10 0 , etc.

• Functionstospher andfromspher , transforming between Cartesian(x, y, z), and spherical(r, ϑ, ϕ)coordinates. Rotations in 3D:rot3 cs co si n v , rotatingv about the (normalized) axisn, by anangle whose sine and cosine are given;rot3 parametrized by the angle. Functionfindrot n vwhich finds the axis and the angle (its cosine and sine) of a minimal rotation which transformsvinto avector parallel ton.

• Some specific manipulations in 2D. Functionskew computes the skew product.decomp2 u v pdecomposes the vector~p into contravariant coordinates(u, v) along the axes~u and~v: ~p = u~u + v~v.Became obsolete after the introduction of general tiling tools.

• Rotations in 2D:rot2cs, rot2 . Mirroring: refl p0 u p reflects the point~p in the line~x =~p0 + t~u.

• A solver of 2 linear equations using vector notation. Nothing original. . . Also, two procedures:fgrad3eps f p andfgrad2 eps f p which compute gradients off at a given point, using “cheap” finitedifferences with the step equal toε. This was coded originally to test the AD package, but we left that,since it is faster than the automatic differentiation, and works quite well.

• A function fbumpshade which should be defined elsewhere, which computes the lighting of a heightfield by finding its normal, and comparing with the “light” direction. Diffuse reflection only for themoment.

C.6 Basic generators and transformers

This is the “main stuff”, but as you will see, the actual functions are really simple.

• Typical transformersof textures(not of points): rotated angle , also rotated cs co si pa-rameterized by the cosine and the sine, useful if angle doesn’t change. Some related functions:ro-tated90, rotated45, rotated60 , and transposed . Some others, which reducex and/ory using the fractional part of the arguments:reduced, symreduced, redscaled which com-bines the reduction and scaling, etc. Combined transformers such asrepliq s = scaled s osymreduced . Also rotatedabout p0 angle rotating a texture around an arbitrary point.

• Some transformers in 3D:rotated3, rotated3 cs parameterized by the angle and the axis ofrotation.

• Several primitive generators discussed already:step, pulse , parameterizedxstep (shiftedstep ),xpulse . Replicators:trainpulse, symtrain , and their instances:symteeth = symtrainabs , etc. Others: filteredabs, filteredpulse, smoothstep , etc. The functionhy-pulse sharp from one side, smooth from the other, useful for weaving.

• unitdisk , anddisk parameterized. Band generators:xstripe, ystripe from 1-coordinatefunctions. Two checkerboards:checkers, chboard . Regularpolygon generator, and a regularstarregstar . Also: triangle parametrized by the three corners. We defined alsochboard3 withcheckerboard cubic pattern in 3D.

C.7 Mappings and deformations 70

C.7 Mappings and deformations

This module will grow, for the moment it contains just some simple examples. The generic higher-ordertransformerstransf , anddisplace are coded inCTFunalg .

• Higher-order transformers:transf which applies a vector transformer to a texture; its variantdis-place shifts a texture by a given amount. The funtiontrfshift v tfun p = v + tfun (p-v) which generates shifted transformations of a texture, and a translated deformertrftranslatep0 which uses the former. Also:trfturn , a functional which rotates deformers.

• Some specific deformation examples:whirl, vortex, lense .

• 3D mappings: functions which take a ViewScreen, object containing the camera and the ViewPoint, andconstruct intersections in 3D of a ray, and a surface; the result returned is a boolean (True if intersectionexists), the intersection point, the normal, and the relative vision vector, which may be useful to computespecular lighting. Three such mapping are defined now:spherepoint, cubepoint , andcylin-derpoint . OK, there is another one:proj plane , but different and much simpler, it finds simplythe intersection of a ray and a plane.

• The functionbumped which “bumps” one texture with another one; parametrized by the light positionand the normal (computed elsewhere).

C.8 Random stuff

• Some simple classical (congruential) random number generators.rand0, rand1 which act on aninteger seed and produce a tuple: (aReal,newSeed), with aReal in [0 – 1]. Two of them with differentparameters in case you want to be sure not to generate spurious correlations.

Four more:rand0 s, rand1 s with result symmetric between -1 and 1, andrand0 h, rand1 hreturning numbers in [−0.5 – 0.5]. Yes, anybody can define them, and the sense of putting in a libraryseveral similar instances is dubious, but we needed them, and the philosophy to leave in the library allfunctions used was applied. . .

Also, a simple Gaussian generator (two exemplars)randn0, randn1 which exploits the CentralLimit Theorem: adds 12 instances ofrand0 h (or rand1 h), producing a random value in [−6 –6], with mean zero, and variance 1. Almost a Gaussian, as everybody knows.

• Our main engine:ergodic , a pure functionInt -> Real with “crazy” behaviour, its value for anyargumentn is so uncorrelated withn, that it can be used as a random number between 0 and 1. Also:ergodics , with result between -1 and 1.

• Functionsergxy, ergxyz generating random values from pairs or triples of integer numbers.ergvecxyix iy a b generating a random vector, and returning its scalar product with(a, b).

• Main real noise functions:grnoise2, gennoise2 (the last one is more general) symmetric aroundzero,noise2 with positive values,grnoise3 , vecnoise2, vecnoise3 generating random vec-tors, etc.

• Functionalsfractsum2, fractsum3 summing contribution with various frequencies. Also, moregeneralfrsum , very generic, which subsumes the former; heavily overloaded.

• Function fractnoise2 summing scalar 2-dim noise.turbulence2, turbulence3 — sum-ming the abs. values of multifrequence (scalar!) noise in 2- and 3 dimensions. In order to sum vectornoise, usefrsum . If the co-domain of the noise is not scalar, it is difficult to distinguish turbulence and“fractal noise”.

C.9 Tesselation utilities 71

C.9 Tesselation utilities

This is a very incomplete, evolving package.

• We define two more normalized vector constantsT2axis andU2axis forming angles60◦ and120◦

degrees withX2axis , useful for triangular and hexagonal lattices.

• A generic composite data structureUnitCell (created bymkunitcell ) contains the coordinate con-version and reduction/reconstruction procedures, the norms of axes, the (fixed) angles between them, thedefinition of covariant coordinates, etc.

• The functionhextex generates an arbitrary hexagonal P1 lattice, and it paramerized by the unit cell,and by two point inside the cell which define the vertices of the hexagon (shared by 4 neighbouring UC).This function is used byregular hex , andbrickwall in order to produce textures shown in thetext.

• The functionp3reduce reduces the point to the FR of the P3 group, it doesnt move the Motif.

C.10 More math

• Actually we have here only the Automatic Differentiation package, Complex and Rational numbers(overloaded arithmetic; some textures based on relation between complex numbers are very nice), twoapplications of the AD subsystem:contour andbumpshade , and a short functionlic : generator ofa texture which visualizes a vector field, using the Linear Integral Convolution.

C.11 More examples

The moduleCTExamples contains some functions whichbelong elsewhere, and they are here only becausewe want finally to release the package and this tutorial.

• The veawing package, in particular the functionweave , the setts for the tartan patterns etc. are here.

• Some random “goodies”:truchet , dithering and “bombing” generators as well.

• Functionswarp, warpfold use a simple equation solver in order to propagate a local warp along anytrajectory.

• There are some 3D examples: projecting an image on a spherical surface, construction of a planet fromits surfacic and height (bump) maps, etc.

• Finally, some tesselation examples: Escher reptiles, a kaleidoscope generator, and a PG/PGG parquet.

C.12 Viewing routines

Here we describe all the stuff which deals with the “virtual” display, i.e., the manipulation of the intrinsictexture space and its conversion to pixels, and also the Windows iterfacing routines.

• Definition of the basic types:Texture a which may be a tagged function from a 2D point intoRColours, or a 3D texture, needing the point, the normal, and the line of vision.

• The definition ofLight . For the moment only an isotropic point source is used. It is created usingmklight .

C.12 Viewing routines 72

• TheViewport . Contains the parameters of the texturing zone, and defines the conversion proceduresfrom virtual to pixel space (and vice-versa). The functionmkviewport creates one. Another function:bmapport creates a fake viewport attached to a bitmap. The user specifiesxmin and xmax. Thebitmap reader makes available the width and the height, and all this is used to construct the rest, so thatthe aspect ratio is preserved.

• Bitmap handling procedures,readDib file andreadBmp filename world , which read bitmapfiles and construct texture generators. The functionwriteDib saves a texture stored as a DiB array.makeDib creates this array, usessetPixel to index it.The function makedib is the principal workhorse, which iterates over all pixels of the texture zone. The functiongetPixel retrieves a pixelfrom a bitmap array, andbmapToTx performs the actual conversion between a DiB, and our “standard”functional texture. There is alsomakebmaptx paramterized by the file name, etc. Makes it possible totile directly the bitmap in one or two dimensions.

• The definition ofCamera, with its position,look at , andup vectors, and its focal parameter. Also,the definition of theViewScreen structure which contains a camera, a list of lights, and a generic rayspecification. It is created bymkview , andmkvscreen .

• A few additional functions such asaddlights, diffuselight, lightview — which facili-tate the construction of various lighting conditions, andsolidtx — the generic renderer of 3D-textures.

• We pass to windowing procedures, which actually work under Windows only. There are actually twosimple interfaces, one primitive SDI, and another MDI, more elaborate. We cannot describe the detailshere. The SDI interface demands firs the construction of a viwport which precise the size of the texture;the functionmkvport is used. Then the functiontexturwin takes the viewport as it first parameter,and constructs a window. It launchesmkportwin which attaches the viewport to the window, andpasses to it the “renderer”, theWindowLook function which iterates over all the pixels of the texture,usingmakedib .

• The MDI interface applies to theWorld the functionRender = txdialog textureset , wheretextureset returns the world paired with a list of pairs: (title,Texture). The functiontxdialogstarts the wholme business. allocates someids, initializes the list of windows, the menus, etc. All isessentially straightforward and easy to manipulate, provided you decide first to learn some intricacies ofthe Clean IO system. . . .

Bibliography

[1] David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley,Texturing and Model-ing. A Procedural Approach, AP Professional, (1998).

[2] Bryan et Lisa Gibson-Winge,Texture Synthesis, www.threedgraphics.com/texsynth .

[3] John C. Hart,Procedural Texturing, Web course, available from the sitegraphics.eecs.wsu.edu/cpts548/procedural/sld0001.htm .

[4] Steve Upstill,The RenderMan Companion: A Programmer’s Guide to Realistic Computer Graphics,Addison-Wesley, (1990).

[5] Larry Gritz, Blue Moon Rendering Tools, Exluna Inc.,www.exluna.com/bmrt/ .

[6] Web sitewww.pixar.com .

[7] Rinus Plasmaijer, Marko van Eekelen,Concurrent Clean Language Report, Version 1.3, HILT B.V. andUniversity of Nijmegen, (1998). See alsowww.cs.kun.nl/~clean .

[8] Spencer Kimball, Peter Mattis,GIMP, www.gimp.org .

[9] Sean Gibb, Peter Graumann,SynTex, Synthetic Realms, Calgary, Canada. Web sitewww.SyntheticRealms.com .

[10] Conal Elliott, Functional Images, research.microsoft.com/~conal/Pan with references,plenty of additional documentation and examples.

[11] Pedagoguery Software Inc.,GrafEq, www.peda.com/grafeq .

[12] Jules Bloomenthal (ed.),Introduction to Implicit Surfaces, Morgan Kaufmann, (1997).

[13] Ken Perlin,www.noisemachine.com , see alsomrl.nyu.edu/perlin .

[14] Hugo Elias, tutorial,freespace.virgin.net/hugo.elias .

[15] POV-Team, Persistence of Vision Ray-Tracer, Version 3.1 User’s Documentation(1999),www.povray.org .

[16] Doris Schattschneider,The Plane Symmetry Groups: Their recognition and notation, American Math.Monthly. 85, pp. 439–450, (1978).

[17] Xah Lee, The Discontinuous Groups of Rotation and Translation in the Plane, Web pageswww.best.com/~xah/ . This site contains a comprehensive overview of literature.

[18] David E. Joyce, Wallpaper Groups (Plane Symmetry Groups), tutorial. Web sitealeph0.clarku.edu/~djoyce/home.html .

73

BIBLIOGRAPHY 74

[19] J. Karczmarczuk,Functional Differentiation of Computer Programs, Journal of Higher Order and Sym-bolic Computing14, (2001), pp. 35–57.

[20] George Wolberg,Digital Image Warping, IEEE Comp. Soc. Press, (1990).

[21] A.V. Shubnikov, V.A. Koptsik,Symmetry in Science and Art, Plenum Press, (1974).

[22] Greg Turk,Generating Textures on Arbitrary Surfaces Using Reaction-Diffusion.

[23] Li-Yi Wei, Marc Levoy, Fast Texture Synthesis using Tree-structured Vector Quantization, seehttp://graphics.stanford.edu/projects/texture/ .

[24] Willem C. de Leeuw, Jarke J. van Wijk,Enhanced Spot Noise for Vector Field Visualization.

[25] Robert Brumley,Wavelets for Texture Analysis.