Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div style="position:absolute; left:50%; top:50%; margin-left:-450px; margin-top: -300px;">
    <div id="main" style="position:relative; display: block; width: 900px; height: 600px;">        
        <canvas id="canvas" style="position:relative;"></canvas>
    </div>
</div>

<script>
    function getIEVersion() {
        var rv = -1; // Return value assumes failure.
        if (navigator.appName == 'Microsoft Internet Explorer') {
            var ua = navigator.userAgent;
            var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
            if (re.test(ua) != null)
                rv = parseFloat( RegExp.$1 );
        }
        return rv;
    }


    function checkVersion() {
        var ver = getIEVersion();

        if ( ver != -1 ) {
            if (ver <= 9.0) {
                document.body.innerHTML = "";
                document.body.innerHTML =
                        "<p class='no-canvas'>" +
                                "You need a <a href='https://www.google.com/chrome'>modern browser</a> to view this experiment." +
                        "</p>";
            }
        }
    }

    checkVersion();

</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js" type="text/javascript"></script>
              
            
!

CSS

              
                html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #111;
    margin: 0;
    padding: 0;
    -webkit-user-select: none;
    -moz-user-select: none;
    -khtml-user-select: none;
    user-select: none;
}

/*******************************
* Main display
********************************/

div#main {
    width: 100%;
    margin: 0 auto;
    border: 1px solid #222;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    -ms-border-radius: 2px;
    -o-border-radius: 2px;
    border-radius: 2px;

    -webkit-box-shadow: 0px 2px 17px rgba(0,0,0,.80), inset 0 0 15px 15px rgba(5,5,5,.2);
       -moz-box-shadow: 0px 2px 17px rgba(0,0,0,.80), inset 0 0 15px 15px rgba(5,5,5,.2);
            box-shadow: 0px 2px 17px rgba(0,0,0,.80), inset 0 0 15px 15px rgba(5,5,5,.2);
}

canvas {
    width: 740px;
    height: 480px;
    float:left;
    margin-left: 2%;
    margin-top: 2%;
    width: 96%; height: 94%;
    -webkit-border-radius: 4px;
       -moz-border-radius: 4px;
        -ms-border-radius: 4px;
            border-radius: 4px;

    border: 1px solid rgba(0,0,0,.2);
    -webkit-box-shadow: inset 0 0 20px #000;
       -moz-box-shadow: inset 0 0 20px #000;
        -ms-box-shadow: inset 0 0 20px #000;
            box-shadow: inset 0 0 20px #000;
}

.no-canvas {
	  color: #999999;
	  font-size: 24px;
	  text-align: center;
	  margin-top: 150px;
}

              
            
!

JS

              
                function CellDataStruct(maxOrder, at) {
    this.dim = at.length;
    this.at = at;
    this.maxOrder = maxOrder;
    this.F = new Array(maxOrder);
    this.delta = new Array(new Array(maxOrder), new Array(at.length));
    this.ID = new Array(maxOrder);
}

function CellNoise() {
    
    this.b32 = Math.pow(2,32);
    this.Constants = {
        POISON_COUNT : [
            4, 3, 1, 1, 1, 2, 4, 2, 2, 2, 5, 1, 0, 2, 1, 2, 2, 0, 4, 3, 2, 1, 2,
            1, 3, 2, 2, 4, 2, 2, 5, 1, 2, 3, 2, 2, 2, 2, 2, 3, 2, 4, 2, 5, 3, 2,
            2, 2, 5, 3, 3, 5, 2, 1, 3, 3, 4, 4, 2, 3, 0, 4, 2, 2, 2, 1, 3, 2, 2,
            2, 3, 3, 3, 1, 2, 0, 2, 1, 1, 2, 2, 2, 2, 5, 3, 2, 3, 2, 3, 2, 2, 1,
            0, 2, 1, 1, 2, 1, 2, 2, 1, 3, 4, 2, 2, 2, 5, 4, 2, 4, 2, 2, 5, 4, 3,
            2, 2, 5, 4, 3, 3, 3, 5, 2, 2, 2, 2, 2, 3, 1, 1, 5, 2, 1, 3, 3, 4, 3,
            2, 4, 3, 3, 3, 4, 5, 1, 4, 2, 4, 3, 1, 2, 3, 5, 3, 2, 1, 3, 1, 3, 3,
            3, 2, 3, 1, 5, 5, 4, 2, 2, 4, 1, 3, 4, 1, 5, 3, 3, 5, 3, 4, 3, 2, 2,
            1, 1, 1, 1, 1, 2, 4, 5, 4, 5, 4, 2, 1, 5, 1, 1, 2, 3, 3, 3, 2, 5, 2,
            3, 3, 2, 0, 2, 1, 1, 4, 2, 1, 3, 2, 1, 2, 2, 3, 2, 5, 5, 3, 4, 5, 5,
            2, 4, 4, 5, 3, 2, 2, 2, 1, 4, 2, 3, 3, 4, 2, 5, 4, 2, 4, 2, 2, 2, 4,
            5, 3, 2
        ],

        DENSITY_ADJUSTMENT : 0.398150,
        DENSITY_ADJUSTMENT_INV : 1.0 / 0.398150
    };

}

CellNoise.prototype.noise = function(cd) {
    if (cd.dim == 3) {
        /*
         * Adjustment variable to make F[0] average 1.0 when using
         * EUCLIDEAN distance in 3D
         */
        this.Constants.DENSITY_ADJUSTMENT = 0.294631;
        this.Constants.DENSITY_ADJUSTMENT_INV = 1.0 / this.Constants.DENSITY_ADJUSTMENT;
        this.noise3D(cd);
    } else if (cd.dim == 2) {
        /*
         * Adjustment variable to make F[0] average at 1.0 when using
         * EUCLIDEAN distance in 2D
         */
        this.Constants.DENSITY_ADJUSTMENT = 0.294631;
        this.Constants.DENSITY_ADJUSTMENT_INV = 1.0 / this.Constants.DENSITY_ADJUSTMENT;
        this.noise2D(cd);
    }
}

/*
 * Noise function for three dimensions.
 * Coordinating the search on the above cube level.
 * Deciding in which cube to search.
 */
CellNoise.prototype.noise3D = function (cd) {
    var x2, y2, z2, mx2, my2, mz2;
    var newAt = new Array(3);
    var intAt = new Array(3);
    var i;

    for (i = 0; i < cd.maxOrder; i++) {
        cd.F[i] = Number.POSITIVE_INFINITY;
    }
    
    newAt[0] = this.Constants.DENSITY_ADJUSTMENT * cd.at[0];
    newAt[1] = this.Constants.DENSITY_ADJUSTMENT * cd.at[1];
    newAt[2] = this.Constants.DENSITY_ADJUSTMENT * cd.at[2];

    intAt[0] = ~~newAt[0];
    intAt[1] = ~~newAt[1];
    intAt[2] = ~~newAt[2];

    /*
     * The center cube. It's very likely that the closest feature
     * point will be found in this cube.
     */

    this.Add3DSamples(intAt[0], intAt[1], intAt[2], newAt, cd);

    x2 = newAt[0] - intAt[0];
    y2 = newAt[1] - intAt[1];
    z2 = newAt[2] - intAt[2];

    mx2 = (1.0 - x2) * (1.0 - x2);
    my2 = (1.0 - y2) * (1.0 - y2);
    mz2 = (1.0 - z2) * (1.0 - z2);

    x2 *= x2;
    y2 *= y2;
    z2 *= z2;

    /*
     * Check the 6 facing cubes from sample location.
     * These are most likely the closest locations to have feature points
     */

    if ( x2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1], intAt[2], newAt, cd); }
    if ( y2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] - 1, intAt[2], newAt, cd); }
    if ( z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1], intAt[2] - 1, newAt, cd); }
    if (mx2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1], intAt[2], newAt, cd); }
    if (my2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] + 1, intAt[2], newAt, cd); }
    if (mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1], intAt[2] + 1, newAt, cd); }

    /*
     * The 12 edge cubes. These are next closest.
     */

    if ( x2 +  y2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] - 1, intAt[2], newAt, cd); }
    if ( x2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1], intAt[2] - 1, newAt, cd); }
    if ( y2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] - 1, intAt[2] - 1, newAt, cd); }
    if (mx2 + my2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] + 1, intAt[2], newAt, cd); }
    if (mx2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1], intAt[2] + 1, newAt, cd); }
    if (my2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] + 1, intAt[2] + 1, newAt, cd); }
    if ( x2 + my2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] + 1, intAt[2], newAt, cd); }
    if ( x2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1], intAt[2] + 1, newAt, cd); }
    if ( y2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] - 1, intAt[2] + 1, newAt, cd); }
    if (mx2 +  y2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] - 1, intAt[2], newAt, cd); }
    if (mx2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1], intAt[2] - 1, newAt, cd); }
    if (my2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0], intAt[1] + 1, intAt[2] - 1, newAt, cd); }

    /*
     * The 8 corner cubes.
     */

    if ( x2 +  y2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] - 1, intAt[2] - 1, newAt, cd); }
    if ( x2 +  y2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] - 1, intAt[2] + 1, newAt, cd); }
    if ( x2 + my2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] + 1, intAt[2] - 1, newAt, cd); }
    if ( x2 + my2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] + 1, intAt[2] + 1, newAt, cd); }
    if (mx2 +  y2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] - 1, intAt[2] - 1, newAt, cd); }
    if ( x2 + my2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] - 1, intAt[1] + 1, intAt[2] - 1, newAt, cd); }
    if (mx2 +  y2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] - 1, intAt[2] + 1, newAt, cd); }
    if (mx2 + my2 +  z2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] + 1, intAt[2] - 1, newAt, cd); }
    if (mx2 + my2 + mz2 < cd.F[cd.maxOrder - 1]) { this.Add3DSamples(intAt[0] + 1, intAt[1] + 1, intAt[2] + 1, newAt, cd); }

    for (i = 0; i < cd.maxOrder; i++) {
        cd.F[i] = Math.sqrt(cd.F[i] * this.Constants.DENSITY_ADJUSTMENT_INV);
        cd.delta[i][0] *= this.Constants.DENSITY_ADJUSTMENT_INV;
        cd.delta[i][1] *= this.Constants.DENSITY_ADJUSTMENT_INV;
        cd.delta[i][2] *= this.Constants.DENSITY_ADJUSTMENT_INV;
    }
}

CellNoise.prototype.noise2D = function(cd) {
    var x2, y2, mx2, my2, i;
    var newAt = new Array(2);
    var intAt = new Array(2);

    for (i=0; i < cd.maxOrder; i++) {
        cd.F[i] = Number.POSITIVE_INFINITY;
    }

    newAt[0] = this.Constants.DENSITY_ADJUSTMENT * cd.at[0];
    newAt[1] = this.Constants.DENSITY_ADJUSTMENT * cd.at[1];

    intAt[0] = ~~newAt[0];
    intAt[1] = ~~newAt[1];

    /*
     * The center cube. It's very likely that the closest feature
     * point will be found in this cube.
     */

    this.Add2DSamples(intAt[0], intAt[1], newAt, cd);

    x2 = newAt[0] - intAt[0];
    y2 = newAt[1] - intAt[1];

    mx2 = (1.0 - x2) * (1.0 - x2);
    my2 = (1.0 - y2) * (1.0 - y2);
    x2 *= x2;
    y2 *= y2;

    /*
     * Check the 4 facing cubes from sample location.
     * These are most likely the closest locations to have feature points
     */

    if ( x2 < cd.F[cd.maxOrder - 1]) { this.Add2DSamples(intAt[0] - 1, intAt[1], newAt, cd); }
    if ( y2 < cd.F[cd.maxOrder - 1]) { this.Add2DSamples(intAt[0], intAt[1] - 1, newAt, cd); }
    if (mx2 < cd.F[cd.maxOrder - 1]) { this.Add2DSamples(intAt[0] + 1, intAt[1], newAt, cd); }
    if (my2 < cd.F[cd.maxOrder - 1]) { this.Add2DSamples(intAt[0], intAt[1] + 1, newAt, cd); }

    /*
     * Check the 4 square cubes from sample location.
     * These are probably much distant then the nearby cubes
     */

    if (x2 + y2 < cd.F[cd.maxOrder - 1])   { this.Add2DSamples(intAt[0] - 1, intAt[1] - 1, newAt, cd); }
    if (x2 + my2 < cd.F[cd.maxOrder - 1])  { this.Add2DSamples(intAt[0] - 1, intAt[1] + 1, newAt, cd); }
    if (mx2 + y2 < cd.F[cd.maxOrder - 1])  { this.Add2DSamples(intAt[0] + 1, intAt[1] - 1, newAt, cd); }
    if (mx2 + my2 < cd.F[cd.maxOrder - 1]) { this.Add2DSamples(intAt[0] + 1, intAt[1] + 1, newAt, cd); }

    for (i = 0; i < cd.maxOrder; i++) {
        cd.F[i] = Math.sqrt(cd.F[i]) * this.Constants.DENSITY_ADJUSTMENT_INV;
        cd.delta[i][0] *= this.Constants.DENSITY_ADJUSTMENT_INV;
        cd.delta[i][1] *= this.Constants.DENSITY_ADJUSTMENT_INV;
    }
}

/*
 * Generating the sample points in 3D
 */

CellNoise.prototype.Add3DSamples = function(xi, yi, zi, at, cd) {
    var dx, dy, dz, fx, fy, fz, d2, abs = Math.abs;
    var count, i, j, index, seed, id;
    /*
     * Generating a random seed, based on the cube's ID number. The seed might be
     * better if it were a nonlinear hash like Perlin uses for noise, but we do very
     * well with this faster simple one.
     * Our LCG uses Knuth-approved constants for maximal periods.
     */

    seed = this.u32(this.u32(702395077 * xi) + this.u32(915488749 * yi) + this.u32(2120969693 * zi));

    // Number of feature points in this cube
    count = this.Constants.POISON_COUNT[parseInt(0xFF & (seed >> 24))];
    seed = this.u32(1402024253 * seed * 586950981);

    for (j = 0; j < count; j++) {
        id = seed;
        seed = this.u32(1402024253 * seed + 586950981);

        // Compute the 0..1 feature point xyz's location
        fx = (seed + 0.5) / 4294967296.0;
        seed = this.u32(1402024253 * seed + 586950981);
        fy = (seed + 0.5) / 4294967296.0;
        seed = this.u32(1402024253 * seed + 586950981);
        fz = (seed + 0.5) / 4294967296.0;
        seed = this.u32(1402024253 * seed + 586950981);

        /* Calculate distance from feature point to sample location*/

        dx = xi + fx - at[0];
        dy = yi + fy - at[1];
        dz = zi + fz - at[2];

        /*
         * Distance computation
         */
        if (GUI.renderMethod == 1) {
            d2 = dx*dx + dy*dy + dz*dz;
        } else if (GUI.renderMethod == 2) {
            d2 = Math.max(Math.max(abs(dx), abs(dy)), abs(dz));
            d2 *= d2;
        } else if (GUI.renderMethod == 3) {
            d2 = abs(dx) + abs(dy) + abs(dz);
            d2 *= d2;
        } else if (GUI.renderMethod == 4) {
            d2 = dx*dx + dy*dy + dz*dz + dx*dy + dx*dz + dy*dz;
            d2 *= d2;
        }

        /* Store the closest points */

        //Calculate the closest feature point distance to sample location
        if (d2 < cd.F[cd.maxOrder - 1]) {
            index = cd.maxOrder;
            while(index > 0 && d2 < cd.F[index-1]) {
                index--;
            }

            for (i = cd.maxOrder - 1; i-- > index; ) {
                cd.F[i + 1] = cd.F[i];
                cd.ID[i + 1] = cd.ID[i];
                cd.delta[i + 1][0] = cd.delta[i][0];
                cd.delta[i + 1][1] = cd.delta[i][1];
                cd.delta[i + 1][2] = cd.delta[i][2];
            }

            cd.F[index] = d2;
            cd.ID[index] = id;
            cd.delta[index][0] = dx;
            cd.delta[index][1] = dy;
            cd.delta[index][2] = dz;
        }
    }
    return this.Add3DSamples;
}


/*
 * Generating the sample points in 2D
 */

CellNoise.prototype.Add2DSamples = function(xi, yi, at, cd) {
    var dx, dy, fx, fy, d2, abs = Math.abs;
    var count, i, j, index, seed, id;
    /*
     * Generating a random seed, based on the cube's ID number. The seed might be
     * better if it were a nonlinear hash like Perlin uses for noise, but we do very
     * well with this faster simple one.
     * Our LCG uses Knuth-approved constants for maximal periods.
     */

    seed = this.u32(this.u32(702395077 * xi) + this.u32(915488749 * yi));

    // Number of feature points in this cube
    count = this.Constants.POISON_COUNT[parseInt(0xFF & (seed >> 24))];
    seed = this.u32(1402024253 * seed * 586950981);

    for (j = 0; j < count; j++) {
        id = seed;
        seed = this.u32(1402024253 * seed + 586950981);

        // Compute the 0..1 feature point xyz's location
        fx = (seed + 0.5) / 4294967296.0;
        seed = this.u32(1402024253 * seed + 586950981);
        fy = (seed + 0.5) / 4294967296.0;
        seed = this.u32(1402024253 * seed + 586950981);

        /* Calculate distance from feature point to sample location*/

        dx = xi + fx - at[0];
        dy = yi + fy - at[1];

        /*
         * Distance computation
         */

        if (GUI.renderMethod === 1) {
            d2 = dx*dx + dy*dy;
        } else if (GUI.renderMethod == 2) {
            d2 = Math.max(abs(dx), abs(dy));
            d2 *= d2;
        } else if (GUI.renderMethod == 3) {
            d2 = abs(dx) + abs(dy);
            d2 *= d2;
        } else if (GUI.renderMethod == 4) {
            d2 = dx*dx + dy*dy + dx*dy;
            d2 *= d2;
        }

        /* Store the closest points */

        if (d2 < cd.F[cd.maxOrder - 1]) {
            index = cd.maxOrder;
            while(index > 0 && d2 < cd.F[index-1]) {
                index--;
            }

            for (i = cd.maxOrder - 1; i-- > index;) {
                cd.F[i + 1] = cd.F[i];
                cd.ID[i + 1] = cd.ID[i];
                cd.delta[i + 1][0] = cd.delta[i][0];
                cd.delta[i + 1][1] = cd.delta[i][1];
            }

            cd.F[index] = d2;
            cd.ID[index] = id;
            cd.delta[index][0] = dx;
            cd.delta[index][1] = dy;
        }
    }
    return this.Add2DSamples;
}


CellNoise.prototype.u32 = function(s) {
    var st = s % this.b32;
    if (st < 0)
        st += this.b32;
    return st;
}

var noWebWorkers = (function() {
    var cn, cd,
        x, y, t = 0,
        freq = 0.15,
        at = [0, 0, 0];
    var that = this;
    cn = new CellNoise();
    cd = new CellDataStruct(2, at);

    return {
        render : function(method, render) {
            switch (method) {
                case 'cellDistanceDiff' :
                    cellDistanceDiff();
                    break;
                case 'cellDistanceDiffMod' :
                    cellDistanceDiffMod();
                    break;
                case 'firstOrderDistance' :
                    firstOrderDistance();
                    break;
                case 'secondOrderDistance' :
                    secondOrderDistance();
                    break;
                case 'noiseNoise' :
                    noiseNoise();
                    break;
                default :
                    draw();
            }
        }
    };

    /*
     * Different implementation methods provides different outputs.
     * Playing with values gives completely different shapes and dimensions.
     */

// Example 1. -> Cell Distance Difference

    function cellDistanceDiff() {
        at[2] += freq;
        t += freq;
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(y * canvasWidth + x) * 4;
                imageData.data[index] = cd.F[1] * cd.F[0] * GUI.red;
                imageData.data[index+1] = cd.F[0] * cd.F[0] * GUI.green;
                imageData.data[index+2] = cd.F[1] * cd.F[0] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }

// Example 2. -> Cell Distance Difference Modified

    function cellDistanceDiffMod() {
        at[2] += freq;
        t += freq;
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(y * canvasWidth + x) * 4;
                imageData.data[index] = cd.F[1] * cd.F[0] * GUI.red;
                imageData.data[index+1] = cd.F[0] * cd.F[0] + cd.F[1] * GUI.green;
                imageData.data[index+2] = cd.F[0] * cd.F[1] + cd.F[1] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }

//Example 3. -> First order distance

    function firstOrderDistance() {
        at[2] += freq;
        t += freq;
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(y * canvasWidth + x) * 4;
                imageData.data[index] = cd.F[0] * GUI.red;
                imageData.data[index+1] = cd.F[0] * GUI.green;
                imageData.data[index+2] = cd.F[0] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }


//Example 4. -> Second order distance

    function secondOrderDistance() {
        at[2] += freq;
        t += freq;
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(y * canvasWidth + x) * 4;
                imageData.data[index] = cd.F[1] * GUI.red;
                imageData.data[index+1] = cd.F[1] * GUI.green;
                imageData.data[index+2] = cd.F[1] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }


//Example 5. -> Noise noise combination

    function noiseNoise() {
        at[2] += freq;
        t += freq;
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                at[0] = 0.04 * cd.F[0] * (y + 10);
                at[1] = 0.04 * cd.F[0] * (x + 100);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(y * canvasWidth + x) * 4;
                imageData.data[index]   = (cd.F[1] + cd.F[0]) * GUI.red;
                imageData.data[index+1] = (cd.F[1] + cd.F[0]) * GUI.green;
                imageData.data[index+2] = cd.F[0] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }

    function draw() {
        var pix, piy;

        at[2] += freq;
        //t += freq[2];
        for (y = 0; y < canvasHeight; y ++) {
            at[0] = GUI.cellDimension * (y + t);
            for (x = 0; x < canvasWidth; x ++) {
                at[1] = GUI.cellDimension * (x + t);

                cd.at = at;
                cn.noise(cd);

                var index = ~~(((y) * canvasWidth + (x))) * 4;
                imageData.data[index] = cd.F[1] * cd.F[0] * GUI.red;
                imageData.data[index+1] = cd.F[0] * cd.F[0] * GUI.green;
                imageData.data[index+2] = cd.F[1] * cd.F[0] * GUI.blue;
                imageData.data[index+3] = 255;
            }
        }

        ctx.putImageData(imageData, 0, 0);
    }
}).call(this);

//importScripts('CellNoise.js' , 'CellDataStruct.js');

var x, y, t = 0,
    freq = freq || [0.8, 0.8, 0.1],
    at   = at || [0, 0, 0];
var cn = cn ? cn : new CellNoise();
var cd = cd ? cd : new CellDataStruct(2, at);
var withOutWorker = false;

function renderScene(method, img, width, height) {
    this.method = method;
    switch (method) {
        case 'cellDistanceDiff' :
            cellDistanceDiff(img, width, height);
          //  self.postMessage({ 'image' : img, 'method' : method });
            break;
        case 'firstOrderDistance' :
            firstOrderDistance(img, width, height);
            self.postMessage({ 'image' : img, 'method' : method });
            break;
        case 'secondOrderDistance' :
            secondOrderDistance(img, width, height);
         //   self.postMessage({ 'image' : img, 'method' : method });
            break;
        case 'fractalNoise' :
            noiseNoise(img, width, height);
        //    self.postMessage({ 'image' : img, 'method' : method });
            break;
        default :
            draw(img, width, height);
         //   self.postMessage({ 'image' : img, 'method' : method });
    }
}

self.onmessage = function(event) {
    if (event.data.message === 'render' && event.data.method === this.method) {
        renderScene(event.data.method, event.data.image,
            event.data.image.width, event.data.image.height);
    }

    if (withOutWorker) self.close();
}

/*
 * Different implementation methods provides different outputs.
 * Playing with values gives completely different shapes and dimensions.
 */

// Example 1. -> Cell Distance Difference

function cellDistanceDiff(img, w, h) {
    at[2] += freq;
    t += freq;
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(y * w + x) * 4;
            img.data[index] = cd.F[1] * cd.F[0] * GUI.red;
            img.data[index+1] = cd.F[0] * cd.F[0] * GUI.green;
            img.data[index+2] = cd.F[1] * cd.F[0] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}

// Example 2. -> Cell Distance Difference Modified

function cellDistanceDiffMod(img, w, h) {
    at[2] += freq;
    t += freq;
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(y * w + x) * 4;
            img.data[index] = cd.F[1] * cd.F[0] * GUI.red;
            img.data[index+1] = cd.F[0] * cd.F[0] + cd.F[1] * GUI.green;
            img.data[index+2] = cd.F[0] * cd.F[1] + cd.F[1] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}

//Example 3. -> First order distance

function firstOrderDistance(img, w, h) {
    at[2] += freq;
    t += freq;
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(y * w + x) * 4;
            img.data[index] = cd.F[0] * GUI.red;
            img.data[index+1] = cd.F[0] * GUI.green;
            img.data[index+2] = cd.F[0] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}


//Example 4. -> Second order distance

function secondOrderDistance(img, w, h) {
    at[2] += freq;
    t += freq;
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(y * w + x) * 4;
            img.data[index] = cd.F[1] * GUI.red;
            img.data[index+1] = cd.F[1] * GUI.green;
            img.data[index+2] = cd.F[1] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}


//Example 5. -> Noise noise combination

function noiseNoise(img, w, h) {
    at[2] += freq;
    t += freq;
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            at[0] = 0.04 * cd.F[0] * (y + 10);
            at[1] = 0.04 * cd.F[0] * (x + 100);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(y * w + x) * 4;
            img.data[index]   = (cd.F[1] + cd.F[0]) * GUI.red;
            img.data[index+1] = (cd.F[1] + cd.F[0]) * GUI.green;
            img.data[index+2] = cd.F[0] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}

function draw(img, w, h) {
    var pix, piy;

    at[2] += freq;
    //t += freq[2];
    for (y = 0; y < h; y ++) {
        at[0] = GUI.cellDimension * (y + t);
        for (x = 0; x < w; x ++) {
            at[1] = GUI.cellDimension * (x + t);

            cd.at = at;
            cn.noise(cd);

            var index = ~~(((y) * w + (x))) * 4;
            img.data[index] = cd.F[1] * cd.F[0] * GUI.red;
            img.data[index+1] = cd.F[0] * cd.F[0] * GUI.green;
            img.data[index+2] = cd.F[1] * cd.F[0] * GUI.blue;
            img.data[index+3] = 255;
        }
    }

    ctx.putImageData(img, 0, 0);
}

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

var keyPressed = false;

var ctx, canvas,
    canvasWidth, canvasHeight,
    imageData, gui, controller, random = Math.random,
    reachRedMax = false, reachRedMin = false,
    reachGreenMax = false, reachGreenMin = false,
    reachBlueMax = false, reachBlueMin = false,
    increaseRed = true, increaseGreen = true, increaseBlue = true;

var GUI =  new function() {
    this.renderMethod = 1;
    this.renderFunction = 'cellDistanceDiffMod';
    this.title = 'Worley Noise';
    this.cellDimension = 0.14;
    this.red = 120;
    this.green = 150;
    this.blue = 150;
    this.colorize = false;    

    this.reset = function() {
        this.renderMethod = 1;
        this.renderFunction = 'cellDistanceDiffMod';
        this.title = 'Worley Noise';
        this.cellDimension = 0.14;
        this.red = 120;
        this.green = 150;
        this.blue = 150;
    }
};

function createUI() {
    gui = new dat.GUI({autoPlace:false, width: 270, align: "left"});
    gui.domElement.style.position = 'relative';
    gui.domElement.style.top = '40px';
    gui.domElement.style.left = '50px';
    document.body.appendChild(gui.domElement);

    //gui.remember(GUI);
    //gui.add(GUI, 'title').name('Title');
    gui.add(GUI, 'renderMethod').options({
        'Euclidean': 1,
        'Cityblock': 2,
        'Manhattan': 3,
        'Quadratic': 4}).name('Render Method');
    gui.add(GUI, 'renderFunction').options( ['cellDistanceDiffMod', 'cellDistanceDiff','firstOrderDistance', 'secondOrderDistance', 'noiseNoise']).name('Render Function');
    gui.add(GUI, 'cellDimension').min(0.05).max(0.18).step(0.01).name('Cell Dimension');
    gui.add(GUI, 'red').min(20).max(255).step(1).name('Red value').listen().onChange(disableAutoColor);
    gui.add(GUI, 'green').min(20).max(255).step(1).name('Green value').listen().onChange(disableAutoColor);
    gui.add(GUI, 'blue').min(20).max(255).step(1).name('Blue value').listen().onChange(disableAutoColor);
    // gui.add(GUI, 'withWorkers').name('With Webworkers');  // Disable Web Workers
    // gui.add(GUI, 'withOutWorkers').name('Without Webworkers');
    gui.add(GUI, 'reset').name('Reset');
    controller = gui.add(GUI, 'colorize').name('Autocolor').onFinishChange(function(e) {
        autoColorize();
    })
}

function disableAutoColor() {
    GUI.colorize = false;
    controller.setValue(false);
}

function autoColorize() {
    if (GUI.colorize == false) return;
    requestAnimationFrame(autoColorize);

    //Lame method to test each value, but some handwork do not harm :)
    if (reachRedMin && increaseRed) GUI.red++;
    else if (reachRedMax && !increaseRed) GUI.red--;
    if (!reachRedMax && increaseRed) GUI.red++;

    if (reachGreenMin && increaseGreen) GUI.green++;
    else if (reachGreenMax && !increaseGreen) GUI.green--;
    if (!reachGreenMax && increaseGreen) GUI.green++;

    if (reachBlueMin && increaseBlue) GUI.blue++;
    else if (reachBlueMax && !increaseBlue) GUI.blue--;
    if (!reachBlueMax && increaseBlue) GUI.blue++;

    if (parseInt(GUI.red, 10) == 255){
        reachRedMax = true;
        increaseRed = false;
    } else if (parseInt(GUI.red, 10) == 10) {
        reachRedMin = true;
        increaseRed = true;
    }

    if (parseInt(GUI.green, 10) == 255){
        reachGreenMax = true;
        increaseGreen = false;
    } else if (parseInt(GUI.green, 10) == 10) {
        reachGreenMin = true;
        increaseGreen = true;
    }

    if (parseInt(GUI.blue, 10) == 255){
        reachBlueMax = true;
        increaseBlue = false;
    } else if (parseInt(GUI.blue, 10) == 10) {
        reachBlueMin = true;
        increaseBlue = true;
    }
}

function init(width, height) {
    canvasWidth = (width !== undefined) ? width : 200;
    canvasHeight = (height !== undefined) ? height : 200;
    canvas = document.getElementById('canvas');
    canvas.setAttribute('width', canvasWidth);
    canvas.setAttribute('height', canvasHeight);
    ctx = canvas.getContext('2d');

    imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
}
createUI();
init(150, 90);
renderWithoutWorkers();

function render(method, canvas, iterations) {
    var context = canvas.getContext('2d');

    for(var i=0; i < iterations; i++) {
        startWorker(method, context, i);
    }
}

function startWorker(method, context, threadId) {
    var img = context.createImageData(canvasWidth, canvasHeight);
    var worker = new Worker('Worker.js');

    worker.onmessage = function(event) {
        var buffImg = context.getImageData(0, 0, canvasWidth, canvasHeight);
        var threadImg = event.data.image;
        var tf = 1.0 / threadId;
        var bf = 1.0 - tf;

        for (var i=0; i < threadImg.data.length; i++) {
            threadImg.data[i] = (threadImg.data[i] * tf) + (buffImg.data[i] * bf);
        }

        context.putImageData(threadImg, 0, 0);
        worker.postMessage({ 'message' : 'render', 'image' : img, 'threadId' : threadId, 'method' : method });
    }

    worker.onerror = function(event) {
        console.log('Worker error on', threadId);
        throw new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
    }

    worker.postMessage({ 'message' : 'render', 'image' : img, 'threadId' : threadId, 'method' : method });
    return worker;
}

function renderWithWorkers() {
    requestAnimationFrame(renderWithWorkers);
    render(GUI.renderFunction, canvas, 2);
    window.addEventListener('keypress', function(event) {
        if (event.ctrlKey && event.keyCode == 72)
            keyPressed = !keyPressed;
    }, false);

    if (keyPressed)
        stats.style.display = 'none';
}

function renderWithoutWorkers() {
    requestAnimationFrame(renderWithoutWorkers);
    noWebWorkers.render(GUI.renderFunction, GUI.renderMethod);
    window.addEventListener('keypress', function(event) {
        if (event.ctrlKey && event.keyCode == 72)
            keyPressed = !keyPressed;
    }, false);

    if (keyPressed)
        stats.style.display = 'none';
}
              
            
!
999px

Console