CodePen

HTML

            
              <button id="generate">Generate new</button>
<canvas id="canvas"></canvas>
            
          
!

↑ Insert the most common viewport meta tag

CSS

            
              canvas { background-color: blue; display: block;}
            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    mcanvas = document.createElement('canvas'),
    mcontext = mcanvas.getContext('2d'),
    height = canvas.height = mcanvas.height = 480,
    width = canvas.width = mcanvas.width = 600;

function Particle(x, y, radius, color) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.canvas = document.createElement('canvas');
    this.context = this.canvas.getContext('2d');
    this.canvas.height = this.canvas.width = radius * 2;

    var grad = this.context.createRadialGradient(radius, radius, 1, radius, radius, radius);
    grad.addColorStop(0, 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',1)');
    grad.addColorStop(1, 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',0)');
    this.context.fillStyle = grad;

    this.context.beginPath();
    this.context.arc(this.radius, this.radius, this.radius, 0, Math.PI * 2, true);
    this.context.fill();
    this.context.closePath();
}
// argument hell... I know... 
function generate(color, num, size, xmin, ymin, xmax, ymax) {
    xmax = xmax || width;
    ymax = ymax || height;
    xmin = xmin || 0;
    ymin = ymin || 0;
    for (var i = 0; i < num; i++) {
        var x = Math.random() * (xmax - xmin) + xmin,
            y = Math.random() * (ymax - ymin) + ymin,
            r = Math.random() * size + (size / 2) | 0;
        var p = new Particle(x, y, r, color);
        mcontext.drawImage(p.canvas, p.x - r, p.y - r);
    }
}

function metabolize() {
    var image = mcontext.getImageData(0, 0, width, height),
        data = image.data;

    for (var i = 0, l = data.length; i < l; i += 4) {
        var left = i - 12,
            right = i + 12; // check 3 pixles to the left and right

        if (data[i + 3] < 210) { // check alpha
            if (data[i + 3] > 185) { // slight colour blend for the water edge
                data[i] = 200;
                data[i + 1] = 200;
                data[i + 2] = 255;
            }
            data[i + 3] /= 6;
            // shitty way to 'check' for a height... looks ok?	
        } else if (data[i + 3] > 250 && data[left + 3] > 250 && data[right + 3] > 250) {
            // I just darken this. 
            data[i] -= 25;
            data[i + 1] -= 25;
            data[i + 2] -= 25;
        }

    }
    context.putImageData(image, 0, 0);
}

function run() {
    mcontext.clearRect(0, 0, width, height);
  
  // arguments for the generate function are as follows: 
  // color, num, size, xmin, ymin, xmax, ymax
  
    // sand
    for (var i = 0; i < Math.random() * 4 + 1 | 0; i++) {
        generate({
            r: 237,
            g: 201,
            b: 175
        }, 25, 45, 45, 45, width - 45, height - 45);
    }

    // grass
    for (var i = 0; i < Math.random() * 4 + 1 | 0; i++) {
        generate({
            r: 0,
            g: 128,
            b: 0
        }, 45, 45, 45, 45, width - 45, height - 45);
    }

    metabolize();
}
run();
document.getElementById('generate').onclick = run;
            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................