Один контекст OpenGL, несколько представлений

У меня есть приложение для Windows, которое может создавать несколько окон просмотра, которые могут отображать некоторые модели с использованием OpenGL (3.2+). Каждое окно может отображать свой собственный независимый объект, или два (или более) окна могут отображать один и тот же объект (но, например, с разных точек зрения камеры):

пример

После прочтения различных сообщений здесь, в stackoverflow, я решил создать единый контекст OpenGL (HGLRC) и для каждого окна, в которое я отображаю (HDC), я переключаюсь с помощью

wglMakeCurrent(targetWindowHDC, m_deviceContext)

Как вы можете видеть на снимке экрана, в принципе это работает нормально (код окна выполняется в основном потоке, а для рендеринга у меня есть собственный RenderThread, которым ограничены все операции OpenGL). Для каждого из окон я визуализирую в FBO (который имеет поддержку MSAA, если пользователь активирует его), который обновляется только в случае изменения чего-либо в сцене, в противном случае он просто отрисовывает его в окно как есть.

Теперь мой вопрос: какие состояния мне нужно устанавливать каждый раз, когда я переключаюсь на рисование в другом окне? И разумен ли мой подход с точки зрения производительности?

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

glClearDepth( 1.0f );
glClearColor( color.r, color.g, color.b, 1.0f );
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glPointSize(3.0f);
glEnable(GL_BLEND);
glBlendFunc( srcBlend, dstBlend );
glPolygonMode( GL_FRONT_AND_BACK, targetType );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );    
glViewport( 0, 0, vp.width, vp.height );

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

Но действительно ли необходимо делать все эти звонки? Это означает, что в приведенном выше примере с 4 окнами рендеринга мне нужно вызывать их 4 раза в каждом кадре. Есть ли способ лучше? Будет ли это более эффективно с несколькими контекстами GL?


person Bjoern    schedule 08.05.2014    source источник
comment
Если, например, glDepthFunc остается одинаковой во всех четырех окнах рендеринга, то нет необходимости устанавливать ее для каждого окна! Просто установите его один раз в начале цикла рендеринга.   -  person Eejin    schedule 08.05.2014
comment
Спасибо за ваш отзыв. Ну, проблема в том, что я не знаю, изменится ли это, пользователь может создавать новые окна в своем приложении, о которых я не знаю заранее, и устанавливать разные атрибуты для каждого RenderView. Было интересно, есть ли какой-то эквивалент VAO или около того, который можно было бы использовать для объединения вызовов в один.   -  person Bjoern    schedule 08.05.2014


Ответы (1)


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

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


Использование одного и того же контекста для нескольких окон имеет смысл, если тип рендеринга одинаков для всех окон. Например, в типичном средстве 3D-моделирования есть «квадратный вид». Если эти подпредставления реализованы с использованием нескольких окон, то повторное использование одного контекста имеет смысл.

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

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

Итак, как вы решаете, использовать несколько контекстов или один. Ну это легко:

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

Если содержимое окон сильно различается, то несколько контекстов.

person datenwolf    schedule 08.05.2014
comment
Спасибо за ваш отзыв. Проблема в том, что я не могу быть уверен, что будет нарисовано, возможно, что один и тот же вид может быть отрисован из разных окон просмотра, или что каждый из них рисует что-то свое (скажем, это может быть автомобиль, другой может быть автомобилем). только двигатель, и еще какие-то другие части.. так они связаны тем, что тема у них одна, а модели разные). Ok очистит те звонки, которые вы упомянули. - person Bjoern; 08.05.2014
comment
@Bjoern: Имейте в виду, что помимо создания нескольких окон HWND вы также можете использовать glViewport + glScissor для создания логических подокон OpenGL при рендеринге внутри фактического окна, в которое вы выполняете рендеринг. - person datenwolf; 08.05.2014
comment
О, спасибо за совет, да, я обязательно посмотрю! - person Bjoern; 08.05.2014