Эффективный метод рендеринга массивной местности в XNA


10

Я создаю игру XNA, которая требует огромного пространства для игроков. В настоящее время я использую тестовую карту высот 4096x4096 и сохраняется как 4-битный BMP.

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

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

С учетом сказанного я натолкнулся на ряд решений, все из которых я перечислил ниже:

  • Рендеринг основан на текущем местоположении пользователя - в основном рисование квадрата вокруг пользователя независимо от его ориентации в мире. Это не совсем то, что я хотел, потому что вы по-прежнему отображаете пространство, которое пользователь не видит.
  • Рендеринг основан на ориентации и положении пользователя - я нашел формулу для получения треугольника, который должен иметь то, какие пиксели карты высот должны быть отрисованы, но это оказалось очень трудным.
  • Разделение ландшафта на несколько фрагментов и рендеринг, какие из них ближе всего к пользователю - Все еще не очень эффективно, поскольку вы по-прежнему визуализируете фрагменты, которые люди не увидят. И это трудоемко, потому что тогда мне нужно разбить карту высот на несколько частей, и масштабируемость становится большой проблемой.

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

Поэтому, в основном, я прошу простой, прямой способ рендеринга огромных ландшафтов в XNA с максимальной эффективностью.

Я довольно новичок в разработке игр в целом, но я готов исследовать, если это кажется многообещающим.

Обновление 1: после исследования метода геоклипмаппинга я начал кодировать его. Я сделал всю математику, и игра запускается. Тем не менее, это крайне неэффективно - что, вероятно, плохое кодирование с моей стороны. Он работает на 2FPS и использует все ядро ​​моего процессора. Я собираюсь попробовать и улучшить код, но я думаю, что мне понадобится дополнительная помощь, поэтому вот Pastebin кода для класса Terrain Manager. Я опубликую результаты с большим количеством результатов позже, если когда-нибудь получу более эффективный.


1
Интересно, что техника, о которой вы говорите, похожа на ту, которую ID Software использует в своей новой игре Rage. Они используют «мегатекстуру», а затем передают ее части, необходимые для графического процессора. Он рассказал об этом, но вот статья в Википедии, она может быть вдохновляющей: en.wikipedia.org/wiki/MegaTexture

Ответы:


5

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

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

Более продвинутые рендеры рельефа местности используют алгоритм для настройки не только видимой геометрии, но и деталей этой геометрии. Geomipmapping (и его относительное geoclipmapping) относительно популярны в настоящее время для этого, но не являются тривиальной вещью для реализации.

редактировать: вот достойное описание как геоклипмаппинга, так и отбраковки усеченного конуса.

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


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

3

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

Вот примерный план одного подхода, который должен хорошо работать:

Вы должны разделить свою местность на (довольно большие) куски, загружая эти куски в фиксированные вершинные буферы (битовая глубина вашей карты высот не имеет значения!). Эти вершинные буферы просто будут храниться в памяти GPU, ожидая, чтобы их визуализировали. Вам придется поэкспериментировать с подходящим размером чанка, но 128x128 - это, пожалуй, хорошее место для начала.

Для ландшафта размером 4096x4096 вы немного выходите за пределы того, что я бы сразу комфортно загружал в GPU - это, вероятно, несколько сотен МБ данных вершин (хотя вы можете уменьшить их до ~ 64 МБ, если вы умная). Поэтому вам, возможно, придется загружать и выгружать буферы вершин из графического процессора в фоновом режиме.

(Если вы реализуете фоновую загрузку блоков, это должно быть чрезвычайно масштабируемым!)

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

Вы почти никогда не должны делать выборку для каждого треугольника на процессоре!

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

Для получения дополнительной информации о производительности посмотрите этот ответ на сайте Game Dev.


0

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


Есть встроенные решения, но проблема, с которой я столкнулся, заключалась в том, что я пытался отрисовать один большой примитив, который превысил ограничение на полигоны для примитивов. Поэтому он не будет рисовать, просто выбросить исключение.
sammarks
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.