MULTIMEDIA

OpenGL on Windows : Full-Screen Rendering, Double Buffering

2/27/2013 8:40:31 PM

Full-Screen Rendering

Windowed OpenGL apps are great, but it’s hard to create an immersive game if your app isn’t in full-screen! One of the most common developer questions is “How do I do full-screen rendering with OpenGL?” The truth is,  you already know how to do full-screen rendering with OpenGL—it’s just like rendering into any other window! The real question is “How do I create a window that takes up the entire screen and has no borders?”

Even though this issue isn’t strictly related to OpenGL, it is of enough interest to a wide number of our readers that we give this topic some coverage here. Creating a full-screen window is almost as simple as creating a regular window the size of the screen and starting at (0,0). We also use a different window style because we have no need for a title bar or border because none of that is visible. The code in Listing 13.3 does just that.

Listing 1. Setting Up a Full-Screen Window
if(bUseFS)
{
    // Prepare for a mode set to the requested resolution
    DEVMODE dm;
    memset(&dm,0,sizeof(dm));
    dm.dmSize=sizeof(dm);
    dm.dmPelsWidth     = nWidth;
    dm.dmPelsHeight    = nHeight;
    dm.dmBitsPerPel    = 32;
    dm.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

    long error = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);

    if (error != DISP_CHANGE_SUCCESSFUL)
    {
        // Oops, something went wrong, let the user know.
        if (MessageBox(NULL, "Could not set fullscreen mode.\n"
            "Your video card may not support the requested mode.\n"
            "Use windowed mode instead?", g_szAppName,
             MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
        {
            g_InFullScreen = false;
            dwExtStyle  = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
            dwWindStyle = WS_OVERLAPPEDWINDOW;
        }
       else
       {
            MessageBox(NULL, "Program will exit.",
                       "ERROR", MB_OK|MB_ICONSTOP);
            return false;
        }
    }
    else
    {
        // Mode set passed, setup the styles for fullscreen
        g_InFullScreen = true;
        dwExtStyle  = WS_EX_APPWINDOW;
        dwWindStyle = WS_POPUP;
        ShowCursor(FALSE);
    }
}

AdjustWindowRectEx(&g_windowRect, dwWindStyle, FALSE, dwExtStyle);

// Create the window again
     . . .

					  

2. Double Buffering

The sphere_world_redux sample program requests a double buffered pixel format by specifying WGL_DOUBLE_BUFFER_ARB the in the list of attributes when searching for a pixel format using wglChoosePixelFormatARB. By this time you have seen many sample programs that are double buffered. But let’s revisit briefly given that this is relevant to how we allocate the pixel format and how the program is controlled. When a double buffered pixel format is used, two surfaces the size of the window are allocated. One acts as the front buffer and the other as the back buffer.

Why would you want to do that? Double buffering allows OpenGL to draw your entire scene to the back buffer without any intermediate results showing up on the screen. This can provide a smoother and more visually pleasing experience for your users.

But how do users see anything if you are always rendering to a buffer that is not visible? Easy, just tell OpenGL when you are done drawing and the buffers need to be swapped. This is done simply by calling SwapBuffers with the device handle of the window. Once this call is made, the back buffer will be displayed, and our program will have a new back buffer to work with.

// Do the buffer swap
SwapBuffers(g_hDC);

Eliminating Visual Tearing

If your application is able to draw quickly and call SwapBuffers at a faster rate than the refresh rate of the monitor, an ugly effect called tearing can occur. If your application calls SawBuffers before the previous frame is finished being scanned out, someone using your application will see part of one frame and part of the next.

The widely supported extension WGL_EXT_swap_control comes to the rescue! You can tell OpenGL how many video frames, or V-Syncs, are allowed to happen at minimum between swap calls. Just use the following function to set the interval:

Bool wglSwapIntervalEXT(GLint interval);

If you pass in 0 for interval, the calls to SwapBuffers are unrestricted just as they are without this extension. But if you pass 1 for interval, only one SwapBuffers call is allowed to return for every vertical refresh of the monitor (every video frame). This is exactly what you want to eliminate tearing! All of the additional CPU time can be used for other things while your app waits for the swap to complete.

You can also pass larger intervals to wglSwapIntervalEXT to wait more frames between swaps, but this can cause considerable stutter in your applications. Also many drivers may not support larger intervals than one and will quietly clamp the interval back to 1.

Other  
 
Video tutorials
- How To Install Windows 8 On VMware Workstation 9

- How To Install Windows 8

- How To Install Windows Server 2012

- How To Disable Windows 8 Metro UI

- How To Change Account Picture In Windows 8

- How To Unlock Administrator Account in Windows 8

- How To Restart, Log Off And Shutdown Windows 8

- How To Login To Skype Using A Microsoft Account

- How To Enable Aero Glass Effect In Windows 8

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen
programming4us programming4us
Top 10
Free Mobile And Desktop Apps For Accessing Restricted Websites
MASERATI QUATTROPORTE; DIESEL : Lure of Italian limos
TOYOTA CAMRY 2; 2.5 : Camry now more comely
KIA SORENTO 2.2CRDi : Fuel-sipping slugger
How To Setup, Password Protect & Encrypt Wireless Internet Connection
Emulate And Run iPad Apps On Windows, Mac OS X & Linux With iPadian
Backup & Restore Game Progress From Any Game With SaveGameProgress
Generate A Facebook Timeline Cover Using A Free App
New App for Women ‘Remix’ Offers Fashion Advice & Style Tips
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th