Процедурная генерация снежинок

Процедурная генерации снежинок, весьма сложная задача, у неё есть масса решений.

Не все методы дают качественный результат, в этом можно убедиться, если попробовать поискать готовые генераторы снежинок. Среди них можно встретить даже такие экзотические методы как: «Random Snowflake Generator Based on Cellular Automaton».

Для получения результата, совершенно не обязательно использовать сложные формулы, по этому поделюсь своим рецептом.

Первым делом мы создадим кусок снежинки, который будем крутить по кругу.

Подготовим основание:

  context.clearRect(0, 0, width, height);
  context.fillStyle = "#fff";

  poly(context, [0, 0, width, 0, width, height - 1]);

Сократим видимую область, чтобы снежинка имела более естественный вид:

  context.fillStyle = "#000";
  poly(context, [width, 0, width, height, width * 0.8, height]);
  poly(context, [width / 2, height / 2, width, height * random(), width, height]);

Случайным образом накидаем треугольники, они и создадут наш узор:

  var t = 10;
  while (--t >= 0) {
    poly(context,
      [
        random() * width, random() * height,
        random() * width, random() * height,
        random() * width, random() * height
      ]
    );
  }

Преобразуем белый цвет в прозрачность, а его заменим на оттенки сине-голубого:

  var imageData = context.getImageData(0, 0, w, h);
  for (var i = 0; i < w; i++) {
    for (var j = 0; j < h; j++) {
      var p = (i + j * w) * 4;
      imageData.data[p + 3] = Math.floor(imageData.data[p] * alpha);
      imageData.data[p] = Math.min(255, 170 + colorFactor);
      imageData.data[p + 1] = Math.min(255, 220 + colorFactor);
      imageData.data[p + 2] = 255;
    }
  }
  context.putImageData(imageData, 0, 0);

На самом деле, основа для снежинки уже готова, теперь осталось её вывести на экран:

  var canvas = document.createElement('canvas');
  canvas.width = width / 2;
  canvas.height = height / 4;

  var ctx = canvas.getContext("2d");

  snowFlakePart(ctx, canvas.width, canvas.height, alpha);
  var pattern = context.createPattern(canvas, "no-repeat");

  context.save();
  context.translate(docWidth / 2, docHeight / 2);
  context.fillStyle = pattern;

  for (var i = 0; i < 6; i++) {
    context.save();
    context.rotate(i * Math.PI / 3);

    poly(context, [0, 0, width, 0, width, height]);

    context.scale(1, -1);
    poly(context, [0, 0, width, 0, width, height]);
    context.restore();
  }
  context.restore();

  canvas.remove();

Вот и всё, снежинка готова.

Рабочий пример находится тут, подробные исходники можно взять из него.

Не забудьте украсить ваш сайт к Новому году!