OpenGL воксельный движок медленный - PullRequest
6 голосов
/ 30 декабря 2010

Я делаю воксельный движок на C ++ и OpenGL (как Minecraft) и не могу получить приличную частоту кадров на моих 3 ГГц с ATI X1600 ... У меня нет идей.

Когда у меня на экране около 12000 кубов, оно падает ниже 20 кадров в секунду - жалко.

Пока что у меня есть следующие оптимизации: отбраковка усеченного конуса, отбраковка задней грани (с помощью glEnable OpenGL (GL_CULL_FACE)), движок рисует только видимые грани (за исключением, конечно, выбракованных), и они в октрее. 1005 *

Я пробовал VBO, они мне не нравятся, и они не значительно увеличивают fps.

Как движок Майнкрафта может быть таким быстрым ... Я борюсь с 10000 кубами, тогда как Майнкрафт может легко рисовать намного больше при более высоких fps.

Есть идеи?

Ответы [ 5 ]

6 голосов
/ 31 декабря 2010

@ genpfault: я анализирую связь и просто генерирую грани для внешней, видимой поверхности.В VBO был один куб, который я glTranslate () d

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

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

4 голосов
/ 30 декабря 2010

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

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

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

gDEBugger - отличный инструмент, который поможет вам найти узкие места с OpenGL.

2 голосов
/ 27 апреля 2012

Я не знаю, можно ли здесь "поднять" старый вопрос, но мне пришло в голову несколько вещей:

Если ваши вокселы статичны, вы можете ускорить весь процесс рендеринга, используя октрое для отбраковки усеченного конуса и т. Д. Кроме того, вы также можете скомпилировать статическую сцену в набор потенциальной видимости в октри. Основной принцип PVS состоит в том, чтобы предварительно вычислить для каждого узла в дереве, какие другие узлы потенциально видны из него, и сохранить указатели на них в векторе. Когда дело доходит до рендеринга, сначала проверьте, в каком узле размещена камера, а затем запустите отбраковку усеченного контура для всех узлов в PVS-векторе узла (Кармак использовал нечто подобное в движках Quake, но с деревьями Binary Space Partitioning).

Если затенение ваших вокселей довольно сложное, также можно быстро выполнить только перед глубиной, не записывая в цветовой буфер, только для заполнения Глубинного буфера. После этого вы выполняете 2-й проход: отключите запись в Depthbuffer и выполняете рендеринг только в Colorbuffer при проверке Depthbuffer. Таким образом, вы избегаете дорогих шейдерных вычислений, которые впоследствии перезаписываются новым фрагментом, который ближе к зрителю (Кармак использовал это в Quake3)

Другая вещь, которая определенно ускорит вещи, - это использование Instancing. Вы сохраняете только положение каждого вокселя и, если необходимо, его масштаб и другие параметры в объекте текстурного буфера. В вершинном шейдере вы можете затем прочитать позиции вокселей, которые должны быть созданы, и создать экземпляр вокселя (то есть куб, который передается шейдеру в объекте вершинного буфера). Таким образом, вы отправляете 8 вершин + 8 нормалей (3 * sizeof (float) * 8 +3 * sizeof (float) * 8 + float для цвета / текстуры и т. Д.) Только один раз на карту в VBO, а затем только позиции экземпляров Куба (3 * sizeof (float) * количество вокселей) в TBO.

Возможно, есть возможность распараллелить вещи между GPU и CPU, объединив все 3 шага в 2 потока, в потоке CPU вы проверяете pvs octrees и обновляете TBO для создания экземпляров в следующем кадре, тем временем поток GPU делает рендеринг 2 проходов при использовании TBO для создания экземпляров, который был создан потоком ЦП на предыдущем шаге. После этого вы переключаете TBO. Если камера не сдвинулась, вам даже не нужно снова выполнять вычисления CPU.

Другим видом дерева, которое меня интересует, является так называемое k-d-дерево, которое является более общим, чем октреи.

PS: извините за мой английский, это не самый ясный ....

1 голос
/ 05 марта 2011

Существуют сторонние библиотеки, которые можно использовать для повышения эффективности рендеринга. Например, библиотека C ++ PolyVox может взять объем и сгенерировать сетку для вас эффективным способом. Он имеет встроенные методы для уменьшения количества треугольников и помогает создавать такие вещи, как окружающая окклюзия. У него хорошее сообщество, поэтому получить поддержку на форуме должно быть легко.

0 голосов
/ 30 декабря 2010

Использовали ли вы общий список отображения для всех ваших кубов?
Пропускаете ли вы вызывать код рисования кубов, которые не видны пользователю?

...