3D-рендеринг карт в играх

У меня есть несколько вопросов о картах в 3D-играх (например, World of Warcraft) и о том, как программисты их отображают:

  1. Можно ли "сгладить" края гор с помощью некоторой техники, или единственно возможным решением было бы использование большего количества вершин в карте высот?

    enter image description here

    Я ошибаюсь и считаю, что они используют какую-то технику для этого, поскольку они просто отдают достаточное количество вершин для каждой горы?

  2. Посмотрите на это изображение:

    enter image description here
    (источник: gamona.de)

    Некоторые вопросы о том, как визуализировать этот вид сцены:

    1. Как мне сказали, в играх с открытым миром, таких как WoW, для рендеринга рельефа используются карты высот, откуда они знают, где рисовать все остальное? (деревья, дома, заборы, вода и т.д.).
    2. Как они делают подземные районы? (Там огромный замок внутри горы)
    3. Обратите внимание, что каждый выступ использует около 2 текстур для отображения (снег и камень). Каким может быть алгоритм, который они используют, чтобы знать, когда отбирать каждую текстуру? Это не похоже, что это зависит от нормалей. (Я не думаю, что они даже генерируют нормали для своей местности.)
    4. Также не похоже, что они используют скайбокс для горизонта. Какая техника это может быть?
    5. Не могли бы вы назвать другие интересные приемы, которые вы заметили, чтобы я мог их изучить?

В настоящее время я изучаю OpenGL, но я тоже пометил DirectX, поскольку эти вопросы не относятся к API.

Ответ 1

Трудно сказать с вашей карты высоты (в первую очередь потому, что у вас нет никакого освещения на ней), но я бы сказал, что в ваших примерах они используют карты высоты основания с высоким разрешением, чем вы.

Теперь, в отличие от некоторых других плакатов, маловероятно, что пейзаж моделируется в пакете 3D-моделирования. Также маловероятно, что они используют B-сплайны для рендеринга ландшафта.

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

Действительно хорошая методика для рендеринга VAST с очень подробной геометрией ландшафта геометрия клипов. Это довольно сложно. Еще одна схема, которую я использовал в прошлом, - Geo-Mipmapping. Это очень просто и очень быстро. Он также дает отличные результаты, если вы применяете трилинейные методы фильтрации к вашим гео-мипмарам. Также довольно тривиально писать асинхронный кусочный загрузчик для такого ландшафта, чтобы обеспечить хорошую производительность потоковой передачи огромных ландшафтов.

В любом случае я отвечу на ваши другие вопросы.

Удачи!

Ответ 2

В дополнение к ответу Тайлера Дерденса я хочу затронуть несколько ваших пунктов.

  • Скорее всего, они разработали собственный редактор, который они экспортируют и передают в свой рендерер. Таким образом, разработчики могут вставлять и размещать дерево в точке, а затем рендереру известно, чтобы рисовать древовидную модель в этот момент. Или они делают что-то вроде этого: http://mollyrocket.com/casey/stream_0017.html, в котором они "заполняют" пустую область вещами, например травой (как показано в этом примере), деревья и т.д.

  • Точно так же они отображают внешние области: p

  • Мог бы добиться этого эффекта с помощью ссылки dari, отправленной как ответ на ваш пост, или наложить некоторую текстуру из карты высот, как вы упомянули.

  • Я не уверен в Skybox.

  • Взгляните на некоторые из уже опубликованных ссылок, вы наверняка потратили бы немало времени на исследования:)

Ответ 3

Я выяснил, что самый простой способ сгладить рельеф - после преобразования в поплавки, применяя фильтр convolution, чтобы вершины. Это технология обработки изображений, но хорошо работает с данными из 8-битных карт высот.

Здесь источник С++, который я использовал несколько лет назад.

void CGround::CHeightmap::_SmoothTerrain(int passes)
{
   float* NewHeightData;

   while (passes--)
   {
       // Note: m_Size.X and m_Size.Y should be equal and power-of-two values 
       NewHeightData = new float[m_Size.X * m_Size.Y];

       for (int x = 0; x < m_Size.X; x++)
       {
          for (int y = 0; y < m_Size.Y; y++)
          {
              int adjacentSections = 0;
              float sectionsTotal = 0.0f;

              if ((x - 1) > 0) // Check to left
              {
                 sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y];
                 adjacentSections++;

                 if ((y - 1) > 0) // Check up and to the left
                 {
                    sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y - 1];
                    adjacentSections++;
                 }

                 if ((y + 1) < m_Size.Y) // Check down and to the left
                 {
                    sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y + 1];
                    adjacentSections++;
                 }
              }

              if ((x + 1) < m_Size.X) // Check to right
              {
                 sectionsTotal += m_Heights[(x + 1)*m_Size.Y + y];
                 adjacentSections++;

                 if ((y - 1) > 0) // Check up and to the right
                 {
                     sectionsTotal += m_Heights[(x + 1) * m_Size.Y + y - 1];
                     adjacentSections++;
                 }

                 if ((y + 1) < m_Size.Y) // Check down and to the right
                 {
                     sectionsTotal += m_Heights[(x + 1)*m_Size.Y + y + 1];
                     adjacentSections++;
                 }
              }

              if ((y - 1) > 0) // Check above
              {
                 sectionsTotal += m_Heights[x*m_Size.Y + y - 1];
                 adjacentSections++;
              }

              if ((y + 1) < m_Size.Y) // Check below
              {
                 sectionsTotal += m_Heights[x*m_Size.Y + y + 1];
                 adjacentSections++;
              }

              NewHeightData[x*m_Size.Y + y] = (m_Heights[x*m_Size.Y + y] + (sectionsTotal / adjacentSections)) * 0.5f;
           }
       }
       delete m_Heights;
       m_Heights = NewHeightData;
   }
}

Увеличьте значение passes, чтобы получить больше сглаживания.

Чтобы ответить на ваш вопрос 1) - отдельно. Они имеют список объектов и просто помещают их поверх карты высот.

2) - по-другому. Подземелья обычно представляют собой обычные сетки.

3) вы можете использовать нормальную, высоту, дополнительные данные текстуры, интерпретированные по-разному, или любую комбинацию выше

Ответ 4

Моделисты Blizzard используют Autodesk 3ds max для создания моделей. Если вы изучите возможности и технологии этого пакета, вы увидите, как они достигают своих эффектов. Обратите внимание, что в ландшафтных моделях используются неравномерные b-сплайны (NURB), которые придают им округлый вид.