В настоящее время я реализую алгоритм оценки позы, предложенный в Ойкономидис и др., 2011 г., который включает в себя рендеринг сетки в N
различных гипотетических позах (N
, вероятно, будет около 64). В разделе 2.5 предлагается ускорить вычисления с помощью создания экземпляров для одновременной генерации нескольких визуализаций (после чего они сокращают каждую визуализацию до одного числа на графическом процессоре), и, судя по их описанию, похоже, что они нашли способ производить N
визуализации одновременно.
На этапе настройки моей реализации я использую массив окон просмотра OpenGL для определения GL_MAX_VIEWPORTS
окон просмотра. Затем на этапе рендеринга я передаю массив матриц GL_MAX_VIEWPORTS
модели-позы в массив mat4
uniform
в памяти графического процессора (меня интересует только оценка положения и ориентации) и использую gl_InvocationID
в моем шейдере геометрии, чтобы выбрать подходящую матрицу поз и viewport для каждого полигона меша.
GL_MAX_VIEWPORTS
на моей машине 16 (у меня GeForce GTX Titan), поэтому этот метод позволит мне рендерить до 16 гипотез одновременно на GPU. Это может оказаться достаточно быстрым, но мне, тем не менее, любопытно следующее:
Есть ли обходной путь для ограничения GL_MAX_VIEWPORTS
, который, вероятно, будет быстрее, чем вызов моей функции рендеринга ceil(double(N)/GL_MX_VIEWPORTS)
раз?
Я только пару недель назад начал изучать шейдерный подход к OpenGL, так что еще не знаю всех хитростей. Первоначально я думал заменить использование встроенной поддержки видового экрана комбинацией:
h*gl_InvocationID
к y
координатам вершин после проекции перспективы (где h
— желаемая высота области просмотра) и передающий gl_InvocationID
на фрагментный шейдер; а такжеdiscard
создает фрагменты с y
координатами, которые удовлетворяют y<gl_InvocationID*h || y>=(gl_InvocationID+1)*h
.Но я отложил дальнейшее изучение этой идеи из-за страха, что ветвление и discard
будут очень вредны для производительности.
Авторы статьи выше опубликовали технический отчет, описывающий некоторые из их методов ускорения графического процессора, но он недостаточно подробен, чтобы ответить на мой вопрос. Раздел 3.2.3 говорит «Во время создания экземпляров геометрии информация об области просмотра прикрепляется к каждой вершине... Пользовательский пиксельный шейдер отсекает пиксели, которые находятся за пределами их предопределенных областей просмотра».. Это звучит похоже на обходной путь, который я описал выше, но они использовали Direct3D, поэтому непросто сравнить то, чего они смогли достичь в 2011 году, с тем, что я могу сделать сегодня в OpenGL.
Я понимаю, что единственный окончательный ответ на мой вопрос — реализовать обходной путь и измерить его производительность, но в настоящее время это малоприоритетное любопытство, и я не нашел ответов нигде, поэтому я надеялся, что более опытный пользователь GLSL может быть в состоянии предложить свою экономящую время мудрость.
При беглом взгляде на статью мне кажется, что фактический окно просмотра не меняется. То есть вы по-прежнему выполняете рендеринг с той же шириной/высотой и положениями X/Y с тем же диапазоном глубины.
Что вы хотите, так это изменить, на какой изображение вы выполняете рендеринг. Для чего предназначен gl_Layer
; чтобы изменить, какой слой в многоуровневом массиве изображений, прикрепленных к буферу кадра, в который вы выполняете рендеринг.
Так что просто установите gl_ViewportIndex
на 0 для всех вершин. Или, точнее, не устанавливайте его вообще.
Количество Вызовы инстансов GS не является ограничением имеют; это ваш выбор. Вызовы GS могут записывать несколько примитивов, каждый на свой уровень. Таким образом, вы можете сделать так, чтобы каждый экземпляр записывал, например, 4 примитива, каждый в 4 отдельных слоя.
Единственными ограничениями должны быть количество слоев, которые вы можете использовать (регулируется GL_MAX_ARRAY_TEXTURE_LAYERS
и GL_MAX_FRAMEBUFFER_LAYERS
, оба из которых должны быть не менее 2048), а также количество примитивов и данных вершин, которые может сгенерировать один вызов GS (которое равно довольно сложный).
Спасибо за это предложение! Потребовалось некоторое время, чтобы выяснить, как выполнить рендеринг в глубине прикрепления массива текстур, а затем прочитать результат, чтобы убедиться, что он работает (мне пришлось переключиться с использования glReadPixels
на glGetTextureImage
). К сожалению, предел далеко не так высок, как GL_MAX_ARRAY_TEXTURE_LAYERS
, так как вы можете создавать только MAX_GEOMETRY_SHADER_INVOCATIONS
экземпляров геометрического шейдера, а на моей машине их 32. Это все же лучше, чем ограничение GL_MAX_VIEWPORTS
, поэтому я принял ваш ответ.
Раздел 3.2.3 технического отчета, на который я ссылался в своем ответе, называется «отсечение нескольких окон просмотра», поэтому кажется довольно очевидным, что они отображались в разных окнах просмотра параллельно. Неясно, использовали ли они встроенную поддержку области просмотра или смоделировали ее с помощью discard
, как и вопрос о том, действительно ли они смогли визуализировать все свои гипотезы одновременно.
@Ose: вызовы GS не являются ограничением; см. мой ответ.
О, хорошо, я напишу несколько примитивов! Еще раз спасибо за помощь!
Я столкнулся с другим ограничением: количество доступных униформ (khronos.org/opengl/wiki/Uniform_(GLSL)#Implementation_limits). Мне нужен массив N
mat4
(по одному на каждую гипотезу) и дополнительный mat4
для проекционной матрицы, но моя машина не позволит мне определить более 128 mat4
униформ. Этот вопрос предлагает обойти это с помощью объектов юниформ-буфера: stackoverflow.com/q/20647207/1292784 . Но мне все равно больше 127 гипотез не понадобится.
Действительно ли ваш видовые экраны (то есть параметры
glViewport
) меняется с «просмотра» на «просмотр»? Судя по беглому описанию вашего алгоритма, я так не думаю.