Без окон OpenGL
Я хотел бы иметь контекст OpenGL без окон (на GNU/Linux с Xorg и Windows). Я не собираюсь ничего делать, кроме как только функции вызова, такие как glGetString
, glCompileShader
и тому подобное.
Я сделал некоторые очки, но не придумал ничего полезного, кроме создания скрытого окна; который кажется мне взломанным.
У кого-то есть лучшая идея (для любой платформы)?
EDIT: с Xorg мне удалось создать и прикрепить контекст OpenGL к корневому окну:
#include<stdio.h>
#include<stdlib.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
int main(int argc, const char* argv[]){
Display *dpy;
Window root;
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo *vi;
GLXContext glc;
dpy = XOpenDisplay(NULL);
if ( !dpy ) {
printf("\n\tcannot connect to X server\n\n");
exit(0);
}
root = DefaultRootWindow(dpy);
vi = glXChooseVisual(dpy, 0, att);
if (!vi) {
printf("\n\tno appropriate visual found\n\n");
exit(0);
}
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
glXMakeCurrent(dpy, root, glc);
printf("vendor: %s\n", (const char*)glGetString(GL_VENDOR));
return 0;
}
EDIT2: Я написал короткую статью о windowless opengl (с образцом кода) на основе принятого ответа.
Ответы
Ответ 1
На самом деле, необходимо создать дескриптор окна для создания "традиционного" контекста рендеринга (для этого подходят корневое окно на X11 или окно рабочего стола Windows). Он используется для получения информации о доступности и расширениях OpenGL.
Как только вы получите эту информацию, вы можете уничтожить контекст визуализации и отпустить окно "dummy"!
Вы должны проверить расширения ARB_extensions_string и ARB_create_context_profile (описанные на этой странице: ARB_create_context). Затем вы можете создать контекст визуализации, вызвав CreateContextAttribs, независимо от платформы, без связанного системного окна и требующего только контекста системного устройства:
int[] mContextAttrib = new int[] {
Wgl.CONTEXT_MAJOR_VERSION, REQUIRED_OGL_VERSION_MAJOR,
Wgl.CONTEXT_MINOR_VERSION, REQUIRED_OGL_VERSION_MINOR,
Wgl.CONTEXT_PROFILE_MASK, (int)(Wgl.CONTEXT_CORE_PROFILE_BIT),
Wgl.CONTEXT_FLAGS, (int)(Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT),
0
};
if ((mRenderContext = Wgl.CreateContextAttribs(mDeviceContext, pSharedContext, mContextAttrib)) == IntPtr.Zero)
throw new Exception("unable to create context");
Затем вы можете связать объект буфера фрейма или системное окно с созданным контекстом визуализации, если хотите рендерить (но, как я понимаю, вы хотите скомпилировать только шейдеры).
Использование CreateContextAttribs имеет много преимуществ:
- независимая от платформы
- Можно запросить конкретную реализацию OpenGL
- Возможно запросить реализацию 3.2 OpenGL
- Возможно форсировать опцию прямой совместимости (только шейдерный рендеринг, что будет в будущем)
- Возможно выбрать (только в прямом совместимом контексте) конкретный профиль реализации OpenGL (на самом деле существует только профиль CORE, но может быть больше в будущее.
- Возможно включить параметр отладки, даже если не определено, как этот параметр может использоваться фактической реализацией драйвера
Однако старые аппаратные средства/драйверы не смогли реализовать это расширение, поэтому я предлагаю написать резервный код, чтобы создать обратный совместимый контекст.
Ответ 2
Пока вы не создадите окно, OpenGL не знает, какую реализацию вы используете. Например, существует очень другой драйвер (и разное аппаратное ускорение) для OpenGL в удаленном сеансе X-Windows против OpenGL в сеансе DRI X-Windows. Поддержка шейдерных языков может быть разной между этими случаями, и вывод шейдерного компилятора определенно будет зависящим от реализации, а также любые ошибки, созданные на основе исчерпания ресурсов.
Таким образом, хотя фактически создание окна может быть не на 100% необходимым, вы должны каким-то образом связать свой контекст с графическим оборудованием (или его отсутствием), и поскольку это можно сделать с помощью окна, никто не беспокоился о внедрении альтернативного метода.
Ответ 3
Вам нужно окно для размещения контекста, и вам нужен контекст, чтобы иметь возможность сделать что-либо.
Источник
Если вы не хотите отображать что-либо, сделайте окно невидимым.
Если бы был другой способ сделать это, он был бы где-то документирован и легко найден, поскольку это не необычная проблема.
Ответ 4
Одна из вещей, которые я сделал - которая, по общему признанию, немного взламывает - чтобы избежать накладных расходов на создание моего собственного окна GL, - это использовать открытые окна процессов.
Ключом к пониманию OpenGL является следующее: все, что вам нужно для создания контекста GL с вызовом wglCreateContext, является допустимым DC.
В документации, в которой говорится, что она должна быть тем, кем вы являетесь, нет НИЧЕГО.
Чтобы проверить это, я вытащил Worlds Of Warcraft и, используя SPY ++, чтобы получить дескриптор окна, я вручную подключил этот дескриптор к вызову GetDC, который возвращает действительный контекст устройства, и оттуда я запускал остальная часть моего кода GL, как обычно.
Нет создания окна GL моего собственного.
Вот что произошло, когда я сделал это с помощью Worlds of Warcraft и Star Trek Online https://universalbri.wordpress.com/2015/06/05/experiment-results
Итак, чтобы ответить на ваш вопрос, ДА вам нужно окно, но в документации нет ничего, что говорит о том, что окно должно принадлежать вам.
Теперь имейте в виду: я не мог заставить этот метод предоставлять действительный визуальный результат с помощью окна рабочего стола, но мне удалось успешно создать DC, используя API-интерфейс getDeskTopWindow для HWND, а затем вызов GetDC. Поэтому, если есть не визуальная обработка, которую вы хотите использовать OpenGL, дайте мне знать, что вы делаете, мне интересно, и если вам нужно получить метод GetDesktopWindow, работающий с визуальными эффектами, - ПОЖАЛУЙСТА, повторите в этой теме то, что вы сделали.
Удачи.
И не позволяйте никому говорить вам, что это невозможно.
Когда там будет какой-то способ.