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

Создание процедурных текстур у многих вызывает странные чувства. В крупных компаниях, легче попросить дизайнера, нарисовать текстуру, чем написать генератор для её создания.

Но если вы создаете игру, процедурные стадии или модели для работы в браузере, то для вас такие текстуры являются проблемой. Основная проблема их размер, ведь сжать текстуры, которые нарисовал дизайнер, без потери качества очень сложно. Не так много форматов, которые могут похвастаться сильным сжатием, наверное единственный лидер сейчас это формат BPG от Fabrice Bellard.

Попробуем создать процедурную генерацию SciFi текстур с использованием метода «Диаграмма Вороного».

С первого взгляда, может покажется странным, как вообще можно применить данный метод для такой задачи. Но не будем спешить с выводами. Попробуем использовать модификацию названную как «Манхэттен».

В обычном виде мы использовали:

function getValue(dx,dy) {
  return sqrt(dx*dx + dy*dy);
}
«Манхэттен» будет иметь вид:

function getValue(dx,dy) {
  return abs(dx) + abs(dy);
}

Совсем простое изменение, но результат уже совершенно другой:

Это уже и будет та самая основа для нашего генератора текстур.

Конечно, глядя на картинку сразу появляется пару идей:
— разукрасить в более естественные цвета;
— придать объем;
— добавить мелких деталей;
— радоваться результату.

Но, как только мы попытаемся приступить к реализации, нас будет ждать весьма плачевный результат:

Так как формула у нас abs(dx) + abs(dy), то мы естественно и получаем эту специфичную картину.

Как же быть, спросите вы?
Всё просто, модифицируем метод для получения приемлемого результата.
Для этого нам нужно избавиться от изобилия пирамид и создать объем относительно контуров, а так же добавим осевую симметрию относительно вертикальной прямой.

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

Попробуем обычный sin(dv), так же добавим тиснение и посмотрим еще раз на результат.

Для создания эффекта тиснения у нас будет очень простой код:

for(var i = 0; i < data.length; i++) {
  if ( i % 4 === 3 ) continue;
  data[i] = 127 + 2*data[i] - data[i + 4] - data[i + w*4];
}

Наш результат:

А теперь посмотрим на них уже на 3D объекте, чтобы оценить полученный результат:

Результат получился весьма достойный, скорость генерации процедурных scifi текстур размером 512х512 не превышает 250мс. Такие текстуры уже не являются шумом и могут иметь реальное применение. Надеюсь на положительные отзывы. Если есть вопросы или предложения, буду рад на них ответить.

Посмотреть демонстрацию

2 комментария