Привет всем!
Я заметил, что на этом форуме есть сильные и опытные разработчики, хорошо знающие функционал OpenGL. Ребята, надеюсь я не слишком злоупотреблю вашим вниманием - у меня есть два вопроса, скорее теоретических, но явно в спецификациях по OpenGL я не нашел на них ответов, помогите разобраться.
Чтобы получить максимальный FPS загружаем данные VBO в память GPU - используя функции glBufferData и glBufferSubData. Все объекты грузим в один общий VBO и рисуем за один вызов glDrawElements. Все круто, FPS высокий, но вот возникла необходимость что-то нарисовать дополнительным вызовом glDrawElements.
Первый вопрос по функции glDrawElements/glDrawRangeElements - в них последний параметр это указатель на местоположение (начало блока), в котором хранятся данные/индексы. Я почему-то не нашел, как указать кусок (фрагмент) данных из памяти GPU НЕ от начала. Если индексы и данные расположены в GPU, то они обрабатываются фрагментом ВСЕГДА ТОЛЬКО ОТ НАЧАЛА области и до указанной границы. Собственно вопрос: можно ли рисовать объекты несколькими вызовами glDrawElements из одного VBO указывая разные блоки, или для каждого объекта надо либо заводить отдельный VBO, либо адресовать пользовательский массив данных в памяти приложения? Как правильно делать в таких случаях?
Второй вопрос. Из-за него, собственно, и возник первый - использование glStencilFunc для идентификации объектов:
for(int i = 0; i < obj_count; i++) {
glStencilFunc(GL_ALWAYS, i + 1, -1);
draw_object(i);
}- если рисовать типовой террайн в виде меш-сетки, то чтобы использовать glStencilFunc для адресации отдельных ячеек, надо каждую ячейку рисовать отдельным вызовом чередуя с glStencilFunc или я чего-то упустил? Ведь если каждую ячейку меша рисовать отдельным вызовом - это же какие будут "тормоза"!
bigov
> Первый вопрос
http://docs.gl/gl3/glDrawElementsBaseVertex
> если рисовать типовой террайн в виде меш-сетки, то чтобы использовать
> glStencilFunc для адресации отдельных ячеек,
тебе нужно найти треугольник в который попал курсор ? можно PrimitiveID писать в unsigned target или аналитически считать
стенсил же не резиновый :)
bigov
можно через массив индексов указывать какие вертексы обрабатывать. Их придется каждый кадр обновлять и прокачивать по шине, но это не слишком большая нагрузка.
>Ведь если каждую ячейку меша рисовать отдельным вызовом
в OpenGL3.2? Это мобильные игры/браузерные, там пара сотен(несколько тысяч максимум) полигонов на сцену максимум, нагрузка менее 5%(на все) будет даже на мобилках
про ID выше сказали, там тоже просто
g-cont
> можно через массив индексов указывать ...
Если не трудно, "набросай" пару строчек для примера. Я не понял.
innuendo
> http://docs.gl/gl3/glDrawElementsBaseVertex
мимо. Все равно выводится один объект (или непрерывная группа) от начала буфера. Нельзя вывести вторым и последующими вызовами другие объекты - не с начала буфера.
innuendo
> стенсил же не резиновый :)
В каком смысле? Он соответствует числу пикселей на экране, можно хоть всю сцену на него завязать - все равно останутся попиксельные записи только ID видимых объектов. Все остальные будут просто перезаписаны или не попадут в него (если объект за пределами видимости).
bigov
> В каком смысле?
8 битов
innuendo
я понял - это про максимальное значение ID. Да -
The buffer is per pixel, and works on integer values, usually with a depth of one byte per pixel.
bigov
> Все объекты грузим в один общий VBO и рисуем за один вызов glDrawElements. Все
> круто,
на самом деле не очень правильно всё в одном большом буфере … лучше тогда уже несколько
innuendo
Да, теперь я вижу что сложную сцену в один буфер пихать получается "геморно" - проще будет дробить на несколько. Спасибо.
bigov
> > http://docs.gl/gl3/glDrawElementsBaseVertex
>
> мимо. Все равно выводится один объект (или непрерывная группа) от начала буфера. Нельзя вывести вторым и последующими вызовами другие объекты - не с начала буфера.
Все там работает, glDrawElementsBaseVertex для этого и придумали что-бы была возможность выводить часть буфера не сначала.
Поробуй сделать квадрат и побей его на 2 треугольника. Выведи второй, указав смещение с 4 вершины, он как раз и будет не сначала буфера.
Andrey
> Все там работает...
Действительно, я неверно понял описание
glDrawElementsBaseVertex behaves identically to glDrawElements except that the ith element transferred by the corresponding draw call will be taken from element indices + basevertex of each enabled array. ...
Посчитав,что речь идет только об индексном массиве. Да, работает.
Danilw
>... там пара сотен(несколько тысяч максимум) полигонов ...
Ну да, у меня сцена из 6 тысяч полигонов, если все рисовать за один проход:
glDrawElements(GL_TRIANGLES, render_points, GL_UNSIGNED_INT, nullptr);
рендерится с FPS=1800. А если рендерить пошагово:
GLsizei max = (render_points / indices_per_quad) * vertices_per_quad; for ( GLsizei i = 0; i < max; i += vertices_per_quad) { glDrawElementsBaseVertex( GL_TRIANGLES, indices_per_quad, GL_UNSIGNED_INT, nullptr, i); }
то FPS падает всего до 1400 - не так уж и много. Отличная новость, всем спасибо!
однако :)
bigov
> то FPS падает всего до 1400 - не так уж и много
28 % ? на другой геометрии будет все 40 и более
Andrey
С какого перепугу? Это тебе не неубогое апи.
Кстати, кто тебя просадки учил в процентах измерять?
Тема в архиве.