5 Microsoft Windows Specifics

5.010 What's a good source for Win32 OpenGL programming information?

Samuel Paik has created a large repository of links to OpenGL information on Microsoft Web sites.

See Blaine Hodge's web page. Be aware that some examples on this page use the AUX library, which is not recommended.

5.020 I'm looking for a Wintel OpenGL card in a specific price range, any suggestions?

The consumer-level 3D graphics marketplace moves fast. Any information placed in this FAQ would be soon outdated.

You might post a query on this topic to the comp.graphics.api.opengl newsgroup, or one of the many newsgroups devoted to Wintel-based 3D games. You might also do a Web search.

Tom's Hardware Guide and Fast Graphics have a lot of information on current graphics cards.

5.030 How do I enable and disable hardware rendering on a Wintel card?

Currently, OpenGL doesn't contain a switch to enable or disable hardware acceleration. Some vendors might provide this capability with an environment variable or software switch.

If you install your graphics card, but don't see hardware accelerated rendering check for the following:

You might also have acceleration problems if you're trying to set up a multimonitor configuration. Hardware accelerated rendering might not be supported on all (or any) devices in this configuration.

To force software rendering from your application, choose a pixel format that is not hardware accelerated. To do this, you can not use ChoosePixelFormat(), which always selects a hardware accelerated pixel format when one is available. Instead, use DescribePixelFormat() to iterate through the list of available pixel formats. Any format with the PFD_GENERIC_FORMAT attribute bit set will not be hardware accelerated.

An example of iterating over available pixel formats can be found here.

A less tasteful method to disable hardware acceleration is to move or rename your OpenGL ICD.

Also, check your device's documentation to see if your device driver supports disabling hardware acceleration by a dialog box.

5.040 How do I know my program is using hardware acceleration on a Wintel card?

OpenGL doesn't provide a direct query to determine hardware acceleration usage. However, this can usually be inferred by using indirect methods.

If you are using the Win32 interface (as opposed to GLUT), call DescribePixelFormat() and check the returned dwFlags bitfield. If PFD_GENERIC_ACCELERATED is clear and PFD_GENERIC_FORMAT is set, then the pixel format is only supported by the generic implementation. Hardware acceleration is not possible for this format. For hardware acceleration, you need to choose a different format.

If glGetString(GL_VENDOR) returns something other than "Microsoft Corporation", it means you're using the board's ICD. If it returns "Microsoft Corporation", this implies you chose a pixel format that your device can't accelerate. However, glGetString(GL_VENDOR) also returns this if your device has an MCD instead of an ICD, which means you might still be hardware accelerated in this case.

Another way to check for hardware acceleration is to temporarily remove or rename the ICD, so it can't be loaded. If performance drops, it means you were hardware accelerated before. Don't forget to restore the ICD to its original location or name. (To find your ICD file name, run the regedit utility and search for a key named "OpenGLdrivers".)

You can also gather performance data by rendering into the back buffer and comparing the results against known performance statistics for your device. This method is particularly useful for devices that revert to software rendering for some state combinations or OpenGL features. See the section on performance for more information.

5.050 Where can I get the OpenGL ICD for a Wintel card?

If your device supports OpenGL, the manufacturer should provide an ICD (commonly referred to as the device driver) for it. After you install the ICD, your OpenGL application can use the device's hardware capabilities.

If your device didn't come with an ICD on disk, you'll need to check the manufacturer's Web page to see where you can download the latest drivers. The chip manufacturer will probably have a more current ICD than the board manufacturer. Find the device driver download page, get the latest package for your device, and install it per the instructions provided.

Check Reactor Critical for nVidia device drivers. They often have more current and better performing OpenGL device drivers than nVidia makes available from their web page.

GLsetup, a free utility, is available. According to the GLsetup Web page, it "detects a user's 3D graphics hardware and installs the correct device drivers." Windows 2000 device drivers might not be supported. You can get it from http://www.glsetup.com.

5.060 I'm using a Wintel card, and an OpenGL feature doesn't seem to work. What's going on?

It could simply be a bug in your code. However, if the same code works fine on another OpenGL implementation, this implies the problem is in your graphics device or its ICD. See the previous question for information on obtaining the latest ICD for your device.

5.070 Can I use OpenGL with DirectDraw?

Moxing OpenGL rendering calls with rendering calls from other APIs (such as DirectDraw) in the same window won't work on some drivers, and is therefore unportable. I don't recommended it.

5.080 Can I use use DirectDraw to change the screen resolution or desktop pixel depth?

You can create a window and use DirectDraw to change the display resolution and/or pixel depth. Then, get the window's DC and create an OpenGL context from it. This is known to work on some devices.

While we're on the subject, Microsoft doesn't require, and consequently does not test for, the ability to render OpenGL into a DirectDraw surface. Just because you can get a surface's DC does not mean that OpenGL rendering is supported. Always check for error returns when creating contexts or maiing them current.

5.090 My card supports OpenGL, but I don't get acceleration regardless of which pixel format I use.

Are you in 8bpp?  There are few 3D accelerators for PCs that support acceleration in 8bpp.

5.100 How do I get hardware acceleration?

The pixel format selects hardware acceleration.  Pay attention to the flags GENERIC_FORMAT and GENERIC_ACCELERATED. You want both of them on if you're using a 3D-DDI or an MCD and neither on if you are using an ICD.  You may have to iterate using DescribePixelFormat() instead of only using ChoosePixelFormat().

5.110 Why doesn't OpenGL hardware acceleration work with multiple monitors?

In Windows 98, Microsoft decided to disable OpenGL hardware acceleration when multiple monitors are enabled.  In Windows NT 4.0, some drivers support multiple monitors when using identical (or nearly identical) cards. I don't believe multiple monitors and hardware accelerated OpenGL work with different types of cards.  I don't know the story with Windows 2000, but it's likely to be similar to Windows NT 4.0.

5.120 Why does my MFC window flash, even though I'm using double buffering?

Your view class should have an OnEraseBkgnd() event handler. You can eliminate flashing by overriding this function and returning TRUE. This tells Windows that you've cleared the window. Of course, you didn't really clear the window. However, overriding the function keeps Microsoft from trying to do it for you, and should prevent flashing.

5.121 Why does my double buffered window appear incomplete or contain black stripes?

This is a problem with MS OpenGL. The bug is in the generic code, or possibly in MS Windows itself, because it occurs even with pure software rendering. To work around the bug, try one of these two methids:

5.130 What's the difference between opengl.dll and opengl32.dll?

According to OpenGL Reference Manual editor Dave Shreiner:

"Unless there's an absolutely compelling reason ... I really would suggest using opengl32.dll, and letting the old opengl.dll thing die.

"opengl.dll comes from the now totally unsupported OpenGL for Windows release of OpenGL for Microsoft Windows by SGI.  We stopped supporting that release over two years -- like no one ever touches the code. ...

"Now, why use opengl32.dll?  For the most part, SGI provides Microsoft with the ICD kit, sample drivers, and software OpenGL implementation that you find there.  Its really the same code base (with fixes and new features) as the opengl.dll, its only that we got Microsoft to ship and support it (in a manner of speaking)."

More information on linking with opengl.dll can be found here.

5.140 Should I use Direct3D or OpenGL?

A good comparison of the two can be found here.

5.150 What do I need to know to use OpenGL with MFC?

You need to be familiar with both OpenGL and the Microsoft Foundation Class (MFC). An online MFC reference is available, the MFC FAQ. You don't need to be an MFC guru to add OpenGL to an MFC application. Familiarity with C++ can make mastering MFC easier, and the more you know about MFC, the more you can concentrate on your OpenGL code. If you have only a rudimentary knowledge of MFC, look at the downloadable source code example below, and look at the steps necessary to recreate it.

Samuel Paik's repository of links to OpenGL information on Microsoft Web sites also has information on using OpenGL and MFC.

Here's a list of books that might be helpful.

OpenGL Programming for Windows 95 and Windows NT, by Ron Fosner. This is also known as the white book. It contains good information on using OpenGL in Microsoft Windows. Much of the information in it can be found on the MSDN Web site, but the book presents the information in a more logical and easily digestable format, and comes with good demos.

Opengl Superbible: The Complete Guide to Opengl Programming for Windows NT and Windows 95, by Richard S. Wright and Michael Sweet. This book contains a chapter on OpenGL and MFC.

MFC Programming with Visual C++ 6 Unleashed, by David White, et al. The book contains a short chapter on OpenGL and focuses more on DirectX.

5.160 How can I use OpenGL with MFC?

To add OpenGL to an MFC application, you need to do at least the following:

You can render OpenGL into any CWnd object, including frame windows, dialog boxes, and controls.

Download this example, which demonstrates OpenGL in a CStatic form control. This code uses a CGlView class that takes any CWnd as a parameter to its constructor. Rather than create a View derived from a CFormView, you could just as easily create an SDI application, and pass "this" (an instantiation of a CView) as a parameter to the constructor. Follow these steps to recreate this sample code using Microsoft Visual C++ v6.0:

  1. If you haven't done so already, download the example. You'll need to borrow code from it in the steps that follow.
  2. Create an MFC application using the AppWizard. Use defaults, except derive your View class from a CFormView. The project will open in the resource editor. Add a FORM control to the open CFormView. Call it IDC_OPENGLWIN.
  3. Select Project->Settings...->Link, and add glu32.lib opengl32.lib to the list of objects/library modules.
  4. Select Project->Add To Peoject->Files... and add the CGlView.cpp OpenGL view class source file from the above example code.
  5. From the class view, right click your application's View class and select Add Member Variable... Set the variable type to CGlView *, the name to m_pclGLView, and the access to Private.
  6. In your application's View class header file, add #include "CGlView.h" just before the class definition.
  7. Find the global declaration of "theApp". Immediately after this declaration, add two new global variables:
    CGlView *g_pclGLView = NULL;
    MSG msg;
  8. In the wizard bar, set the application's View class, set the filter to All Class Members, and select the OnInitialUpdate member function.
  9. For the CGlView class to work, it needs a CWnd to initialize OpenGL for that window. For this example, our CWnd is the CStatic FORM control we added in step 1. After the existing code in this function, add the following:
    CStatic pclStatic = (CStatic *)GetDlgItem(IDC_OPENGLWIN);
    m_pclGLView = new CGlView(pclStatic);
  10. Open the class wizard with View->ClassWizard. From the message map tab, select your project's Application class. Add a function handler for the Run message. Replace the generated code with the Run message handler from the downloaded example.

5.170 Is OpenGL inherently slower when used with MFC?

Nothing in MFC guarantees a slow-running OpenGL application. However, some poorly written MFC applications might run slowly. This is a possibility in any development environment and is not specific to OpenGL. Here are some things to look out for:

  1. Build the application as Release instead of Debug. Disable the TRACE debugging feature.
  2. Avoid MFC classes such as CArray, CMap, and CList that perform inefficient data copies.
  3. You may be able to improve performance by avoiding the WM_PAINT message. See the question above for example source that does this.
  4. MFC classes are general purpose. For maximum performance, write a tuned implementation of an MFC class.
  5. Use standard efficient programming techniques such as avoiding redundant calls, etc.

5.180 Where can I find MFC examples?

This FAQ contains an example.

Alan Oursland, Using OpenGL in Visual C++ Version 4.x, DevCentral Learning Center, http://devcentral.iftech.com/learning/tutorials/mfc-win32/opengl/. This is good but dated.  It will get you started with a SDI MFC OpenGL application.

Mahesh Venkitachalam, OpenGL Code, http://home.att.net/~bighesh/ogl.html. Mahesh presents OpenGL in a no application wizard, minimal MFC program along with some OpenGL techniques.

Roman Podobedov, Skeleton of OpenGL program for Windows (MFC). http://madli.ut.ee/~romka/opengl/demos/win32_eng.htm. This is a minimal MFC program with no controls or application wizard.

Paul Martz, Generating Random Fractal Terrain. http://www.gameprogrammer.com/fractal.html. This is a good example of the MFC SDI approach. However, the primary focus of the example is terrain, to which OpenGL and MFC take a back seat.

[5] Pierre Alliez, Starting OpenGL in a Dialog. http://codeguru.earthweb.com/opengl/texture_mapping.shtml.

Pierre Alliez, Starting Rendering Modes. http://www.codeguru.com/opengl/start.shtml. This is a splitter window example.

Pierre Alliez, How to snap an OpenGL client and send it to the clipboard, http://codeguru.earthweb.com/opengl/snap.shtml.

Pierre Alliez, A small VRML viewer using OpenGL and MFC. http://www.codeproject.com/opengl/wrl_viewer.asp.

Uwe Kotyczka, Enu.zip, http://ws56.tinst.uni-jena.de/opengl_en.html. This rather large and impressive MFC contribution demonstrates, multiple OpenGL views, rubber banding, color ramp, mouse trackball type control, OpenGL printing, etc., in a MFC MDI and SDI framework.  This was built with VC++ 6.0 (SP4) .

5.190 What do I need to know about mixing WGL and GDI calls?
5.200 Why does my code crash under Windows NT or 2000 but run fine under 9x?
5.210 How do I properly use WGL functions?

Charles E. Hardwidge has tutorial articles and examples for download that address these issues. The idea is to use WGL, GDI, and OpenGL functions such that the Microsoft OpenGL ICD mechanism isn't assumed.