1

我想使用 OpenGL(1.5 版)将图像渲染到内存,而不在屏幕上显示它们(例如,我可以将它们保存为图像文件或在终端中将它们渲染为 ASCII)。我不想要任何 I/O。我在 SO 发现了类似的问题,但没有一个可以解决我接下来的具体进一步要求。

现在我想我可以使用像 glx 这样的库并告诉它不要打开任何窗口,但是我也不希望我的代码依赖于像 X11 这样的任何窗口系统库,因为我的程序根本不对任何窗口做任何事情或 I/O,我不明白为什么我的程序应该依赖于 X 窗口(因为某些系统根本没有 X 窗口,它们甚至可能根本没有图形界面)。我的程序应该只依赖于 OpenGL 驱动程序。

我知道为此我需要创建一个 OpenGL 上下文,它不是 OpenGL 的一部分,它依赖于平台,所以实际上我可能需要一些库来理想地以多平台方式创建 OpenGL 渲染到内存上下文(即抽象掉依赖于平台的东西)。这样的事情存在吗?(我对任何专有的、特定于 GPU 或特定于驱动程序的软件不感兴趣,该程序应该在任何支持给定 OpenGL 版本的 GPU 上运行。)还有什么我应该考虑的吗?

基本上我希望我的程序非常小,并且不会因为它不需要的东西而负担,因为它所需要的只是使用通用的 OpenGL 驱动程序将图像渲染到内存中,并且应该在任何具有这种 OpenGL 驱动程序的系统上工作。

谢谢你。

4

1 回答 1

3

根据您使用的操作系统和驱动程序的可用性,您可以使用 EGL 进行纯、无头、GPU 加速的 OpenGL 渲染。Nvidia 在https://developer.nvidia.com/blog/egl-eye-opengl-visualization-without-x-server/上有一个很好的开发者博客关于如何做到这一点

它的要点是,在显示设备上创建 EGL 上下文而不将其与输出相关联。来源(直接从链接文章复制):

#include <EGL/egl.h>
static const EGLint configAttribs[] = {
          EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
          EGL_BLUE_SIZE, 8,
          EGL_GREEN_SIZE, 8,
          EGL_RED_SIZE, 8,
          EGL_DEPTH_SIZE, 8,
          EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
          EGL_NONE
};    

static const int pbufferWidth = …;
static const int pbufferHeight = …;

static const EGLint pbattr[] = {
        EGL_WIDTH, pbufferWidth,
        EGL_HEIGHT, pbufferHeight,
        EGL_NONE,
};

int main(int argc, char *argv[])
{
  EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  EGLint major, minor;
  eglInitialize(eglDpy, &major, &minor);
  EGLint numConfigs;
  EGLConfig eglCfg;

  eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
  EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg, pbattr);
  eglBindAPI(EGL_OPENGL_API);
  EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, NULL);    
  eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);

  do_opengl_stuff();

  eglTerminate(eglDpy);
  return 0;
}

如果您无法访问 EGL,但您的操作系统和 GPU 受 Linux DRM/DRI 支持,您可以走 KMS/GBM 路线,并且值得通过扩展机制获得帧缓冲区对象(嗯,使用 Mesa,您可以即使使用 OpenGL-1.x,也可以像使用它们一样使用它们)。kmscube演示有一个“表面”模式,它演示了如何做到这一点。

简而言之:EGL 是一种“干净”的方式。KMS 是一种“hacky”方式。

另一个选择,现在可能完全超出你的范围,是使用 Vulkan,严格来说,无头渲染是“默认”,在屏幕上获取内容的方法是对规范的实际扩展:

    VK_KHR_wayland_surface
    VK_KHR_xcb_surface
    VK_KHR_xlib_surface
    VK_KHR_win32_surface
于 2021-07-08T12:25:18.993 回答