在OpenGL中实现镜面反射

Welcome to another exciting tutorial. The code for this tutorial was written by Banu Octavian. The tutorial was of course written by myself (NeHe). In this tutorial you will learn how to create EXTREMELY realistic reflections. Nothing fake here! The objects being reflected will not show up underneath the floor or on the other side of a wall. True reflections!
A very important thing to note about this tutorial: Because the Voodoo 1, 2 and some other cards do not support the stencil buffer, this demo will NOT run on those cards. It will ONLY run on cards that support the stencil buffer. If you're not sure if your card supports the stencil buffer, download the code, and try running the demo. Also, this demo requires a fairly decent processor and graphics card. Even on my GeForce I notice there is a little slow down at times. This demo runs best in 32 bit color mode!
As video cards get better, and processors get faster, I can see the stencil buffer becoming more popular. If you have the hardware and you're ready to reflect, read on!
The first part of the code is fairly standard. We include all necessary header files, and set up our Device Context, Rendering Context, etc.
#include < windows.h > // Header File For Windows
#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 < stdio.h > // Header File For Standard Input / Output
HDC hDC = NULL; // Private GDI Device Context
HGLRC hRC = NULL; // Permanent Rendering Context
HWND hWnd = NULL; // Holds Our Window Handle
HINSTANCE hInstance = NULL; // Holds The Instance Of The Application
Next we have the standard variables to keep track of key presses (keys[ ]), whether or not the program is active (active), and if we should use fullscreen mode or windowed mode (fullscreen).
Next we set up our lighting variables. LightAmb[ ] will set our ambient light. We will use 70% red, 70% green and 70% blue, creating a light that is 70% bright white. LightDif[ ] will set the diffuse lighting (the amount of light evenly reflected off the surface of our object). In this case we want to reflect full intensity light. Lastly we have LightPos[ ] which will be used to position our light. In this case we want the light 4 units to the right, 4 units up, and 6 units towards the viewer. If we could actually see the light, it would be floating in front of the top right corner of our screen.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
// Light Parameters
static GLfloat LightAmb[] = { 0.7f , 0.7f , 0.7f , 1.0f }; // Ambient Light
static GLfloat LightDif[] = { 1.0f , 1.0f , 1.0f , 1.0f }; // Diffuse Light
static GLfloat LightPos[] = { 4.0f , 4.0f , 6.0f , 1.0f }; // Light Position
We set up a variable called q for our quadratic object, xrot and yrot to keep track of rotation. xrotspeed and yrotspeed control the speed our object rotates at. zoom is used to zoom in and out of the scene (we start at -7 which shows us the entire scene) and height is the height of the ball above the floor.
We then make room for our 3 textures with texture[3], and define WndProc().
The ReSizeGLScene() and LoadBMP() code has not changed so I will skip over both sections of code.GLUquadricObj * q; // Quadratic For Drawing A Sphere
GLfloat xrot = 0.0f ; // X Rotation
GLfloat yrot = 0.0f ; // Y Rotation
GLfloat xrotspeed = 0.0f ; // X Rotation Speed
GLfloat yrotspeed = 0.0f ; // Y Rotation Speed
GLfloat zoom = - 7.0f ; // Depth Into The Screen
GLfloat height = 2.0f ; // Height Of Ball From Floor
GLuint texture[ 3 ]; // 3 Textures
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
The load texture code is pretty standard. You've used it many times before in the previous tutorials. We make room for 3 textures, then we load the three images, and create linear filtered textures from the image data. The bitmap files we use are located in the DATA directory.GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
AUX_RGBImageRec * LoadBMP( char * Filename) // Loads A Bitmap Image
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status = FALSE; // Status Indicator
AUX_RGBImageRec * TextureImage[ 3 ]; // Create Storage Space For The Textures
memset(TextureImage, 0 , sizeof ( void * ) * 3 ); // Set The Pointer To NULL
if ((TextureImage[ 0 ] = LoadBMP( " Data/EnvWall.bmp " )) && // Load The Floor Texture
(TextureImage[ 1 ] = LoadBMP( " Data/Ball.bmp " )) && // Load the Light Texture
(TextureImage[ 2 ] = LoadBMP( " Data/EnvRoll.bmp " ))) // Load the Wall Texture
{
Status = TRUE; // Set The Status To TRUE
glGenTextures( 3 , & texture[ 0 ]); // Create The Texture
for ( int loop = 0 ; loop < 3 ; loop ++ ) // Loop Through 5 Textures
{
glBindTexture(GL_TEXTURE_2D, texture[loop]);
glTexImage2D(GL_TEXTURE_2D, 0 , 3 , TextureImage[loop] -> sizeX, TextureImage[loop] -> sizeY, 0 , GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop] -> data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
for (loop = 0 ; loop < 3 ; loop ++ ) // Loop Through 5 Textures
{
if (TextureImage[loop]) // If Texture Exists
{
if (TextureImage[loop] -> data) // If Texture Image Exists
{
free(TextureImage[loop] -> data); // Free The Texture Image Memory
}
free(TextureImage[loop]); // Free The Image Structure
}
}
}
return Status; // Return The Status
}

工程师必备
- 项目客服
- 培训客服
- 平台客服
TOP
