简体   繁体   中英

Reading OpenGL's default framebuffer in a windowless GLX program

I would like to perform some 3D rendering on my Debian machine and bring the result into client-side memory.

I've created a C++, GLX, and GLEW based application that does not require a window. I get a display with glXOpenDisplay , use it to find a proper framebuffer with glXChooseFBConfig (passing the DefaultScreen of the display), obtain visual info with glXGetVisualFromFBConfig , and pass the relevant information to glXCreateContext . I make that context current & initialize GLEW.

As a starting test, I'm simply clearing the default framebuffer with a variety of colors; I would like to now query the result pixel-by-pixel, presumably with glReadPixels .

But this is where I seem to be fundamentally misunderstanding something: What are the dimensions of the default framebuffer? I never define an initial height or a width for it, and I'm not seeing a way to do so.

Answers such as this one imply the window "defines" the dimensions. In my application, is the DefaultScreen defining the dimensions? If that's the case, what can I do to make the default framebuffer larger than a particularly small screen?

and pass the relevant information to glXCreateContext. I then initialize GLEW.

Just because you have a context does not mean, that you can immediately use it. Consider what happens if you have more than one context. Before you can make OpenGL calls, you have to make active a context on the current thread, using glXMakeCurrent or glXMakeContextCurrent . If you look at those functios' signatures you'll see that they take a Drawable as parameter in addition to the OpenGL context. So you need that, too.

For windowless operation GLX offers PBuffers, which offer windowless drawables. Or you could use a window that you don't map to the screen. PBuffers allow to do offscreen rendering without the use of framebuffer objects, but the use of their main framebuffer is a bit finicky. My recommendation is the use of a 0×0 sized PBuffer and a framebuffer object.

You need to use framebuffer objects. These use textures whose dimensions you have specified. For example:

// Generate framebuffer ID
GLuint fb;
glGenFramebuffers(1, &fb);

// Make framebuffer active
glBindFramebuffer(GL_FRAMEBUFFER, fb);

// Attach color and depth textures (must have same dimensions)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_tex, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0);

// Check framebuffer is valid
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM