📄 lesson22.cpp
字号:
/* This Code Was Created by Jens Schneider (WizardSoft) 2000
* Lesson22 to the series of OpenGL tutorials by NeHe-Production
*
* This Code is loosely based upon Lesson06 by Jeff Molofee.
*
* contact me at: schneide@pool.informatik.rwth-aachen.de
*
* Basecode Was Created By Jeff Molofee 2000
* If You've Found This Code Useful, Please Let Me Know.
* Visit My Site At nehe.gamedev.net
*/
// [HTML]: Point Out That Bump Maps Have To Be "Sharper" To Do Nice Effects!
#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
#define MAX_EMBOSS (GLfloat)0.008f // Maximum Emboss-Translate. Increase To Get Higher Immersion
// At A Cost Of Lower Quality (More Artifacts Will Occur!)
/* Here Comes The ARB-Multitexture Support.
* There Are (Optimally) 6 New Commands To The OpenGL Set:
* glMultiTexCoordifARB i=1..4 : Sets Texture-Coordinates For Texel-Pipeline #i
* glActiveTextureARB : Sets Active Texel-Pipeline
* glClientActiveTextureARB : Sets Active Texel-Pipeline For The Pointer-Array-Commands
*
* There Are Even More For The Various Formats Of glMultiTexCoordi{f,fv,d,i}, But We Don't Need Them.
*/
#define __ARB_ENABLE true // Used To Disable ARB Extensions Entirely
// #define EXT_INFO // Do You Want To See Your Extensions At Start-Up?
#define MAX_EXTENSION_SPACE 10240 // Characters for Extension-Strings
#define MAX_EXTENSION_LENGTH 256 // Maximum Of 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.
PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB = NULL;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL;
PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB = NULL;
PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB = NULL;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB= NULL;
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
bool keys[256]; // Array Used For The Keyboard Routine
bool active=true; // Window Active Flag Set To TRUE By Default
bool fullscreen=true; // Fullscreen Flag Set To Fullscreen Mode By Default
bool emboss=false; // Emboss Only, No Basetexture?
bool bumps=true; // Do Bumpmapping?
GLfloat xrot; // X Rotation
GLfloat yrot; // Y Rotation
GLfloat xspeed; // X Rotation Speed
GLfloat yspeed; // Y Rotation Speed
GLfloat z=-5.0f; // Depth Into The Screen
GLuint filter=1; // Which Filter To Use
GLuint texture[3]; // Storage For 3 Textures
GLuint bump[3]; // Our Bumpmappings
GLuint invbump[3]; // Inverted Bumpmaps
GLuint glLogo; // Handle For OpenGL-Logo
GLuint multiLogo; // Handle For Multitexture-Enabled-Logo
GLfloat LightAmbient[] = { 0.2f, 0.2f, 0.2f}; // Ambient Light is 20% white
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f}; // Diffuse Light is white
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f}; // Position is somewhat in front of screen
GLfloat Gray[]= {0.5f,0.5f,0.5f,1.0f};
// Data Contains The Faces For The Cube In Format 2xTexCoord, 3xVertex;
// Note That The Tesselation Of The Cube Is Only Absolute Minimum.
GLfloat data[]= {
// FRONT FACE
0.0f, 0.0f, -1.0f, -1.0f, +1.0f,
1.0f, 0.0f, +1.0f, -1.0f, +1.0f,
1.0f, 1.0f, +1.0f, +1.0f, +1.0f,
0.0f, 1.0f, -1.0f, +1.0f, +1.0f,
// BACK FACE
1.0f, 0.0f, -1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f, +1.0f, -1.0f,
0.0f, 1.0f, +1.0f, +1.0f, -1.0f,
0.0f, 0.0f, +1.0f, -1.0f, -1.0f,
// Top Face
0.0f, 1.0f, -1.0f, +1.0f, -1.0f,
0.0f, 0.0f, -1.0f, +1.0f, +1.0f,
1.0f, 0.0f, +1.0f, +1.0f, +1.0f,
1.0f, 1.0f, +1.0f, +1.0f, -1.0f,
// Bottom Face
1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
0.0f, 1.0f, +1.0f, -1.0f, -1.0f,
0.0f, 0.0f, +1.0f, -1.0f, +1.0f,
1.0f, 0.0f, -1.0f, -1.0f, +1.0f,
// Right Face
1.0f, 0.0f, +1.0f, -1.0f, -1.0f,
1.0f, 1.0f, +1.0f, +1.0f, -1.0f,
0.0f, 1.0f, +1.0f, +1.0f, +1.0f,
0.0f, 0.0f, +1.0f, -1.0f, +1.0f,
// Left Face
0.0f, 0.0f, -1.0f, -1.0f, -1.0f,
1.0f, 0.0f, -1.0f, -1.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
0.0f, 1.0f, -1.0f, 1.0f, -1.0f
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
// Always Check For Extension-Availability During Run-Time!
// Here We Go!
bool isInString(char *string, const char *search) {
int pos=0;
int maxpos=strlen(search)-1;
int len=strlen(string);
char *other;
for (int i=0; i<len; i++) {
if ((i==0) || ((i>1) && string[i-1]=='\n')) { // New Extension Begins Here!
other=&string[i];
pos=0; // Begin New Search
while (string[i]!='\n') { // Search Whole Extension-String
if (string[i]==search[pos]) pos++; // Next Position
if ((pos>maxpos) && string[i+1]=='\n') return true; // We Have A Winner!
i++;
}
}
}
return false; // Sorry, Not Found!
}
// isMultitextureSupported() Checks At Run-Time If Multitexturing Is Supported
bool initMultitexture(void) {
char *extensions;
extensions=strdup((char *) glGetString(GL_EXTENSIONS)); // Fetch Extension String
int len=strlen(extensions);
for (int i=0; i<len; i++) // Separate It By Newline Instead Of Blank
if (extensions[i]==' ') extensions[i]='\n';
#ifdef EXT_INFO
MessageBox(hWnd,extensions,"supported GL extensions",MB_OK | MB_ICONINFORMATION);
#endif
if (isInString(extensions,"GL_ARB_multitexture") // Is Multitexturing Supported?
&& __ARB_ENABLE // Override-Flag
&& isInString(extensions,"GL_EXT_texture_env_combine")) // Is texture_env_combining Supported?
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&maxTexelUnits);
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) wglGetProcAddress("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) wglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) wglGetProcAddress("glMultiTexCoord4fARB");
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
#ifdef EXT_INFO
MessageBox(hWnd,"The GL_ARB_multitexture extension will be used.","feature supported!",MB_OK | MB_ICONINFORMATION);
#endif
return true;
}
useMultitexture=false; // We Can't Use It If It Isn't Supported!
return false;
}
void initLights(void) {
glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient); // Load Light-Parameters Into GL_LIGHT1
glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv( GL_LIGHT1, GL_POSITION, LightPosition);
glEnable(GL_LIGHT1);
}
// Using auxDIBImageLoad's Own Error-Handler!
int LoadGLTextures(){ // Load Bitmaps And Convert To Textures
bool status=true; // Status Indicator
AUX_RGBImageRec *Image=NULL; // Create Storage Space For The Texture
char *alpha=NULL;
// Load The Tile-Bitmap For Base-Texture
if (Image=auxDIBImageLoad("Data/Base.bmp")) {
glGenTextures(3, texture); // Create Three Textures
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// ========
// Use GL_RGB8 Instead Of "3" In glTexImage2D. Also Defined By GL: GL_RGBA8 Etc.
// NEW: Now Creating GL_RGBA8 Textures, Alpha Is 1.0f Where Not Specified By Format.
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, Image->sizeX, Image->sizeY, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
}
else status=false;
if (Image) { // If Texture Exists
if (Image->data) delete Image->data; // If Texture Image Exists
delete Image;
Image=NULL;
}
// Load The Bumpmaps
if (Image=auxDIBImageLoad("Data/Bump.bmp")) {
glPixelTransferf(GL_RED_SCALE,0.5f); // Scale RGB By 50%, So That We Have Only
glPixelTransferf(GL_GREEN_SCALE,0.5f); // Half Intenstity
glPixelTransferf(GL_BLUE_SCALE,0.5f);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); // No Wrapping, Please!
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,Gray);
glGenTextures(3, bump); // Create Three Textures
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, bump[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, bump[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, bump[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, Image->sizeX, Image->sizeY, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
for (int i=0; i<3*Image->sizeX*Image->sizeY; i++) // Invert The Bumpmap
Image->data[i]=255-Image->data[i];
glGenTextures(3, invbump); // Create Three Textures
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, invbump[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, invbump[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, invbump[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, Image->sizeX, Image->sizeY, GL_RGB, GL_UNSIGNED_BYTE, Image->data);
glPixelTransferf(GL_RED_SCALE,1.0f); // Scale RGB Back To 100% Again
glPixelTransferf(GL_GREEN_SCALE,1.0f);
glPixelTransferf(GL_BLUE_SCALE,1.0f);
}
else status=false;
if (Image) { // If Texture Exists
if (Image->data) delete Image->data; // If Texture Image Exists
delete Image;
}
// Load The Logo-Bitmaps
if (Image=auxDIBImageLoad("Data/OpenGL_ALPHA.bmp")) {
alpha=new char[4*Image->sizeX*Image->sizeY]; // Create Memory For RGBA8-Texture
for (int a=0; a<Image->sizeX*Image->sizeY; a++)
alpha[4*a+3]=Image->data[a*3]; // Pick Only Red Value As Alpha!
if (!(Image=auxDIBImageLoad("Data/OpenGL.bmp"))) status=false;
for (a=0; a<Image->sizeX*Image->sizeY; a++) {
alpha[4*a]=Image->data[a*3]; // R
alpha[4*a+1]=Image->data[a*3+1]; // G
alpha[4*a+2]=Image->data[a*3+2]; // B
}
glGenTextures(1, &glLogo); // Create One Textures
// Create Linear Filtered RGBA8-Texture
glBindTexture(GL_TEXTURE_2D, glLogo);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Image->sizeX, Image->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, alpha);
delete alpha;
}
else status=false;
if (Image) { // If Texture Exists
if (Image->data) delete Image->data; // If Texture Image Exists
delete Image;
Image=NULL;
}
// Load The "Extension Enabled"-Logo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -