Давайте напишем ... MMO! Часть 20: Еще прозрачность

Опубликовано NowhereMan -

18 мая 2011

В конце последнего обновления я сказал, что собираюсь оставить прозрачность пока в покое и вернуться к ней позже. Я солгал... Я просто не мог оставить её в покое.

В последней части я подумал, что у меня есть хорошее решение для прозрачности - техника "экранной двери". Оказалось, что я внедрил ее неправильно и даже не заметил, что она не работает. Причина в том, что этот конкретный ландшафт Minecraft не делает ничего сложного. У нас всего три прозрачных блока - вода, стекло и листья. Вода в основном лежит ровно над землей и не нуждается в сортировке. Стекло в основном затуманивает другие стеклянные или непрозрачные вещи, и его не нужно сортировать. А листья появляются в пучке вокруг дерева и ошибки сортировки не очень заметны.

Когда я правильно реализовал прозрачность двери, она выглядела довольно плохо, и я понял, что она просто не достаточно хороша. Я хотел перейти к более глобальному построению мира, но вопрос все еще ворчал на меня. В конце концов, я хочу позволить пользователям создавать свои собственные блоки с собственными текстурами. Что, если я просто не смогу реализовать это из-за времени, необходимого для корректного рендеринга прозрачных данных?

Это видео - кошмар, который меня преследует. Посмотрите его в 480p, чтобы увидеть истинный ужас сглаживания!

Читатель Саймон Бакэн предложил прозрачность "Quake 2-style", где полутонирование происходит не на поверхности визуализируемого объекта, а во "view-пространстве". Это предотвращает наложение псевдонимов (в основном) и сверкание при движении. Это выглядит лучше, и я пытался сказать себе, что это достаточно хорошо. Вот видео. Если сфокусировать взгляд на шуме полутонового рисунка, то можно увидеть, что он движется вместе с экраном, а не с миром.

Сортируем реже

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

  • Распределите сортировку по нескольким кадрам. Глаз не заметит, если вещи на короткое время окажутся в неправильном порядке.
  • Сначала сортируйте близлежащие объекты, а удаленные оставляйте на потом. Ошибки на расстоянии будут не так заметны.
  • Сортируйте только тогда, когда нужно сортировать - когда глаз движется и меняет перспективу на кусочек сцены.
Рис. 1: Когда мы сортируем?

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

Если подумать, какие кубы находятся ближе всего к глазу в начальной и конечной позиции, то можно увидеть, что только при переходе глаза между двумя разными рядами кубов нам нужно отсортировать. Офф-концы - это особый случай - если глаз движется в одну сторону кубика, это не влияет на порядок сортировки. Мы делаем этот тест в x, y и z, и если ни один из них не требует повторной сортировки, мы оставляем кусок в покое.

На практике это дает несколько странный результат. При перемещении одного блока все куски к горизонту в тех же X, Y или Z, что и глаз, повторно сортируются, в то время как куски к боковым сторонам остаются неизменными. Так как ландшафт в основном горизонтальный, то при вертикальном перемещении вы получаете действительно большие размеры (целую плоскость кусков).

Я добавил код, чтобы сохранить список "сортируемых" кусочков. В процессе визуализации он тестирует каждый кусочек и добавляет его в этот список. На каждом фрейме мы сортируем некоторое количество кусочков из списка. В конце концов, это будет контролироваться некоторой оценкой того, сколько процессорного времени я могу себе позволить. Сейчас это опция "sortCount".

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

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

Видео было снято со скоростью 30 кадров в секунду с 2 отсортированными кусочками на кадр. В демо, я получаю больше похоже на 90 кадров в секунду и сортирую по 10 кусочков за раз, так что вы не можете увидеть, что происходит на самом деле. Кроме того, я даже не проверяю кусочки без прозрачных кубиков. Мне было трудно даже сказать, делает ли он сортировки (потому что так мало сортировки требуется на этом пейзаже), поэтому я добавил кучу плавающих коробок с прозрачными сторонами.

Это видео показывает конечный результат. На моих машинах, я еще не поймал его с некорректной областью. Частота смены кадров нормальная, даже на моих более медленных машинах с Linux. Попробуйте и дайте мне знать. На данный момент я удалил сводку точек на расстоянии, поэтому опции "summarDistance" и "detailDistance" не дают никакого эффекта.

Я доволен этим, так что теперь я могу вернуться к построению мира!

Построй свой собственный пейзаж

В исходном коде появился новый проект под названием BuildWorld. Это бекенд кода извлечения из Minecraft, который позволит вам создать свой собственный ландшафт. Вам понадобятся инструменты программирования, чтобы перекомпилировать код, но в остальном навыков программирования немного. В файле Source/BuildWorld/BuildWorld.cpp найдите процедуру createWorld. Вы можете написать что-нибудь простое:

  // add a terrain from noise
  for (int x = 0; x < WORLD_XSIZE; x++)
  {
    for (int z = 0; z < WORLD_ZSIZE; z++)
    {
      double value = (noise(x*DENSITY, z*DENSITY) - noiseMin)/noiseRange;
      int height = 5+(int) (MAXHEIGHT * value);
      height = max(0, min(WORLD_YSIZE-1, height));

      for (int y = 0; y < height; y++)
      {
        WORLD_CELL(x, y, z) = 1;  // stone
      }
    }
  }

Вы устанавливаете байты в большом массиве (1024 на 128 на 1024). Установите любой шаблон блоков, который вам нравится. Цифры для различных типов блоков можно найти в docs/blocks/mcblocks.xml в демонстрационной версии Crafty. Программа BuildWorld создаст этот массив и установит все видимые флаги, а затем запишет огромный каталог блоков для использования в Crafty. Если вы хотите мир поменьше, вы можете изменить его размер в файле BuildWorld.cpp. Просто убедитесь, что ваши размеры кратны 32.

Создайте каталог "newworld", в который он будет записывать чанки. Запустите его, и он создаст ландшафт, как показано на рисунке 2:

Рис. 2: Ландшафт BuildWorld по умолчанию

Отредактируйте файл options.xml в Crafty, чтобы установить "worlddir" вместо "newworld", и вы сможете отобразить свой мир.

Демо

Демо-версия 20 будет использовать те же файлы мира, что и части 19 и 15. Скачайте The Part 19 Demo World. Распакуйте ее в тот же каталог, что и демо. Каталог "world" должен быть рядом с "docs" и "options.xml". Или вы можете отредактировать атрибут "worldDir" в "options.xml", чтобы указать на него.

Для Windows, качайте The Part 20 Demo - Windows.

Для Linux, качайте The Part 20 Demo - Linux.

Исходники

Качайте The Part 20 Source, или идите на https://github.com/mgoodfel/SeaOfMemes гитхаб.