В OpenGL плохая идея «совмещать» немедленный режим и режим сохранения ради графического интерфейса?

8

Предположим, у меня нарисована 3D-сцена, glDrawArrays(...)и я хочу сделать что-то простое, например, 2D-наложение. Было бы плохой идеей использовать немедленный режим для такой вещи, вместо настройки 2D-рендеринга с сохраненным режимом?

Пример:

void Draw()
{
    // Draw the 3D scene:
    // *does stuff*
    glDrawArrays(...);
    // *some other stuff*

    // Setup a quad with immediate mode (for something like a vignette overlay)
    glBegin(GL_QUADS);
    glTexCoord2f(...); glVertex2f(...);
    glEnd();
}
KK Slider
источник
Minecraft делает это. Он работает нормально, за исключением ограничения вашей версии OpenGL (до <3.1 или профиля совместимости) и для того, чтобы сделать ваш графический интерфейс менее быстрым.
user253751
Примечание. Minecraft также имеет свой собственный набор функций, которые имитируют непосредственный режим с использованием массивов вершин - это не сложно написать. Я не уверен, что они используют их для GUI.
user253751

Ответы:

7

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

Переносимость, вероятно, не является проблемой, хотя и должна быть. IHV, похоже, очень неохотно отказываются от поддержки немедленного режима в обозримом будущем (кажется, что он «работает» даже в основных профилях), поэтому, хотя немедленный режим должен был давно исчезнуть, он, вероятно, останется навсегда. Производительность это другая история. Вы действительно хотите, чтобы что-то, что составляет 0,1% сложности сцены, занимало 15-20% процессорного времени - вызовы GL относительно легки по сравнению, например, с DX, но они не бесплатны - и 15-20% реальное время кадра из-за остановки трубопровода? Вы можете даже позволить себе это с вашим временным бюджетом? Большинство игр не могут.

И, конечно, причуды. О, причуды. Очевидная красота немедленного режима заключается в том, что (на первый взгляд) легко и просто сделать что-то вроде быстрого рисования пары четырехугольников. В действительности немедленный режим может быть такой болью в тылу, он полон неочевидных ловушек.
С другой стороны, так же просто (и более просто, если вы спросите меня!) Просто написать небольшую функцию 5-LOC, DrawQuadкоторая при вызове добавляет координаты вершины и индексы в буфер памяти и увеличивает счетчик. Который, к удивлению, вы можете затем нарисовать, glDrawArrays/Elementsи который вы можете использовать повторно (копию GPU, а не только копию пользовательской области!) В следующем кадре, пока ничего не изменилось.
Непосредственный режим должен, иначе нет, выделить буфер и каждый раз выполнять передачу PCIe. Или что-то эквивалентное по задержке (GPU читает основную память по шине, что угодно). Драйвер не может знать (или предполагать), что данные остались в точности такими же, как в предыдущем кадре.

Передача данных в графический процессор - это высокоскоростная, но также высокопроизводительная операция. Перенос по шине сам по себе является сложным протоколом с высокой задержкой (несколько уровней протоколов, пакетирование, подтверждения и т. Д.), Но также не все графические процессоры способны даже передавать и рисовать одновременно или если они могут это делать они могут быть не в состоянии все время переключаться или инициировать новые операции свободно, делая что-то другое. Читайте как: Ты не будешь переносить напрасно .

Damon
источник
«Ничего« ​​настроить », что вы еще не сделали» Пакетный рендеринг?
HolyBlackCat
2
Хотя IHV не хотят отказываться от немедленного режима, в Linux также есть видеодрайверы, которые не поддерживают более высокую версию OpenGL, если вы не запросите Core Profile. Это, в частности, означает графику Intel HD ( intelдрайвер), а также чипы NVidia и AMD при использовании драйверов с открытым исходным кодом ( nouveauи amdgpuсоответственно). Аналогично, в MacOS у вас также нет профиля совместимости с OpenGL> 2.1.
Руслан
@HolyBlackCat: я не уверен, что вы имеете в виду? OP состояния, имеющие рабочий 3D-конвейер на основе glDrawArrays. Таким образом, есть все, что нужно сделать, чтобы сделать еще один вызов glDrawElements(или Array, в зависимости от того), чтобы нарисовать все квады для GUI (после записи вершин в буфер). Функции загружены, у вас есть структура для распределения буферов и т. Д. Ничего особенного не нужно делать с пакетированием графического интерфейса, на самом деле. Просто свяжите (или нет, если у вас осталось достаточно TU, чтобы оставить его связанным) с текстурой GUI, установите орто-матрицу и выполните один дополнительный вызов отрисовки. Как вы хотите выпечки лучше?
Деймон,
(Конечно, я согласен, что немедленный режим плох.) Извините, если я не был ясен. Я имею в виду процесс заполнения указанного буфера вершин. Это легко, но это немного больше работы, чем в непосредственном режиме.
HolyBlackCat
12

Лично я считаю это плохим по двум причинам:

  1. Это очень устарело и устарело. А также,
  2. Это намного медленнее, чем современные способы рисования с OpenGL.

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

Пойми это, хотя. Что в конце дня OpenGL делает то же самое; рисование на экране. Немедленный режим просто намного медленнее, если вы обрабатываете много вещей. Итак, вы должны выбрать, что является наиболее полезным для задачи, которую вы имеете в виду. Надеюсь, что это помогает вам!

dev9999
источник
1

Другим недостатком является то, что он делает ваш код менее переносимым. Некоторые варианты OpenGL вообще не поддерживают непосредственный режим, например, OpenGL ES. (и по мере того, как устройства на базе Android более крупного калибра, такие как планшеты, приобретают все большую популярность, это может стать важным)

Показать имя
источник
0

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

Чтобы создать простой элемент графического интерфейса, скажем, кнопку:

  1. Вам нужна сетка из четырех квадратов,
  2. Текстура для сетки
  3. Ортографическое проекционное преобразование

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

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

Ян Янг
источник