8

I have a task to implement offscreen OpenGL renderer both for Window and Linux in C++.I have such a version already written in Java using LWJGL lib.There I used PBuffer object ,which under hood creates Pbuffers based on the used OS.First I thought to re-implement the full PBuffer creation logic just as it i done in native source of LWJGL.Then I read this post on StackOverflow.com where it is suggested using the standard context creation ,let's say using GLFW (which is cross platform) but not to create the actual window.Is it the right way to go? What are pros and cons vs using Pbuffer in such a case?

Update: I just want to emphasize that I use FBOs to render the frames so my problem here is not how to render in offscreen mode but how to create a context without window both in Windows and Linux OSs.

Community
  • 1
  • 1
Michael IV
  • 11,016
  • 12
  • 92
  • 223

3 Answers3

6

I'd highly recommend not to use PBuffers anymore but to use Frame Buffer Objects (FBOs) instead. FBOs offer much better performance as using them does not require a context switch and they have several other advantages.

LWJGL supports FBOs, but GLFW is "just" for cross-platform setup of OpenGL and not for rendering. For convenient cross-platform FBO usage I'd recommend to use a library like OGLplus on top of GLFW. See here for a render-to-texture example.

McManip
  • 155
  • 1
  • 9
sschuberth
  • 28,386
  • 6
  • 101
  • 146
  • 1
    That is right ,I do assume using FBOs.But FBOs don't create GL context ,that is why I am asking this question. – Michael IV Jan 10 '13 at 09:23
  • If you want hardware acceleration, at least on Windows, you cannot create an OpenGL context without creating a (hidden) window first. That's because [wglCreateContext](http://msdn.microsoft.com/en-us/library/windows/desktop/dd374379(v=vs.85).aspx) expects a Device Context (DC), and only a window's DC can have a hardware accelerated pixel format assigned. In particular, you [cannot render with hardware accelerated OpenGL into a memory DC](http://www.opengl.org/discussion_boards/showthread.php/161374-Why-can-t-i-write-to-a-memory-device-context?p=1143832&viewfull=1#post1143832). – sschuberth Jan 10 '13 at 09:45
  • So do you mean Windows version of PBuffer in LWJGL creates window anyway and then removes it ? – Michael IV Jan 10 '13 at 09:50
  • I mean any hardware-accelerated OpenGL application on Windows creates a (potentially hidden) window, no matter whether it uses PBuffers, FBOs or no offscreen rendering at all. – sschuberth Jan 10 '13 at 10:26
  • 1
    @MichaelIV: OpenGL context creation is always plattform dependent being it on a window or not. There is the EGL API, but it is not widely supported yet. – datenwolf Jan 10 '13 at 15:47
  • Can you extended on why not to use pbuffers? Also of I use the standard GLFW setup which creates window but use my FBOs,don't I get any performance issues with that exsiting window? – Michael IV Jan 10 '13 at 18:53
  • There's no performance hit due to the existing window, it just might not be (explicitly) used. For example, you could do some offscreen rendering into the FBO only and save the result as an image to disk without ever seeing what is being rendered. However, if your application requires to alternately render to both the window and offscreen, e.g. for [dynamic environment mapping](http://www.mbroecker.com/page2/page12/page12.html), that would require expensive context switching with PBuffers (which have their own context) as opposed to FBOs (which use the window's context). – sschuberth Jan 10 '13 at 20:03
  • Ah now I see, well my need of pbuffer was only in relation to context creation. All the rendering is done with FBOs always. Well thanks for the tips! – Michael IV Jan 10 '13 at 21:40
2

The Simple DirectMedia Layer (SDL) library is worth a try. It simplifies cross-platform OpenGL context creation, with the ability to use memory surfaces for off-screen rendering.

The only thing you would have to do extra, is to include your OpenGL and SDL headers from different locations, depending on your platform. This can be done with simple pre-processor directives.

mcvz
  • 494
  • 4
  • 13
0

As far as I know there is no cross-platform way to create contexts, you will have to create your own abstraction and then implement it for each platform.

On windows I have used the following code to create a second context to do loading of content in a background thread (this program used GLFW but that should not matter):

void Program::someFunction()
{
    HDC hdc = wglGetCurrentDC();
    HGLRC hglrc = wglGetCurrentContext();
    HGLRC hglrc_new = wglCreateContext(hdc);
    wglShareLists(hglrc, hglrc_new);
    loadThread = boost::thread(&Program::loadFunc, this, hdc, hglrc_new);
}

/**
 * Imports all our assets. Supposed to run in its own thread with its own OpenGL context.
 * @param hdc The current device context.
 * @param hglrc A OpenGL context thats shares its display list with the main rendering context.
 */
void Program::loadFunc(HDC hdc, HGLRC hglrc)
{   
    wglMakeCurrent(hdc, hglrc);

        //Do stuff...

    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(hglrc);
}
Daniel
  • 3,741
  • 1
  • 16
  • 21