Рисуем ландшафт для карты

Ландшафт шаг за шагом.

Автор: Серба Андрей

Этот туториал охватывает азы техники создания ландшафтов. Я рассмотрю карту высот, простейший алгоритм визуализации, раскраску (текстурирование) ландшафта, а так же оптимизацию на уровне OpenGL. Что касается примеров, я считаю, что если размер примера (не считая инициализации OpenGL и т.п.) больше 8-10 Кб то это что угодно, но только не пример. Поэтому я старался следовать этому принципу.

Представление ландшафта, карта высот.

Для представления ландшафта мы будем использовать карту высот.

Карта высот — это двумерный массив значений высот ландшафта, взятых с определенным интервалом. Т.е. мы каждому дискретному значению Х и Y в горизонтальной плоскости сопоставляем высоту.


массив


Графическое представление массива

Создать карту высот можно с помощью графического редактора (прекрасно подойдет Photoshop) или с помощью программ специально для этого предназначенных, например TerraGen. Для создания карты высот в Photoshop’е необходимо выполнить фильтр Clouds, а затем несколько раз фильтр Different clouds. И сохранить полученную картинку как Grayscale файл в формате RAW (в принципе можно использовать другой формат, но об этом поговорим позже). Размер карты может быть произвольный, но удобней использовать квадратную, с размером стороны кратным числу степени двойки: 128х128, 256х256 и т.д.

Будем считать, что на представленных примерах светлые области представляют собой возвышения, соответственно темные — низменность.

Photoshop
TerraGen

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

В примере ландшафт реализован в виде класса Terrain. Приведенный ниже кусочек кода — часть функции Terrain::RenderLandscape() демонстрирует простейшую реализацию процедуры рисования.


Пример (40 кБ)

Раскраска (текстурирование) ландшафта.

Я расскажу о двух способах закраски ландшафта (и во втором случае текстурирования). Это очень краткое объяснение, не затрагивающее множество аспектов, таких как мультитекстурирование, блендинг нескольких текстур, и т.п. Обо всем этом я напишу отдельную статью.

Способ первый — интерполяция цветов.

Первый способ раскраски ландшафта состоит в использовании интерполяции цветов. Что такое интерполяция цветов, наверное, знает каждый, но если кто-то не знает, краткий пример. Например, если, рисуя треугольник, каждой вершине задать разный цвет, получим картину изображенную ниже. При этом OpenGL сам выполнит интерполяцию, от нас только требуется включить интерполяцию, что делается просто:

ниже приведен код демонстрирующий рисование треугольника с интерполяцией цветов:

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

Грубо говоря, любая RGB картинка сохраненная, как Raw-файл, может быть использована в качестве карты цветов. Важно заметить, что ширина и высота этих файлов должны быть равными размеру карты высот!

Как известно в RGB режиме одна точка изображения описывается тремя байтами — значение Red, Green, Blue компоненты цвета. Таким же образом точки картинки хранятся и в Raw-файле.

Хранить карту цветов (как и карту высот) мы будем в массиве, только в карте высот одному элементу массива соответствует одно значение высоты, а в карте цветов три значения — интенсивность красной, зеленой и синей составляющей цвета. Поэтому введем следующую структуру, которая и будет элементом массива цветов:

При этом процедура рисования (я убрал рисование «проволочной» модели) претерпела минимальные изменения:

Способ второй — текстурирование.

Суть второго способа состоит в наложении на ландшафт текстуры. Для этого нам понадобится текстура, точно такая же как файл для карты цветов, только сохранить его надо как TGA файл (понятно, что выбор формата — это дело вкуса, но в приведенных мною примерах используются TGA-файлы). Я предполагаю что вы знакомы с текстурирование, и не буду описывать процесс загрузки и создания текстуры в OpenGL.

Размер текстуры, может и не соответствовать размеру карты высот. Например для карты высот 128×128 может быть выбрана текстура размером 64×64 или 512×512 точек. В последнем случае качество буде лучше. На практике достаточно выбрать размер текстуры равный размеру карты высот.

Суть метода состоит в текстурирование одной текстурой всех треугольников нашего ландшафта, рассчитывая каждому треугольнику соответствующие координаты текстуры.

Итак, прежде чем приступить к текстурированию мы должны определит шаг изменения координат текстуры. Необходимо вычислить значение 1.0/MapSize (MapSize — размер карты высот). И тогда умножая координаты x и y треугольника на этот шаг, мы получим координаты текстуры соответствующие этому треугольнику. Ниже приведен рисунок иллюстрирующий текстурирование, и пример процедуры рисования.

Читайте также:  Варианты клумбы с лилейниками

Если вы хотите, чтобы текстура не «растягивалась» на весь ландшафт, а соответствовала определенной его части, необходимо при вычислении шага, вместо 1 подставить нужное вам число, и текстура повториться заданное количество раз.

Шаг изменения координат текстуры объявлен как константа в Terrain.H.

const GLfloat TextureBit = 1.0f/(float)MapSize;
а измененная процедура рисования выглядит следующим образом:

Следует сказать пару слов о фильтрации текстуры. В приведенном примере используется линейная фильтрация, что намой взгляд, является оптимальным вариантом. Фильтрация ближайший сосед (GL_NEAREST) существенно ухудшает качество, в то время как мипмаппинг практически его не улучшает. Использование мипмаппинга будет иметь смысл, если размер текстуры превышает размер ландшафта хотя бы в два раза, или если текстура повторяется.

Оптимизация на уровне OpenGL.

Сразу необходимо заметить, что только оптимизация на уровне OpenGL не может решить проблему производительности в целом. Безусловно, прирост производительности будет но не всегда достаточный. OpenGL оптимизацию необходимо использовать вместе с оптимальным алгоритмом отображения ландшафта. Хотя, если размер карты не превышает 128×128, можно обойтись оптимизацией только на уровне OpenGL.

Первое, что можно сделать на уровне OpenGL, это уменьшить число вершин предаваемых на конвейеру текстурирования, для этого необходимо заменить рисование с использованием GL_TRIANGLE_STRIP на эквивалентный GL_TRIANGLE_FAN, как показано на рисунке:

GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN

Правда в примере, я использовал GL_TRINGLE_STRIP

Второе, использовать для отображения функцию glDrawElements. Это функция позволяет рендерить множество примитивов вызовом одной функции, тем самым уменьшая число вызовов OpenGL функций. Для того, что бы выполнить рисование с помощью функции glDrawElements необходимо выполнит три шага:

1. Активировать массивы с данными, в нашем случае массив вершин и координат текстур (аналогично можно поступить с цветами, нормалями и некоторыми другими атрибутами). Для этого необходимо воспользоваться функцией void glEnableClientState(GLenum Array), где в качестве параметра указать GL_VERTEX_ARRAY, а затем GL_TEXTURE_COORD_ARRAY.

2. Задать параметры данных и массивы для их хранения. Для задания массива и типа вершин служит функция

void glVertexPointer( GLint Size, GLenum Type, GLsizei Stride, void *Ptr )
которая определяет способ хранения и координаты вершин. При этом Size определяет число координат вершины (может быть равен 2, 3, 4), Type определяет тип данных (может быть равен GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE). Иногда удобно хранить в одном массиве другие атрибуты вершины, и тогда параметр Stride задает смещение от координат одной вершины до координат следующей. Если Stride равен нулю, это значит, что координаты расположены последовательно. В параметре Ptr указывается адрес, где находятся данные.

Аналогично можно определить массив координат текстуры, используя команду

void glTexCoordPointer(GLint Size, GLenum Type, GLsizei Stride);

3. Заполнить массивы данными и выполнить отрисовку. Как уже было сказано, рисование выполняется с помощью функции

Источник статьи: http://www.gamedev.ru/articles/?id=30015

Карта с нуля. Учимся ее делать

Замутить свою карту хотел бы чуть ли не каждый, кто хоть как-то задумывался о моддинге Hearts of Iron. Правда, этот энтузиазм быстро сгорает при встрече с реальностью.

Создание новой карты — труд, требующий базовых знаний работы с графическими редакторами (Photoshop, GIMP, PaintNet и т. п.) и понимания аспектов моддинга. Неопытный малец, скорее всего, погрязнет в этом болоте и бросит это дело… Этот урок — попытка расширить порог вхождения.

К чему нужно быть готовым?

1. Вероятность создать полноценную функционирующую карту без вылетов за один день КРАЙНЕ МАЛА.

2. Вылеты при разработке новой карты — НОРМА.

3. 2000+ ошибок в логе — НОРМА.

4. Часть ошибок взаимосвязаны, исправление одной может привлечь к появлению других. Править пока не исчезнут ПОЛНОСТЬЮ.

5. Придется пользоваться Nudge.

6. Чистить КЭШ игры (кнопка внизу лаунчера) при работе с картой ОБЯЗАТЕЛЬНО. Особенно, если Вы переходите на разные моды или ванильную игру.

7. Мелкая ошибка может привести к КОЛОССАЛЬНОМУ НРАВСТВЕННОМУ СТРАДАНИЮ.

8. Вероятность, что Вам захотят помочь или сделать карту за Вас, близится К НУЛЮ.

Тем не менее, эти рубежи не пугают истинных бойцов, настоящих спартанцев от мира моддинга. И, однажды, благодаря упорству, они всё-таки способны создать ту самую НОВУЮ КАРТУ.

Какими навыками нужно владеть?

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

  1. Хотя бы уметь включить Photoshop, GIMP, PaintNet и т. п., выбирать цвет по коду, рисовать по пикселям без сглаживания и уметь экспортировать файлы в dds, bmp форматах.
  2. Хотя бы приземленно понимать, чем Вы занимаетесь. Рекомендуем ознакомиться с файлами раздела map.
Читайте также:  Технологии теплицы для выращивания цветов

3. Не умеешь включить режим -debugне лезь туда, она тебя сожрет.

4. Желателен опыт работы с ванильной картой игры. Если успешно добавляли новые острова, меняли провинции, регионы, создавали новые — БУДЕТ ПРОЩЕ.

Способы создания

Имеется два способа создания карты с нуля:

  1. Полностью ручным способом. Метод последовательный, но муторный, требует хороших навыков работы с Photoshop, GIMP, PaintNet и т. п. (и быть садомазохистом). Это значит, что все карты (карты рек, ландшафта, морей, провинций, нормалей, высот и др.) нужно рисовать самому. Ветераны моддинга начинали с этого.
  2. Часть карт можно сгенерировать с программой Mapgen 2.2, написанной Джеймсом Роджерсом. Софтина, моё почтение, но не является волшебной палочкой для решения всех проблем. Скачать без СМС регистрации — ЗДЕСЬ.

Радость и беда Mapgen

Более функционального софта, чем Mapgen 2.2, еще никто не создал, или мы о другом попросту не знаем. Совершенной программы по карте нет, наверно, и не будет никогда, но стремиться к этому стоит.

  1. Mapgen 2.2 облегчает первый этап разработки карты, задает тон происходящему и позволяет относительно быстро решить некоторые проблемы с картой.
  2. Программой можно сгенерировать все необходимые карты. Правда, это не гарантирует того, что она это сделает с первого раза.
  3. Разработчик проги забил на своё творение, не оставил ее исходного кода, поэтому она успешно создает карту только на версию игры 1.5.4. Всё остальное нужно править и переделывать РУЧНЫМ СПОСОБОМ.

Вообще, создавать новую карту с Mapgen 2.2 — решение разумное. Стоит понимать, что она не создаст вам рабочую версию карты, но позвоночник файлов выдаст, что уже очень много.

Начало

Для начала нам нужен графический редактор. Я использую БЕСПЛАТНЫЙ вариант — GIMP. Легко устанавливается, не требует танцев с бубном и борьбы с совестью. Содержит базовый инструментарий Photoshop, чего вполне достаточно для работы.

Следовательно, нужна идея: какую карту готовитесь рисовать? Придумали, молодцы.

Для примера я взял эту карту. Кто узнал, тот молодец.

2. СКАЧАТЬ Mapgen: ЗДЕСЬ. Открываем сие творение.

3. Открываем GIMP:

Первые шаги

  1. Начинаем мы с общей формы карты — Land Input. Открываем в GIMP файл LandMap из \MapGen v2.2\Examples:

Что нужно знать про Land Input?

Эта карта из трех цветов указывает Мапгену, где море, озеро и земля. Размер этого изображения также определяет размер вашей карты, но не надейтесь, что Вы сможете создать карту любого размера, игра ограничена в этом вопросе (стандартный размер 5632 x 2048), поэтому используйте LandMap из \MapGen v2.2\Examples в качестве шаблона.

Вы можете нарисовать ее вручную, что мы и будем делать, и перетащить в программу или сгенерировать из карты высот (height map). В любом случае, придется создавать карту.

Нам нужны три цвета. Ниже указаны их коды.

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

Рисуете карандашом без сглаживания, пиксели при приближении должны выглядеть подобным образом:

Обязательно используйте подобные параметры! Если Force и Hardness будут не 100%, то цвет не будет соответствовать коду.

Правда, если вы слегка изменили цвет, программа может исправить это, но не злоупотребляйте этим. Однако, важно сохранить изображение в виде 24-битного растрового изображения (24-bit bitmap), прежде чем загружать его в пажилую Мапгену.

Потом рисуем, что хотим, соблюдая параметры карандаша:

Закидываете файл в Мапгену в разделе Land Input.

У HOI4 минимальный размер провинции 8 пикселей. Прога превращает все маленькие острова в провинцию, что может стать проблемой, если остров меньше 8 пикселей. Включение «check for small islands» будет проверять наличие этих островков. Если они найдены, карта будет отображаться с указанными островками, обведенными красным, чтобы вы могли ее исправить.

Ну вот, одна карта уже готова!

2. Создаем карту ландшафта — terrain input.

Карта местности указывает, где находятся различные зоны ландшафта на вашей карте (НЕ ПУТАТЬ с картой местности terrain map, которая определяет текстуры карты).

Генератор может автоматически создать такую карту, щелкнув «generate plains world». Вы можете нарисовать свою карту:

Читайте также:  Маленькая лужайка с клумбами

-Городская местность: #9B00FF

Файл создается по аналогичному принципу, как и Land Input, а также должен быть с 24-битным растровым изображением того же размера, что и прошлая карта.

Опыт показывает, что во избежании квадратных артефактов на прибрежных зонах, делаем их равнинами (это повлияет на генерацию карты высот).

Закидываем в Мапгену!

3. Следующий этап проще. Прога сама сгенерирует Province Size Input:

Карта Province Size Input определяет размер провинций суши (внезапно). Указывая цвет провинций от белого до черного цвета. Оттенки серого варьируется. Для провинций, сгенерированных на белых областях, будет задан максимальный размер, для областей на черных областях будет установлен минимальный размер, а между провинциями будет масштабироваться в зависимости от значения оттенков серого.

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

Настройки размера провинций — это искусство. Правильный их выбор решает много. В будущем Вы столкнетесь с такими ошибками:

  • Слишком большие провинции вызовут ошибку — Province X has TOO LARGE BOX. Соотношение ширина/высота провинции составляет более 1/8 от общей ширины/высоты карты. Также это может быть признаком того, что две провинции имеют общий цвет.
  • Слишком маленькие провинции — Province X has only N pixels. Минимальный размер провинции — 8 пикселей.
  • Иногда общий угол провинций может вызвать ошибку — Map invalid X crossing. Please fix pixels at coords. Иногда игра может соединить нижнюю левую и верхнюю правую провинции, что вызывает подобные ошибки. Их появление неизбежно и правится ручным способом или генерируя другую карту провинций, о которой мы поговорим далее.

Оптимальная настройка интуитивна, и подбирается в зависимости от формы карты. Главное — не переборщить:

Имеется два способа сгенерировать Province Size Input.

Mercator Distribution: имитирует форму глобуса, так что экваториальные провинции меньше, чем полярные. Отлично подходит по дефолту.

Uniform Distribution: провинции однородного размеры, подходящие для модов с маленькими картами (редкость). Малую карту технически сложно реализовать, не сломав саму игру.

Мы жмем Mercator Distribution.

4. Дальше определяем примерные регионы суши в

Границы указывают как провинциям и стейтам выровняться относительно этих границ.

Границы должны быть толщиной в один пиксель, непрерывными.

Эта карта не является обязательной (можете вообще пропустить этот момент, если Вам не нужны какие-то строгие границы), но если вы хотите добавить ее, убедитесь, что это 24-битное изображение и того же размера как и остальные карты.

5. Логично было перейти к ближней вкладке province map, но опыт показывает, что лучше сначала замутить карту рек.

Делаем карту рек — river map. Можно рисовать самому или автоматически сгенерировать.

Правда, очень важно соблюдать цвета рек. Реки всегда должны быть толщиной в 1 пиксель.

Палитра цветов:

Зеленый пиксель — начало реки, красный — объединяет реки в одну, желтый — разделяет на две, голубые пиксели — определяют толщину реки на карте (но на этой карте все толщиной в пиксель).

Если вы сделали карту вручную, сначала загрузите ее в Мапген, а затем сохраните ее в проге. Это гарантирует, что ваше изображение будет в нужном формате для игры.

Случайные изгибы рек «River Random Wander». Если «Add to Existing Rivers» включено, предыдущая карта рек не будет перезаписана, и дополнительные реки будут добавлены к существующим.

6. И вот сейчас генерируем карту провинций — province map.

Карта провинции province map очень важна, она определяет все провинции в игре. Мапген также создает файл definitions.csv к этим провинциям.

В этом файле информация по:

В будущем пригодится.

К счастью, вам не нужно ее делать вручную. Нажмите «Generate» в левом нижнем углу, и карта провинции будет создана, используя ваши настройки и карты, определенные на предыдущих вкладках. Опция «Provinces Don’t Cross Rivers» станет доступной, если вы загрузите карту рек. Это заставит провинции выравниваться с реками, поэтому мы рисовали реки заранее.

Если у вас уже есть карта провинций, перетащите ее и файл definitions.csv в программу вместе. Из этих файлов будут также сгенерированы land map и terrain input map.

7. Потом генерируем «Generate» дефолтные стейты (states) для нашей карты в State Output. Не забудьте сохранить файлы стейтов, нажав на «Save» (создаете новую папку и жмете «Select» и «Yes»), это пригодится в будущем.

Источник статьи: http://vk.com/@heartsofmodding-karta-s-nulya-uchimsya-ee-delat

Оцените статью