Как получить блоки, которые видит игрок?


15

Я пишу игру для Minecraft, используя движок Ogre, и у меня проблема. Я должен оптимизировать свою игру, потому что, когда я пытаюсь нарисовать 10000 блоков, у меня есть 2 FPS ... Итак, у меня появилась идея блокировать отображение плоскости и скрывать невидимые блоки. Но у меня проблема - как узнать, какие блоки одновременно видны игроку?

И - если вам известны другие методы оптимизации для такой игры, напишите, что и как использовать в Ogre.

Ответы:


16

Что ж, в Ogre уже реализована выборка из усеченного конуса (которая в основном не рисует ничего, что не видно из камеры), но я думаю, что ваша проблема в другом.

Вы не должны отображать 10000 блоков, что обычно делается (или, по крайней мере, в немногих майнкрафтах на основе Ogre3d, таких как клоны, которых я видел (из которых я тоже делаю один), и в оригинале) - создание меша ( некоторой области NxNxN кусков), которая имеет внешние грани кубов показано. То есть, когда вы кладете 2 куба рядом друг с другом, соприкасающиеся 2 грани не видны и поэтому не нуждаются в рисовании.

Эти грани также должны быть нарисованы примерно так: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=DynamicGrowingBuffers, поскольку современные видеокарты предпочитают одну сетку из 100000 полигонов по сравнению с 1000 сетками из 100 полигонов.


10

Есть несколько аспектов этой проблемы. Во-первых, как вы рисуете свои 10000 блоков? Вы действительно рисуете их как 10000 отдельных объектов? Если это так, то это почти наверняка ваша горлышко бутылки, а не отсутствие выбраковки прикуса. Вы должны сгруппировать эти блоки в меньшее количество ячеек (возможно, несколько тысяч на ячейку), чтобы уменьшить количество вызовов отрисовки.

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

1) Блоки за пределами области видимости. Это означает блоки, которые находятся позади вас или двух сторон. Ogre уже удаляет их через отбор вида фрустума.

2) Блоки, которые находятся «под землей» или полностью окружены другими блоками, поэтому их никогда нельзя увидеть под любым углом. Вы можете определить их, посмотрев на соседние блоки. Если они все твердые, ваш блок скрыт. Графический процессор никогда не должен слышать об этих блоках - они должны быть пропущены, когда вы строите сетку, которая представляет вашу поверхность.

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

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

http://www.thermite3d.org/

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

http://www.youtube.com/watch?v=Jju6WRPEK7o


4

Вы можете использовать отбраковку задней грани для отбраковки вершин и связанных с ними пикселей, которые не обращены к игроку. Глубина буферизации должна позаботиться об остальном. 10k блоков на самом деле не много, мой 5770 может рендерить 100k верт при 1500fps. Я думаю, что ты делаешь что-то еще довольно сильно неправильно.


Я согласен. Это, вероятно, проблема с чем-либо еще.
Notabene

1

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

У Minecraft есть концепция блоков кубов, но я не могу найти ссылку на данный момент.

Вот также мои эксперименты по рисованию тонн кубиков с использованием различных техник. Не включает выпечки (пока).


0

Я создаю массив блоков, но перед созданием вершин запускаю подпрограмму UpdateBlockVisiblility.

Подпрограмма просто проверяет соседей по блоку и обновляет видимый логический блок Blocks соответственно.

#define BLOCKFACE_NORTH 0

#define BLOCKFACE_SOUTH 1 

etc etc etc

if(IsBlockAt(NorthOfBlock))
  Blocks[Whatever].facevisible[BLOCKFACE_NORTH] = false;

Тогда я создаю вершины для лица, только если оно видно! Просто :)

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