Integration into an existing OpenGL application

Introduction

This tutorial creates a standalone window, using the basic operating system features: A Win 32 window on Windows, a X11 window on Linux and a Cocoa view on OSX. Then, we create a simple OpenGL rendering context and draw a rotating cube into that window. The standalone window renders like that:

The basic OpenGL application built by the tutorial.

Then, we create and setup a REDsdk window so that it can co-exist and render into the same window as our application, using the existing window application context. This illustrates how REDsdk can be used to enrich an existing application graphics or how it can be used to replace parts of a graphic pipeline.

This capability is very important as it allows a smooth integration of REDsdk into an existing OpenGL application, without breaking any legacy graphics layer, that could be difficult to rewrite from scratch otherwise.

Adding the REDsdk window

The tutorial is divided into 4 steps:

  1. Creation of the window for the considered OS.
  2. Creation of the OpenGL context.
  3. Creation of the REDsdk window to work in this environment (with a simple scene setup).
  4. Rendering of both the original OpenGL code AND REDsdk for the same frame.

The REDsdk window uses an auxiliary RED::WindowRenderInfo to source the application OpenGL parameters:

RED_RC rc;
RED::Object* window;

RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
if( !resmgr )
  RC_TEST( RED_FAIL );

RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

RED::WindowRenderInfo winfo;
winfo.SetBufferSwapping( false );

#if defined( _WIN32 )

winfo.SetHostingContext( hdc, hrc );
window = RED::Factory::CreateREDWindow( *resmgr, hwnd, width, height, &winfo, rc );

#elif defined( _LIN32 )

winfo.SetHostingContext( xwin, glxctx );
window = RED::Factory::CreateREDWindow( *resmgr, (void*)xwin, display, screen, visual, width, height, NULL, rc );

#elif defined( _MAC32 )

winfo.SetHostingContext( ctx );
window = RED::Factory::CreateREDWindow( *resmgr, (void*)OSXGetWindowView( ns_window ), width, height, NULL, rc );

#endif

if( !window )
  RC_TEST( RED_FAIL );

RC_TEST( rc );

Note that we have chosen to disable the window buffer swapping so that this is the source application that'll control the window buffer swapping. We also disable any buffer clear from the REDsdk window's default VRL, so that we can draw the REDsdk OpenGL after the application's own OpenGL.

Then, we setup a default scene and here goes the rendering code:

RC_TEST( iwindow->RestoreHostState( hdc, hrc ) );

if( wglMakeCurrent( hdc, hrc ) == false )
  RC_TEST( RED_DRV_FAIL );

if( MyBeautifulCube() != 0 )
  RC_TEST( RED_FAIL );

RC_TEST( iwindow->RestoreREDState( hdc, hrc ) );

RC_TEST( iresmgr->EndState() );
RC_TEST( iwindow->FrameDrawing() );
iresmgr->BeginState();

::SwapBuffers( hdc );

We only quote the Windows OS source code version. Please refer to the source code directly for the Linux and MacOS versions. As detailed in the Integration into an external OpenGL window chapter of the documentation, we need to isolate the application OpenGL code from the REDsdk OpenGL code. This is performed by the RED::IWindow::RestoreREDState and RED::IWindow::RestoreHostState calls.

As a result, we have the mix of the application OpenGL code and REDsdk scene rendered both in the same color and depth buffers, as illustrated below:

The final view with the mix of REDsdk scene with the application OpenGL scene.