* DOWNLOAD Linux Code For This Lesson. (Conversion by Marius Andra)
* DOWNLOAD Linux/GLX Code For This Lesson. (Conversion by Mihael Vrbanec)
* DOWNLOAD Linux/SDL Code For This Lesson. (Conversion by Ti Leggett)
* DOWNLOAD Mac OS Code For This Lesson. (Conversion by Anthony Parker)
* DOWNLOAD Mac OS X/Cocoa Code For This Lesson. (Conversion by Bryan Blackburn)
* DOWNLOAD Visual C++ / OpenIL Code For This Lesson. (Conversion by Denton Woods)
Lesson 22
This lesson was written by Jens Schneider. It is loosely based on Lesson 06, though lots of changes were made. In this lesson you will learn:
• How to control your graphic-accelerator's multitexture-features.
• How to do a "fake" Emboss Bump Mapping.
• How to do professional looking logos that "float" above your rendered scene using blending.
• Basics about multi-pass rendering techniques.
How to do matrix-transformations efficiently. Since at least three of the above four points can be considered "advanced rendering techniques", you should already have a general understanding of OpenGL's rendering pipeline. You should know most commands already used in these tutorials, and you should be familiar with vector-maths. Every now and then you'll encounter a block that reads begin theory(…) as header and end theory(…) as an ending. These sections try to teach you theory about the issue(s) mentioned in parenthesis. This is to ensure that, if you already know about the issue, you can easily skip them. If you encounter problems while trying to understand the code, consider going back to the theory sections.
Last but not least: This lesson consists out of more than 1,200 lines of code, of which large parts are not only boring but also known among those that read earlier tutorials. Thus I will not comment each line, only the crux. If you encounter something like this >:<, it means that lines of code have been omitted.
Here we go:
#include <windows.h> // Header File For Windows
#include <stdio.h> // Header File For Standard Input/Output
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The GLaux Library
#include "glext.h" // Header File For Multitexturing
#include <string.h> // Header File For The String Library
#include <math.h> // Header File For The Math Library
The GLfloat MAX_EMBOSS specifies the "strength" of the Bump Mapping-Effect. Larger values strongly enhance the effect, but reduce visual quality to the same extent by leaving so-called "artefacts" at the edges of the surfaces.
#define MAX_EMBOSS (GLfloat)0.01f // Maximum Emboss-Translate. Increase To Get Higher Immersion
Ok, now let's prepare the use of the GL_ARB_multitexture extension. It's quite simple:
Most accelerators have more than just one texture-unit nowadays. To benefit of this feature, you'll have to check for GL_ARB_multitexture-support, which enables you to map two or more different textures to one OpenGL-primitive in just one pass. Sounds not too powerful, but it is! Nearly all the time if you're programming something, putting another texture on that object results in higher visual quality. Since you usually need multiple "passes" consisting out of interleaved texture-selection and drawing geometry, this can quickly become expensive. But don't worry, this will become clearer later on.
Now back to code: __ARB_ENABLE is used to override multitexturing for a special compile-run entirely. If you want to see your OpenGL-extensions, just un-comment the #define EXT_INFO. Next, we want to check for our extensions during run-time to ensure our code stays portable. So we need space for some strings. These are the following two lines. Now we want to distinguish between being able to do multitexture and using it, so we need another two flags. Last, we need to know how many texture-units are present(we're going to use only two of them, though). At least one texture-unit is present on any OpenGL-capable accelerator, so we initialize maxTexelUnits with 1.
#define __ARB_ENABLE true // Used To Disable ARB Extensions Entirely
// #define EXT_INFO // Uncomment To See Your Extensions At Start-Up?
#define MAX_EXTENSION_SPACE 10240 // Characters For Extension-Strings
#define MAX_EXTENSION_LENGTH 256 // Maximum Characters In One Extension-String
bool multitextureSupported=false; // Flag Indicating Whether Multitexturing Is Supported
bool useMultitexture=true; // Use It If It Is Supported?
GLint maxTexelUnits=1; // Number Of Texel-Pipelines. This Is At Least 1.
The following lines are needed to "link" the extensions to C++ function calls. Just treat the PFN-who-ever-reads-this as pre-defined datatype able to describe function calls. Since we are unsure if we'll get the functions to these prototypes, we set them to NULL. The commands glMultiTexCoordifARB map to the well-known glTexCoordif, specifying i-dimensional texture-coordinates. Note that these can totally substitute the glTexCoordif-commands. Since we only use the GLfloat-version, we only need prototypes for the commands ending with an "f". Other are also available ("fv", "i", etc.). The last two prototypes are to set the active texture-unit that is currently receiving texture-bindings (glActiveTextureARB()) and to determine which texture-unit is associated with the ArrayPointer-command (a.k.a. Client-Subset, thus glClientActiveTextureARB). By the way: ARB is an abbreviation for "Architectural Review Board". Extensions with ARB in their name are not required by an OpenGL-conformant implementation, but they are expected to be widely supported. Currently, only the multitexture-extension has made it to ARB-status. This may be treated as sign for the tremendous impact regarding speed multitexturing has on several advanced rendering techniques.
The lines ommitted are GDI-context handles etc.
PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB = NULL;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL;
PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB = NULL;
PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB = NULL;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB= NULL;
We need global variables:
• filter specifies what filter to use. Refer to Lesson 06. We'll usually just take GL_LINEAR, so we initialise with 1.
• texture holds our base-texture, three times, one per filter.
• bump holds our bump maps
• invbump holds our inverted bump maps. This is explained later on in a theory-section.
• The Logo-things hold textures for several billboards that will be added to rendering output as a final pass.
• The Light…-stuff contains data on our OpenGL light-source.
GLuint filter=1; // Which Filter To Use