The DemoI've created a simple demo to show you some extensions in action. As you can see from Figure 1, the demo itself is fairly simple, nothing more than a light moving above a textured surface, casting a light on it using a lightmap. The demo isn't interactive at all. I kept it simple because I wanted to be able to focus on the extension mechanism. The demo uses seven different extensions. Some of them aren't strictly necessary, but I wanted to include enough to get the point across. Table 2 lists all of the extensions in use, and how they are used.
The full source code to the demo is included on the CD, but there are a couple of functions that I want to look at. The first is InitializeExtensions(). This function is called at startup, right after the rendering context is created. It verifies that the extensions used are supported, and gets the function entry points that are needed. bool InitializeExtensions() { if (CheckExtension("GL_ARB_multitexture")) { glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB"); glActiveTexture = (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB"); glClientActiveTexture = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB"); } else { MessageBox(g_hwnd, "This program requires multitexturing, which " "is not supported by your hardware", "ERROR", MB_OK); return false; } if (CheckExtension("GL_EXT_point_parameters")) { glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC) wglGetProcAddress("glPointParameterfvEXT"); } if (CheckExtension("WGL_EXT_swap_control")) { wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); } if (!CheckExtension("GL_EXT_bgra")) { MessageBox(g_hwnd, "This program requires the BGRA pixel storage" "format which is not supported by your hardware", "ERROR", MB_OK); return false; } g_useTextureCompression = CheckExtension("GL_ARB_texture_compression"); g_useEdgeClamp = CheckExtension("GL_EXT_texture_edge_clamp"); g_useSGISMipmapGeneration = CheckExtension("GL_SGIS_generate_mipmap"); return true; } As you can see, there are two extensions that the demo requires: multitexturing and BGRA pixel formats. Although I could have provided alternate ways to do both of these things, doing so would have unnecessarily complicated the program. The point parameter and swap control extensions aren't required, so I don't exit if they aren't present. Instead, where they are used, I check to see if the function pointer is invalid (i.e., set to NULL). If so, I simply don't use the extension. I use a similar approach with the texture compression, texture edge clamp, and generate mipmap extensions. Since all three of these extensions only introduce new enumrants, I set global flags to indicate whether or not they are supported. When they are used, I check the flag, and if they aren't supported, I use an alternate method. For texture compression, I just use the normal pixel format, for texture edge clamp, I use normal clamping instead, and if the generate mipmaps extension isn't supported, I use gluBuild2DMipmaps() instead. The other function I want to look at is the CheckExtension() function, which is used repeatedly by InitializeExtensions(). bool CheckExtension(char* extensionName) { // get the list of supported extensions char* extensionList = (char*) glGetString(GL_EXTENSIONS); if (!extensionName || !extensionList) return false; while (*extensionList) { // find the length of the first extension substring unsigned int firstExtensionLength = strcspn(extensionList, " "); if (strlen(extensionName) == firstExtensionLength && strncmp(extensionName, extensionList, firstExtensionLength) == 0) { return true; } // move to the next substring extensionList += firstExtensionLength + 1; } return false; } This function gets the extensions string, and then parses each full extension name string from it, comparing each to the requested extension. Notice that I'm finding each string by looking for the next space to be sure that I don't accidentally match a substring. Also, this function doesn't check for WGL extensions at all, although it could easily be modified to do so. The code in the demo is not intended to be optimal, nor is it intended to be the "best" way to use extensions. Some people like to make extension function pointers global, as I have done, so that they can be used just like core OpenGL functions anywhere in your program. Others like to put class wrappers around them. Use whatever means you prefer. The demo was intentionally kept as straightforward as possible so that you could easily understand it and take out the parts that interest you. What You've LearnedYou've now seen you how you can use OpenGL's extensions to use the latest features offered by modern video cards. You've learned what some of these features are, and how your game can benefit from them. You've also seen ways in which you can get the most out of extensions without unnecessarily limiting your target audience. Where To Go NowI've given you an overview of the features available in OpenGL 1.2, 1.3, and through extensions. I've only been able to cover a few of them in detail. Fortunately, the web is full of resources to help get you started with using these features. The developer sections of the NVIDIA and ATI websites in particular are full of whitepapers, presentations, and demos. In addition, I've found the following websites to be quite useful. http://www.nutty.org
And of course, the front page of OpenGL.org is a great resource for finding links to pages containing OpenGL tutorials and demos. ConclusionNow that you have a basic understanding of extensions, I encourage you to spend some time researching them and experimenting on your own. You may find that some of them enable you to significantly improve the efficiency and visual quality of your games. AcknowledgementsI'd like to thank Alexander Heiner and Mark Shaxted for reviewing this article and correcting some minor inaccuracies, as well as suggesting ways to make it more complete. I'd also like to thank my wife Melissa for making me look like a better writer than I really am. References[1] Mark Kilgard, "All About Extensions", http://www.opengl.org/developers/code/features/OGLextensions/OGLextensions.html
Dave Astle is the Executive Producer and one of the cofounders of GameDev.net. He is the coauthor of OpenGL Game Programming, has contributed to several other books, and has spoken at game industry conferences such as the Game Developers Conference. He has several years of game industry experience, and is currently a senior engineer on the Graphics and Gaming team at QUALCOMM, Inc. in San Diego, CA. |
|