如何使用GLUT/OpenGL渲染文件?

yhuiod9q  于 2022-11-04  发布在  其他
关注(0)|答案(6)|浏览(211)

我有一个程序,它模拟一个随时间变化的物理系统。我想以预定的间隔(比如每10秒)将模拟状态的可视化输出到一个文件中。我想以这样一种方式来做,即很容易“关闭可视化”,根本不输出可视化。
我把OpenGL和GLUT作为图形工具来做可视化。然而问题似乎是,首先,它看起来只能输出到一个窗口,而不能输出到一个文件。其次,为了生成可视化,你必须调用GLUTMainLoop,这会停止主函数的执行--从那时起,唯一被调用的函数是来自GUI的调用。然而,我不希望这是一个基于GUI的应用程序-我希望它只是一个应用程序,你从命令行运行,它会生成一系列的图像。有没有办法在GLUT/OpenGL中做到这一点?或者OpenGL是完全错误的工具,我应该使用其他东西

aor9mmx1

aor9mmx11#

无论如何,你几乎肯定不想要GLUT,因为你的需求不符合它的预期用途(即使你的需求 * 确实 * 符合它的预期用途,你通常也不想要它)。
你可以使用OpenGL。要在文件中生成输出,你基本上需要设置OpenGL渲染一个纹理,然后将生成的纹理读入主内存并保存到一个文件中。至少在某些系统上(例如Windows),我敢肯定你仍然需要创建一个窗口,并将渲染上下文与窗口相关联,尽管如果窗口总是隐藏的话,这 * 可能 * 是好的。

pw136qt2

pw136qt22#

不是要从其他优秀的答案中删除,但是如果您需要一个现有的示例,我们已经在OpenSCAD中进行了几年的Offscreen GL渲染,作为从命令行渲染到.png文件的测试框架的一部分。相关文件位于Offscreen*.cc下的https://github.com/openscad/openscad/tree/master/src
它在OSX上运行(CGL),Linux X11(GLX),BSD格式(GLX)和视窗(WGL),由于驱动程序的差异而有一些怪癖。基本的窍门是忘记打开一个窗口(例如,道格拉斯亚当斯说飞行的诀窍是忘记撞到地面)。如果你有一个像Xvfb或Xvnc一样运行的虚拟X11服务器,它甚至可以在“无头”linux/bsd上运行。在Linux/BSD上也可以使用软件渲染,方法是在运行程序之前将环境变量LIBGL_ALWAYS_SOFTWARE设置为1,这在某些情况下会有所帮助。
这并不是唯一一个这样做的系统,我相信VTK成像系统也做了类似的事情。
这段代码在方法上有点旧(我从Brian Paul的glxgears中撕下了GLX代码),尤其是随着新系统的沿着,OSMesa、Mir、Wayland、EGL、Android、Vulkan等,但请注意OffscreenXXX.cc文件名,其中XXX是GL上下文子系统,理论上可以将其移植到不同的上下文生成器。

egmofgnx

egmofgnx3#

不确定OpenGL是否是最佳解决方案。
但您始终可以渲染到屏幕外缓冲区。
将openGL输出写入文件的典型方法是使用readPixels将生成的场景像素-像素复制到图像文件

oknrviil

oknrviil4#

您可以使用SFML http://www.sfml-dev.org/。您可以使用image类保存渲染输出。
http://www.sfml-dev.org/documentation/1.6/classsf_1_1Image.htm
若要获得渲染输出,可以渲染到纹理或复制屏幕。

渲染到纹理:

l7mqbcuq

l7mqbcuq5#

1.使用带有PbufferSurface而不是WindowSurface的EGL进行屏幕外渲染

EGLDisplay display;
EGLSurface surface;
EGLContext context;

//bind desktop OpenGL
eglBindAPI(EGL_OPENGL_API);
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);

//example constraints
const EGLint egl_config_constraints[] = {
    EGL_STENCIL_SIZE, static_cast<EGLint>(8),
    EGL_DEPTH_SIZE, static_cast<EGLint>(16),
    EGL_BUFFER_SIZE, static_cast<EGLint>(32),
    EGL_RED_SIZE, static_cast<EGLint>(8),
    EGL_GREEN_SIZE, static_cast<EGLint>(8),
    EGL_BLUE_SIZE, static_cast<EGLint>(8),
    EGL_ALPHA_SIZE, static_cast<EGLint>(8),
    EGL_SAMPLE_BUFFERS, EGL_FALSE,
    EGL_SAMPLES, 0,
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
    EGL_CONFORMANT, EGL_OPENGL_BIT,
    EGL_CONFIG_CAVEAT, EGL_NONE,
    EGL_NONE };

EGLint configCount;
EGLConfig configs[1];

//find a fitting config
eglChooseConfig(display, egl_config_constraints, configs, 1, &configCount);

//set up the PbufferSurface
EGLint pbuffer_attrib_list[] = {
    EGL_WIDTH, WIDTH,
    EGL_HEIGHT, HEIGHT,
    EGL_NONE };

surface = eglCreatePbufferSurface(display, configs[0], pbuffer_attrib_list);

//setup the EGLContext
const EGLint contextVersion[] = {
    EGL_CONTEXT_MAJOR_VERSION, 4,
    EGL_CONTEXT_MINOR_VERSION, 6,
    EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
    EGL_CONTEXT_OPENGL_DEBUG, debug ? EGL_TRUE : EGL_FALSE,
    EGL_NONE };
context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, contextVersion);
eglMakeCurrent(display, surface, surface, context);
eglSwapInterval(display, 1);

2.保存图像

有几种方法可以实现这一点。实际上,上面的代码是我写的一个演示(https://github.com/kallaballa/GCV/blob/main/src/tetra/tetra-demo.cpp)的一部分,它使用OpenCL/OpenGL/VAAPI互操作性结合OpenCV来编写一个用OpenGL渲染的视频。
如果您想构建演示,请参考自述文件。

相关问题