• fullscreen
• NoiseBasedWarping.pde
• _1_DomainWarper.pde
• _2_DomainStrategy.pde
• ```/*--------------------------------------------------------------------------------------------------------------------------------
Noise Based Warping Explorer
Ale González · 2012 · Dominio Público | Public Domain
----------------------------------------------------------------------------------------------------------------------------------
A explorer of noise based warping, as explained here: http://www.iquilezles.org/www/articles/warp/warp.htm
And as pointed out here: http://amnonp5.wordpress.com/2012/06/17/playing-with-glsl-in-processing/
----------------------------------------------------------------------------------------------------------------------------------

The process as described basically by Iñigo:
"Say you have some geometry or image defined as a function of space. For geometry, that would be a function of the form f(x,y,z)
and for an image it would be f(x,y). We can just write both cases more compactly as f(p), where p is the position in space for
which we can evaluate the volumetric density that will define our (iso)surface or image color. Warping simply means we distort
the domain with another function g(p) before we evaluate f. Basically, we replace f(p) with f(g(p)). g can be anything, but often
we want to distort the image of f just a little bit with respect its regular behabiour. Then, it makes sense to have g(p) being
just the identiy plus a small arbitary distortion h(p), or in other words,

g(p) = p + h(p),

meaning we will be computing

f( p + h(p) )

This technique is really powerful and allows you to shape apples, buildings, animals or any other thing you might imagine. For the
purpose of this article, we are going to work only with fbm based patterns, both for f ang h. This will produce some abstract but
beautiful images with a pretty organic quality to them."

----------------------------------------------------------------------------------------------------------------------------------
Thanks to both, Íñigo and Amnon, for dedicating so much time to share. ;-)
----------------------------------------------------------------------------------------------------------------------------------
Font: 'sw!ft' by orgdot, as shared on dafont, http://www.dafont.com/orgdot.d518. Thanks again!
--------------------------------------------------------------------------------------------------------------------------------*/

/*
Global variables and objects
*/

//Canvas size
final int W= 500, H= 500;

//A font to output frameRate
PFont theFont;

//Default level of recursion and text properties
int level = 1,
txt_x = 25,
txt_y = 25,
txt_c = 0xddffff00,
txt_s = 10;

//default values to instantiate the noise domain and warper objects
float
perlin_x= .01,
perlin_y= .01,
simplex_x= .0045,
simplex_y= .0045,
min_V = -1f,
max_V =  1f,
vK=4f;

boolean
moving = false,
hud     = true;

DomainStrategy domain;
DomainWarper   warper;

/*
Main methods
*/

void setup(){
size (W,H,P2D);
cursor (CROSS);
domain  = new Perlin  (255, perlin_x, perlin_y);
warper  = new DomainWarper (level, min_V, max_V, vK);
fill (txt_c);
}

void draw(){
if (moving) {warper.x2--; warper.y1++;}
//Iterate over screen pixels
for (int y=0, yW=0; y<H; y++, yW+=W) {
for(int x=0; x<W; x++) {
//And use domain values (v) to set grayscale values to them, using the domain function provided
int v = (int) warper.getValue (x,y, domain);
pixels[x+yW] = v<<16|v<<8|v;
}
}
updatePixels();
if (hud) text ("Level: " + level + " - K: " + vK + " - Framerate: " + nfc(frameRate,2), txt_x, txt_y);
}

/*
Some interaction here:
· Move mouse to shift the warping, acting onto one of the vectors that define the parent of the tree structure
· Keys:
'1'    : use Perlin noise based domain
'2'    : use Simplex noise based domain
'Up'   : increase level of recursion (up to 5)
'Down' : decrease level of recursion (down to 0).
*/

void mousePressed(){
switch (mouseButton) {
case (LEFT):
moving= !moving;
break;
case (RIGHT):
hud = !hud;
break;
}
}

void keyPressed(){
if (key!=CODED) {
switch (key) {
case (KeyEvent.VK_1) : //key '1' constant value as implemented in KeyEvent Java class
domain = new  Perlin (255, perlin_x, perlin_y);
break;
case (KeyEvent.VK_2) : //...
domain = new Simplex (255, simplex_x, simplex_y);
break;
}
} else {
if      (keyCode==UP    && level<10) warper= new DomainWarper (++level, min_V, max_V, vK);
else if (keyCode==DOWN  && level>1)  warper= new DomainWarper (--level, min_V, max_V, vK);
else if (keyCode==RIGHT && vK<=10)   warper= new DomainWarper (level, min_V, max_V, ++vK);
else if (keyCode==LEFT  && vK>=0)    warper= new DomainWarper (level, min_V, max_V, --vK);
}
}
```
```/*
A domain-based compound warper.
Each possible level of recursion is encapsulated in a warper object inside a unary tree structure
*/

class DomainWarper {

//Each warping level is 'described' by two points, defined by the vectors: v1{x1,y1} and v2{x2,y2}
//k is a constant that scales the effect of the correspondent recursion level
float x1, y1, x2, y2, k;

//Further depth level, only accesible from its direct parent
private DomainWarper child;

/*
Constructors
*/

//Create a custom warper from given parameters
DomainWarper (float x1, float y1, float x2, float y2, float k) {
this.x1=x1; this.y1=y1;
this.x2=x2; this.y2=y2;
this.k=k;
child = null;
}

//Create a warper of given depth, defined at each level by a given k and random vectors,
//using a float range minV<-->maxV.
DomainWarper (int level, float minV, float maxV, float k){
x1= random (minV, maxV); y1= random (minV, maxV);
x2= random (minV, maxV); y2= random (minV, maxV);
this.k=k;
if(--level>0) this.addLevel (new DomainWarper(level, minV, maxV, k));
}

/*
Methods
*/

/*
To add recursively a new level, defined by a Warper child:
If the node is a leaf, add it the new child, else traverse its children until a leaf is found and the warper is finally added to this one
*/
if (child==null) child=rw; else child.addLevel (rw);
}

/*
This method calculates recursively the sum of associated vectors of parent node and its children. The associated vector of a warper object is
defined by calculating its coordinates as the result of applying the domain algorithm to p{x,y}+v1 and p+v2, scaled by the k coefficient afterwards.
*/
PVector getLevelVector (int x, int y, DomainStrategy domain) {
PVector levelVector = new PVector (domain.getValue (x+x1, y+y1) *k, domain.getValue (x+x2, y+y2) *k);
if (child!=null) levelVector.add (child.getLevelVector (x, y, domain));
return levelVector;
}

/*
The main output of the object is this value, result of applying the domain algorithm to
the associated vector of the parent of the tree
*/
float getValue (int x, int y, DomainStrategy domain) {
PVector v = getLevelVector (x, y, domain);
return domain.getValue (x+v.x, y+v.y);
}
}
```
```/*
Interface DomainStrategy.
I have preferred to encapsulate different domain math algorithms in objects
implementing this interface in order to be easily extended, keeping clean
the warper class.
*/

interface DomainStrategy {
float getValue (float x, float y);
}

/*
This one uses Perlin noise as ported to P5 by Toxi from the original implementation
by german demo group Farbrausch: http://www.farb-rausch.de/fr010src.zip
Original implementation: Ken Perlin, 1984
*/

class Perlin implements DomainStrategy {

float magnitude, kX, kY;

Perlin (float magnitude, float kX, float kY) {
this.magnitude   = magnitude;
this.kX = kX; this.kY = kY;
}

float getValue (float x, float y) {
return magnitude * noise (kX*x, kY*y);
}
}

/*
Simplex noise as implemented by Toxi in his Math library, and as described in
this paper by Stefan Gustavson: http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf.
Original implementation: Ken Perlin, 2001
http://mrl.nyu.edu/~perlin/paper445.pdf    Siggraph 2002 paper explaining the new algorithm
http://mrl.nyu.edu/~perlin/noise/          the raw code -- quite hardcoded, compact, beautiful... and absolutely impenetrable :-)
*/

import toxi.math.noise.SimplexNoise;

class Simplex implements DomainStrategy {

float magnitude, kX, kY;

Simplex (float magnitude, float kX, float kY) {
this.magnitude   = magnitude;
this.kX = kX; this.kY = kY;
}

float getValue (float x, float y) {
//Simplex yields values from -1d to 1d unlike standard P5 noise implementation (that gives values from 0 to 1f),
//so this object yields the absolute value casted to float:
return  magnitude * abs((float) SimplexNoise.noise(kX*x, kY*y));
}
}
```

### tweaks (0)

This sketch is running as Java applet, exported from Processing.

Report Sketch

Report for inappropriate content

Your have successfully reported the sketch. Thank you very much for helping to keep OpenProcessing clean and tidy :)

## NoiseBasedWarping_Explorer

19

This sketch tries to go deep into noise based warping, a technique described by Iñigo Quilez here:
http://www.iquilezles.org/www/articles/warp/warp.htm
and pointed out by Amnon Owed here:
http://amnonp5.wordpress.com/2012/06/17/playing-with-glsl-in-processing/
(Thanks to both)

I've done the sketch as an exercise that tries to understand the technique and to observe the effect of the different parameters involved in the final result. I've designed it with this objective in mind, so it isn't a much efficient design for real time animations.

ale plus+
1 Sep 2012
Interaction:
- Key UP -- Add a domain
- Key DOWN -- Remove it
- Key RIGHT -- Increase the coeficient that scales the effect of each domain into the whole
- Key LEFT -- Decrease it
- Key 1 -- Standard P5 Perlin noise
- Key 2 -- Simplex Noise
- Mousebutton LEFT -- Toggle animating the vectors that define the domain
- Mousebutton RIGHT -- Toggle showing the Info

Conclusions:
- If you want to get rich effects for real time is best to increase the coefficient (vK in the Code) instead of increasing the level of complexity. Maths are very expensive here.
- Simplex is by far more efficient than simple noise but the effect is less interesting in organic terms.
- For real-time is better to use a LUT approach, storing in a PVector[level][x][y] all level vectors. This increases x2 the framerate although is quite expensive in memory terms, so it isn't a useful approach (for instance) to get hi-res pictures. It'd be a good exercise to create a general-purpose design for the class Warper.

Font: 'sw!ft' by orgdot, as shared on dafont, http://www.dafont.com/orgdot.d518. Thanks again!
R.A. Robertson
4 Sep 2012
Absolutely amazing.

This is exactly the kind of terrain I've been trying to explore lately, without making any progress.
I'll be studying this.

Thank you.
ale plus+
11 Sep 2012
You're welcome!
:-)
You need to login/register to comment.