在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).

 
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

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.

  
// 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().

  
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 ReSizeGLScene() and LoadBMP() code has not changed so I will skip over both sections of code.

  
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window

AUX_RGBImageRec
* LoadBMP( char * Filename) // Loads A Bitmap Image

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.

  
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
}

程序开发有限元理论及编程

在OpenGL中实现镜面反射的评论4条

  • temp
    0
    <PRE><DIV>续<BR>A new command called glClearStencil is introduced in the init code. Passing 0 as a parameter tells OpenGL to disable clearing of the stencil buffer. You should be familiar with the rest of the code by now. We load our textures and enable smooth shading. The clear color is set to an off blue and the clear depth is set to 1.0f. The stencil clear value is set to 0. We enable depth testing, and set the depth test value to less than or equal to. Our perspective correction is set to nicest (very good quality) and 2d texture mapping is enabled. <BR><BR></DIV></PRE><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> InitGL(GLvoid) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> All Setup For OpenGL Goes Here</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">{<br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">LoadGLTextures()) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> If Loading The Textures Failed</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> FALSE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Return False</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/> glShadeModel(GL_SMOOTH); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Smooth Shading</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glClearColor(</SPAN><SPAN style="COLOR: #000000">0.2f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.5f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Background</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glClearDepth(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Depth Buffer Setup</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glClearStencil(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Clear The Stencil Buffer To 0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_DEPTH_TEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enables Depth Testing</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDepthFunc(GL_LEQUAL); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> The Type Of Depth Testing To Do</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Really Nice Perspective Calculations</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_TEXTURE_2D); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable 2D Texture Mapping</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P><FONT face="Courier New">Now it's time to set up light 0. The first line below tells OpenGL to use the values stored in LightAmb for the Ambient light. If you remember at the beginning of the code, the rgb values of LightAmb were all 0.7f, giving us a white light at 70% full intensity. We then set the Diffuse light using the values stored in LightDif and position the light using the x,y,z values stored in LightPos. </FONT></P><br/><P><FONT face="Courier New">After we have set the light up we can enable it with glEnable(GL_LIGHT0). Even though the light is enabled, you will not see it until we enable lighting with the last line of code. </FONT></P><br/><P><FONT face="Courier New">Note: If we wanted to turn off all lights in a scene we would use glDisable(GL_LIGHTING). If we wanted to disable just one of our lights we would use glDisable(GL_LIGHT{0-7}). This gives us alot of control over the lighting and what lights are on and off. Just remember if GL_LIGHTING is disabled, you will not see lights! <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Ambient Lighting For Light0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Diffuse Lighting For Light0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glLightfv(GL_LIGHT0, GL_POSITION, LightPos); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Position For Light0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> glEnable(GL_LIGHT0); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Light 0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_LIGHTING); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Lighting</SPAN></DIV></PRE><br/><P><BR>In the first line below, we create a new quadratic object. The second line tells OpenGL to generate smooth normals for our quadratic object, and the third line tells OpenGL to generate texture coordinates for our quadratic. Without the second and third lines of code, our object would use flat shading and we wouldn't be able to texture it. </P><br/><P>The fourth and fifth lines tell OpenGL to use the Sphere Mapping algorithm to generate the texture coordinates. This allows us to sphere map the quadratic object. <BR><BR><SPAN style="COLOR: #000000"> q </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> gluNewQuadric(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Create A New Quadratic</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000"> gluQuadricNormals(q, GL_SMOOTH); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Generate Smooth Normals For The Quad</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000"> gluQuadricTexture(q, GL_TRUE); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Texture Coords For The Quad</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000"><BR> glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Up Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000"> glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Up Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000"><BR> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> TRUE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Initialization Went OK</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">}<BR><BR></SPAN><BR>The code below will draw our object (which is a cool looking environment mapped beach ball). </P><br/><P>We set the color to full intensity white and bind to our BALL texture (the ball texture is a series of red, white and blue stripes). </P><br/><P>After selecting our texture, we draw a Quadratic Sphere with a radius of 0.35f, 32 slices and 16 stacks (up and down). <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> DrawObject() </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw Our Ball</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">{<br/> glColor3f(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Color To White</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glBindTexture(GL_TEXTURE_2D, texture[</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">]); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Select Texture 2 (1)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> gluSphere(q, </SPAN><SPAN style="COLOR: #000000">0.35f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">32</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">16</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw First Sphere</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>After drawing the first sphere, we select a new texture (EnvRoll), set the alpha value to 40% and enable blending based on the source alpha value. glEnable(GL_TEXTURE_GEN_S) and glEnable(GL_TEXTURE_GEN_T) enables sphere mapping. </P><br/><P>After doing all that, we redraw the sphere, disable sphere mapping and disable blending. </P><br/><P>The final result is a reflection that almost looks like bright points of light mapped to the beach ball. Because we enable sphere mapping, the texture is always facing the viewer, even as the ball spins. We blend so that the new texture doesn't cancel out the old texture (a form of multitexturing). <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glBindTexture(GL_TEXTURE_2D, texture[</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">]); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Select Texture 3 (2)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glColor4f(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.4f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Color To White With 40% Alpha</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_BLEND); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Blending</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glBlendFunc(GL_SRC_ALPHA, GL_ONE); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Blending Mode To Mix Based On SRC Alpha</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_TEXTURE_GEN_S); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_TEXTURE_GEN_T); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> gluSphere(q, </SPAN><SPAN style="COLOR: #000000">0.35f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">32</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">16</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw Another Sphere Using New Texture<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Textures Will Mix Creating A MultiTexture Effect (Reflection)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_TEXTURE_GEN_S); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_TEXTURE_GEN_T); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Sphere Mapping</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_BLEND); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Blending</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">}<br/><br/></SPAN></DIV></PRE><br/><P>The code below draws the floor that our ball hovers over. We select the floor texture (EnvWall), and draw a single texture mapped quad on the z-axis. Pretty simple!<BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> DrawFloor() </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draws The Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">{<br/> glBindTexture(GL_TEXTURE_2D, texture[</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">]); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Select Texture 1 (0)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glBegin(GL_QUADS); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Begin Drawing A Quad</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glNormal3f(</SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Normal Pointing Up</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glTexCoord2f(</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Bottom Left Of Texture</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glVertex3f(</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Bottom Left Corner Of Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> <br/> glTexCoord2f(</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Top Left Of Texture</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glVertex3f(</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Top Left Corner Of Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> <br/> glTexCoord2f(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Top Right Of Texture</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glVertex3f( </SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Top Right Corner Of Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> <br/> glTexCoord2f(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Bottom Right Of Texture</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glVertex3f( </SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">2.0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Bottom Right Corner Of Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnd(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Done Drawing The Quad</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">}<br/><br/></SPAN></DIV></PRE><br/><P>Now for the fun stuff. Here's where we combine all the objects and images to create our reflective scene. </P><br/><P>We start off by clearing the screen (GL_COLOR_BUFFER_BIT) to our default clear color (off blue). The depth (GL_DEPTH_BUFFER_BIT) and stencil (GL_STENCIL_BUFFER_BIT) buffers are also cleared. Make sure you include the stencil buffer code, it's new and easy to overlook! It's important to note when we clear the stencil buffer, we are filling it with 0's. </P><br/><P>After clearing the screen and buffers, we define our clipping plane equation. The plane equation is used for clipping the reflected image. </P><br/><P>The equation eqr[]={0.0f,-1.0f, 0.0f, 0.0f} will be used when we draw the reflected image. As you can see, the value for the y-plane is a negative value. Meaning we will only see pixels if they are drawn below the floor or at a negative value on the y-axis. Anything drawn above the floor will not show up when using this equation. </P><br/><P>More on clipping later... read on. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> DrawGLScene(GLvoid) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw Everything</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">{<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Clear Screen, Depth Buffer &amp; Stencil Buffer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glClear(GL_COLOR_BUFFER_BIT </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> GL_DEPTH_BUFFER_BIT </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> GL_STENCIL_BUFFER_BIT);<br/><br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Clip Plane Equations</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000"> eqr[] </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> {</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">}; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Plane Equation To Use For The Reflected Objects</SPAN></DIV></PRE><br/><P>So we have cleared the screen, and defined our clipping planes. Now for the fun stuff! </P><br/><P>We start off by resetting the modelview matrix. Which of course starts all drawing in the center of the screen. We then translate down 0.6f units (to add a small perspective tilt to the floor) and into the screen based on the value of zoom. To better explain why we translate down 0.6f units, I'll explain using a simple example. If you were looking at the side of a piece of paper at exactly eye level, you would barely be able to see it. It would more than likely look like a thin line. If you moved the paper down a little, it would no longer look like a line. You would see more of the paper, because your eyes would be looking down at the page instead of directly at the edge of the paper. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glLoadIdentity(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Reset The Modelview Matrix</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glTranslatef(</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">0.6f</SPAN><SPAN style="COLOR: #000000">, zoom); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Zoom And Raise Camera Above The Floor (Up 0.6 Units)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>Next we set the color mask. Something new to this tutorial! The 4 values for color mask represent red, green, blue and alpha. By default all the values are set to GL_TRUE. </P><br/><P>If the red value of glColorMask({red},{green},{blue},{alpha}) was set to GL_TRUE, and all of the other values were 0 (GL_FALSE), the only color that would show up on the screen is red. If the value for red was 0 (GL_FALSE), but the other values were all GL_TRUE, every color except red would be drawn to the screen. </P><br/><P>We don't want anything drawn to the screen at the moment, with all of the values set to 0 (GL_FALSE), colors will not be drawn to the screen. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000">glColorMask(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Color Mask<br/></SPAN></DIV></PRE><br/><P><BR>Now even more fun stuff... Setting up the stencil buffer and stencil testing! </P><br/><P>We start off by enabling stencil testing. Once stencil testing has been enabled, we are able to modify the stencil buffer. </P><br/><P>It's very hard to explain the commands below so please bear with me, and if you have a better explanation, please let me know. In the code below we set up a test. The line glStencilFunc(GL_ALWAYS, 1, 1) tells OpenGL what type of test we want to do on each pixel when an object is drawn to the screen. </P><br/><P>GL_ALWAYS just tells OpenGL the test will always pass. The second parameter (1) is a reference value that we will test in the third line of code, and the third parameter is a mask. The mask is a value that is ANDed with the reference value and stored in the stencil buffer when the test is done. A reference value of 1 ANDed with a mask value of 1 is 1. So if the test goes well and we tell OpenGL to, it will place a one in the stencil buffer (reference&amp;mask=1). </P><br/><P>Quick note: Stencil testing is a per pixel test done each time an object is drawn to the screen. The reference value ANDed with the mask value is tested against the current stencil value ANDed with the mask value. </P><br/><P>The third line of code tests for three different conditions based on the stencil function we decided to use. The first two parameters are GL_KEEP, and the third is GL_REPLACE. </P><br/><P>The first parameter tells OpenGL what to do if the test fails. Because the first parameter is GL_KEEP, if the test fails (which it can't because we have the funtion set to GL_ALWAYS), we would leave the stencil value set at whatever it currently is. </P><br/><P>The second parameter tells OpenGL what do do if the stencil test passes, but the depth test fails. In the code below, we eventually disable depth testing so this parameter can be ignored. </P><br/><P>The third parameter is the important one. It tells OpenGL what to do if the test passes! In our code we tell OpenGL to replace (GL_REPLACE) the value in the stencil buffer. The value we put into the stencil buffer is our reference value ANDed with our mask value which is 1. </P><br/><P>After setting up the type of testing we want to do, we disable depth testing and jump to the code that draws our floor. </P><br/><P>In simple english I will try to sum up everything that the code does up until now... </P><br/><P>We tell OpenGL not to draw any colors to the screen. This means that when we draw the floor, it wont show up on the screen. BUT... each spot on the screen where the object (our floor) should be if we could see it will be tested based on the type of stencil testing we decide to do. The stencil buffer starts out full of 0's (empty). We want to set the stencil value to 1 wherever our object would have been drawn if we could see it. So we tell OpenGL we don't care about testing. If a pixel should have been drawn to the screen, we want that spot marked with a 1. GL_ALWAYS does exactly that. Our reference and mask values of 1 make sure that the value placed into the stencil buffer is indeed going to be 1! As we invisibly draw, our stencil operation checks each pixel location, and replaces the 0 with a 1. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glEnable(GL_STENCIL_TEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Stencil Buffer For "marking" The Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glStencilFunc(GL_ALWAYS, </SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Always Passes, 1 Bit Plane, 1 As Mask</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> We Set The Stencil Buffer To 1 Where We Draw Any Polygon<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Keep If Test Fails, Keep If Test Passes But Buffer Test Fails<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Replace If Test Passes</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_DEPTH_TEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Depth Testing</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DrawFloor(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw The Floor (Draws To The Stencil Buffer)<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> We Only Want To Mark It In The Stencil Buffer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>So now we have an invisible stencil mask of the floor. As long as stencil testing is enabled, the only places pixels will show up are places where the stencil buffer has a value of 1. All of the pixels on the screen where the invisible floor was drawn will have a stencil value of 1. Meaning as long as stencil testing is enabled, the only pixels that we will see are the pixels that we draw in the same spot our invisible floor was defined in the stencil buffer. The trick behind creating a real looking reflection that reflects in the floor and nowhere else! </P><br/><P>So now that we know the ball reflection will only be drawn where the floor should be, it's time to draw the reflection! We enable depth testing, and set the color mask back to all ones (meaning all the colors will be drawn to the screen). </P><br/><P>Instead of using GL_ALWAYS for our stencil function we are going to use GL_EQUAL. We'll leave the reference and mask values at 1. For the stencil operation we will set all the parameters to GL_KEEP. In english, any object we draw this time around will actually appear on the screen (because the color mask is set to true for each color). As long as stencil testing is enabled pixels will ONLY be drawn if the stencil buffer has a value of 1 (reference value ANDed with the mask, which is 1 EQUALS (GL_EQUAL) the stencil buffer value ANDed with the mask, which is also 1). If the stencil value is not 1 where the current pixel is being drawn it will not show up! GL_KEEP just tells OpenGL not to modify any values in the stencil buffer if the test passes OR fails! <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glEnable(GL_DEPTH_TEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Depth Testing</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glColorMask(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Color Mask to TRUE, TRUE, TRUE, TRUE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glStencilFunc(GL_EQUAL, </SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> We Draw Only Where The Stencil Is 1<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> (I.E. Where The Floor Was Drawn)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Don't Change The Stencil Buffer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>Now we enable the mirrored clipping plane. This plane is defined by eqr, and only allows object to be drawn from the center of the screen (where the floor is) down to the bottom of the screen (any negative value on the y-axis). That way the reflected ball that we draw can't come up through the center of the floor. That would look pretty bad if it did. If you don't understand what I mean, remove the first line below from the source code, and move the real ball (non reflected) through the floor. If clipping is not enabled, you will see the reflected ball pop out of the floor as the real ball goes into the floor. </P><br/><P>After we enable clipping plane0 (usually you can have from 0-5 clipping planes), we define the plane by telling it to use the parameters stored in eqr. </P><br/><P>We push the matrix (which basically saves the position of everything on the screen) and use glScalef(1.0f,-1.0f,1.0f) to flip the object upside down (creating a real looking reflection). Setting the y value of glScalef({x},{y},{z}) to a negative value forces OpenGL to render opposite on the y-axis. It's almost like flipping the entire screen upside down. When position an object at a positive value on the y-axis, it will appear at the bottom of the screen instead of at the top. When you rotate an object towards yourself, it will rotate away from you. Everything will be mirrored on the y-axis until you pop the matrix or set the y value back to 1.0f instead of -1.0f using glScalef({x},{y},{z}). <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glEnable(GL_CLIP_PLANE0); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Clip Plane For Removing Artifacts<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> (When The Object Crosses The Floor)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glClipPlane(GL_CLIP_PLANE0, eqr); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Equation For Reflected Objects</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glPushMatrix(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Push The Matrix Onto The Stack</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glScalef(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Mirror Y Axis</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P><BR><BR> </P></FONT>
  • temp
    0
    <P>再续<BR>The first line below positions our light to the location specified by LightPos. The light should shine on the bottom right of the reflected ball creating a very real looking light source. The position of the light is also mirrored. On the real ball (ball above the floor) the light is positioned at the top right of your screen, and shines on the top right of the real ball. When drawing the reflected ball, the light is positioned at the bottom right of your screen. </P><br/><P>We then move up or down on the y-axis to the value specified by height. Translations are mirrored, so if the value of height is 5.0f, the position we translate to will be mirrored (-5.0f). Positioning the reflected image under the floor, instead of above the floor! </P><br/><P>After position our reflected ball, we rotate the ball on both the x axis and y axis, based on the values of xrot and yrot. Keep in mind that any rotations on the x axis will also be mirrored. So if the real ball (ball above the floor) is rolling towards you on the x-axis, it will be rolling away from you in the reflection. </P><br/><P>After positioning the reflected ball and doing our rotations we draw the ball by calling DrawObject(), and pop the matrix (restoring things to how they were before we drew the ball). Popping the matrix all cancels mirroring on the y-axis. </P><br/><P>We then disable our clipping plane (plane0) so that we are not stuck drawing only to the bottom half of the screen, and last, we disable stencil testing so that we can draw to other spots on the screen other than where the floor should be. </P><br/><P>Note that we draw the reflected ball before we draw the floor. I'll explain why later on. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glLightfv(GL_LIGHT0, GL_POSITION, LightPos); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Up Light0</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glTranslatef(</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, height, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Position The Object</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glRotatef(xrot, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Rotate Local Coordinate System On X Axis</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glRotatef(yrot, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Rotate Local Coordinate System On Y Axis</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DrawObject(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw The Sphere (Reflection)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glPopMatrix(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Pop The Matrix Off The Stack</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_CLIP_PLANE0); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Clip Plane For Drawing The Floor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_STENCIL_TEST); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> We Don't Need The Stencil Buffer Any More (Disable)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P><FONT face="Courier New">We start off this section of code by positioning our light. The y-axis is no longer being mirrored so drawing the light this time around will position it at the top of the screen instead of the bottom right of the screen. </FONT></P><br/><P><FONT face="Courier New">We enable blending, disable lighting, and set the alpha value to 80% using the command glColor4f(1.0f,1.0f,1.0f,0.8f). The blending mode is set up using glBlendFunc(), and the semi transparent floor is drawn over top of the reflected ball. </FONT></P><br/><P><FONT face="Courier New">If we drew the floor first and then the reflected ball, the effect wouldn't look very good. By drawing the ball and then the floor, you can see a small amount of coloring from the floor mixed into the coloring of the ball. If I was looking into a BLUE mirror, I would expect the reflection to look a little blue. By rendering the ball first, the reflected image looks like it's tinted the color of the floor. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glLightfv(GL_LIGHT0, GL_POSITION, LightPos); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Up Light0 Position</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glEnable(GL_BLEND); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Blending (Otherwise The Reflected Object Wont Show)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_LIGHTING); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Since We Use Blending, We Disable Lighting</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glColor4f(</SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.8f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set Color To White With 80% Alpha</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Blending Based On Source Alpha And 1 Minus Dest Alpha</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DrawFloor(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw The Floor To The Screen</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>Now we draw the 'real' ball (the one that floats above the floor). We disabled lighting when we drew the floor, but now it's time to draw another ball so we will turn lighting back on. </P><br/><P>We don't need blending anymore so we disable blending. If we didn't disable blending, the colors from the floor would mix with the colors of our 'real' ball when it was floating over top of the floor. We don't want the 'real' ball to look like the reflection so we disable blending. </P><br/><P>We are not going to clip the actual ball. If the real ball goes through the floor, we should see it come out the bottom. If we were using clipping the ball wouldn't show up after it went through the floor. If you didn't want to see the ball come through the floor, you would set up a clipping equation that set the Y value to +1.0f, then when the ball went through the floor, you wouldn't see it (you would only see the ball when it was drawn on at a positive value on the y-axis. For this demo, there's no reason we shouldn't see it come through the floor. </P><br/><P>We then translate up or down on the y-axis to the position specified by height. Only this time the y-axis is not mirrored, so the ball travels the opposite direction that the reflected image travels. If we move the 'real' ball down the reflected ball will move up. If we move the 'real' ball up, the reflected ball will move down. </P><br/><P>We rotate the 'real' ball, and again, because the y-axis is not mirrored, the ball will spin the opposite direction of the reflected ball. If the reflected ball is rolling towards you the 'real' ball will be rolling away from you. This creates the illusion of a real reflection. </P><br/><P>After positioning and rotating the ball, we draw the 'real' ball by calling DrawObject(). <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> glEnable(GL_LIGHTING); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Enable Lighting</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glDisable(GL_BLEND); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Disable Blending</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glTranslatef(</SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, height, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Position The Ball At Proper Height</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glRotatef(xrot, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Rotate On The X Axis</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glRotatef(yrot, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">1.0f</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0.0f</SPAN><SPAN style="COLOR: #000000">); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Rotate On The Y Axis</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DrawObject(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Draw The Ball</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><br/><P>The following code rotates the ball on the x and y axis. By increasing xrot by xrotspeed we rotate the ball on the x-axis. By increasing yrot by yrotspeed we spin the ball on the y-axis. If xrotspeed is a very high value in the positive or negative direction the ball will spin quicker than if xrotspeed was a low value, closer to 0.0f. Same goes for yrotspeed. The higher the value, the faster the ball spins on the y-axis. </P><br/><P>Before we return TRUE, we do a glFlush(). This tells OpenGL to render everything left in the GL pipeline before continuing, and can help prevent flickering on slower video cards. <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000"> xrot </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000"> xrotspeed; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Update X Rotation Angle By xrotspeed</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> yrot </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000"> yrotspeed; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Update Y Rotation Angle By yrotspeed</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> glFlush(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Flush The GL Pipeline</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> TRUE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Everything Went OK</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">}<br/><br/></SPAN></DIV></PRE><br/><P>The following code will watch for key presses. The first 4 lines check to see if you are pressing one of the 4 arrow keys. If you are, the ball is spun right, left, down or up. </P><br/><P>The next 2 lines check to see if you are pressing the 'A' or 'Z' keys. Pressing 'A' will zoom you in closer to the ball and pressing 'Z' will zoom you away from the ball. </P><br/><P>Pressing 'PAGE UP' will increase the value of height moving the ball up, and pressing 'PAGE DOWN' will decrease the value of height moving the ball down (closer to the floor). <BR><BR></P><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> ProcessKeyboard() </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Process Keyboard Results</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">{<br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_RIGHT]) yrotspeed </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0.08f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Right Arrow Pressed (Increase yrotspeed)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_LEFT]) yrotspeed </SPAN><SPAN style="COLOR: #000000">-=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0.08f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Left Arrow Pressed (Decrease yrotspeed)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_DOWN]) xrotspeed </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0.08f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Down Arrow Pressed (Increase xrotspeed)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_UP]) xrotspeed </SPAN><SPAN style="COLOR: #000000">-=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0.08f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Up Arrow Pressed (Decrease xrotspeed)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">]) zoom </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">0.05f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 'A' Key Pressed ... Zoom In</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">Z</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">]) zoom </SPAN><SPAN style="COLOR: #000000">-=</SPAN><SPAN style="COLOR: #000000">0.05f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 'Z' Key Pressed ... Zoom Out</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_PRIOR]) height </SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">0.03f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Page Up Key Pressed Move Ball Up</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (keys[VK_NEXT]) height </SPAN><SPAN style="COLOR: #000000">-=</SPAN><SPAN style="COLOR: #000000">0.03f</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Page Down Key Pressed Move Ball Down</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000">}<br/><br/></SPAN></DIV></PRE>The KillGLWindow() code hasn't changed, so I'll skip over it. <BR><BR><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000">GLvoid KillGLWindow(GLvoid) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Properly Kill The Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE><BR>You can skim through the following code. Even though only one line of code has changed in CreateGLWindow(), I have included all of the code so it's easier to follow through the tutorial. <BR><BR><PRE><DIV><!--<br/><br/>Code highlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br/><br/>--><SPAN style="COLOR: #000000">BOOL CreateGLWindow(</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> title, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> width, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> height, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> bits, </SPAN><SPAN style="COLOR: #0000ff">bool</SPAN><SPAN style="COLOR: #000000"> fullscreenflag)<br/>{<br/> GLuint PixelFormat; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Holds The Results After Searching For A Match</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> WNDCLASS wc; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Windows Class Structure</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DWORD dwExStyle; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Extended Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> DWORD dwStyle; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> fullscreen</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">fullscreenflag; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Global Fullscreen Flag</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> hInstance </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> GetModuleHandle(NULL); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Grab An Instance For Our Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.style </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> CS_HREDRAW </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> CS_VREDRAW </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> CS_OWNDC; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Redraw On Size, And Own DC For Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.lpfnWndProc </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> (WNDPROC) WndProc; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> WndProc Handles Messages</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.cbClsExtra </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Extra Window Data</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.cbWndExtra </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Extra Window Data</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.hInstance </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> hInstance; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Instance</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.hIcon </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> LoadIcon(NULL, IDI_WINLOGO); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Load The Default Icon</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.hCursor </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> LoadCursor(NULL, IDC_ARROW); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Load The Arrow Pointer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.hbrBackground </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> NULL; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Background Required For GL</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.lpszMenuName </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> NULL; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> We Don't Want A Menu</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> wc.lpszClassName </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">OpenGL</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Set The Class Name</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">RegisterClass(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">wc)) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Attempt To Register The Window Class</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> MessageBox(NULL,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Failed To Register The Window Class.</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">ERROR</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,MB_OK</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">MB_ICONEXCLAMATION);<br/> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> FALSE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Return FALSE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/> <br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (fullscreen) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Attempt Fullscreen Mode?</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> DEVMODE dmScreenSettings; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Device Mode</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> memset(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">dmScreenSettings,</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #0000ff">sizeof</SPAN><SPAN style="COLOR: #000000">(dmScreenSettings)); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Makes Sure Memory's Cleared</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dmScreenSettings.dmSize</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">sizeof</SPAN><SPAN style="COLOR: #000000">(dmScreenSettings); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Size Of The Devmode Structure</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dmScreenSettings.dmPelsWidth </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> width; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Selected Screen Width</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dmScreenSettings.dmPelsHeight </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> height; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Selected Screen Height</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dmScreenSettings.dmBitsPerPel </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> bits; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Selected Bits Per Pixel</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dmScreenSettings.dmFields</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">DM_BITSPERPEL</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">DM_PELSWIDTH</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">DM_PELSHEIGHT;<br/><br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (ChangeDisplaySettings(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">dmScreenSettings,CDS_FULLSCREEN)</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">DISP_CHANGE_SUCCESSFUL)<br/> {<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (MessageBox(NULL,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">NeHe GL</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,MB_YESNO</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">MB_ICONEXCLAMATION)</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">IDYES)<br/> {<br/> fullscreen</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">FALSE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Windowed Mode Selected. Fullscreen = FALSE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/> </SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000"><br/> {<br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Pop Up A Message Box Letting User Know The Program Is Closing</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> MessageBox(NULL,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Program Will Now Close.</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">ERROR</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,MB_OK</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">MB_ICONSTOP);<br/> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> FALSE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Return FALSE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/> }<br/> }<br/><br/> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (fullscreen) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Are We Still In Fullscreen Mode?</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> dwExStyle</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">WS_EX_APPWINDOW; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Extended Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dwStyle</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">WS_POPUP </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> WS_CLIPSIBLINGS </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> WS_CLIPCHILDREN; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Windows Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> ShowCursor(FALSE); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Hide Mouse Pointer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/> </SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000"><br/> {<br/> dwExStyle</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">WS_EX_APPWINDOW </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> WS_EX_WINDOWEDGE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Extended Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dwStyle</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">WS_OVERLAPPEDWINDOW </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> WS_CLIPSIBLINGS </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> WS_CLIPCHILDREN;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Windows Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/><br/> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Create The Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">(hWnd</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">CreateWindowEx( dwExStyle, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Extended Style For The Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">OpenGL</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Class Name</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> title, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Title</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> dwStyle, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Style</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Window Position</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> width, height, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Selected Width And Height</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> NULL, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Parent Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> NULL, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Menu</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> hInstance, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Instance</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> NULL))) </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Dont Pass Anything To WM_CREATE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> KillGLWindow(); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Reset The Display</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> MessageBox(NULL,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Window Creation Error.</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">ERROR</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,MB_OK</SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000">MB_ICONEXCLAMATION);<br/> </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> FALSE; </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Return FALSE</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> }<br/><br/> </SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000"> PIXELFORMATDESCRIPTOR pfd</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> pfd Tells Windows How We Want Things To Be</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> {<br/> </SPAN><SPAN style="COLOR: #0000ff">sizeof</SPAN><SPAN style="COLOR: #000000">(PIXELFORMATDESCRIPTOR), </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Size Of This Pixel Format Descriptor</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Version Number</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> PFD_DRAW_TO_WINDOW </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Format Must Support Window</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> PFD_SUPPORT_OPENGL </SPAN><SPAN style="COLOR: #000000">|</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Format Must Support OpenGL</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> PFD_DOUBLEBUFFER, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Must Support Double Buffering</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> PFD_TYPE_RGBA, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Request An RGBA Format</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> bits, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Select Our Color Depth</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Color Bits Ignored</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Alpha Buffer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Shift Bit Ignored</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> No Accumulation Buffer</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Accumulation Bits Ignored</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">16</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 16Bit Z-Buffer (Depth Buffer)</SPAN><SPAN style="COLOR: #008000"><br/></SPAN><SPAN style="COLOR: #000000"><br/></SPAN></DIV></PRE></FONT>

在OpenGL中实现镜面反射的相关案例教程

Electric vehicles are using electric machines for propulsion and energy recuperation. An electric machine can be of two types: motor and generator. An electric motor converts electric energy into mech
Electric vehicles are using electric machines for propulsion and energy recuperation. An electric machine can be of two types: motor and generator. An electric motor converts electric energy into mech
简介:FRED作为COM组件可以实现与Excel、VB、Matlab等调用来完成庞大的计算任务或画图,本文的目的是通过运行一个案例来实现与Matlab的相互调用,在此我们需要借助脚本来完成,此脚本为视为通用型脚本。 配置:在执行调用之前,我们需要在Matlab命令行窗口输入如下命令: enableservice('AutomationServer', true) enableservice('Au
原文标题:Why SYCL: Elephants in the SYCL Room By James Reinders and Michael Wong 摘录自:https://www.hpcwire.com/2022/02/03/why-sycl-elephants-in-the-sycl-room/ Commentary — In the second of a series of guest
晶体塑性有限元仿真入门(3)--开源代码平台EVOCD 晶体塑性有限元初学者较为熟知的两个工具Huang's UMAT以及DAMASK平台,这篇文章介绍另外一个晶体塑性有限元方法(CPFEM)的开源代码平台EVOCD,讲解如何使用这些开源代码进行材料的塑性变形模拟以及模拟变形过程中晶体取向的变化(织构)。 图1 EVOCD的CPFEM流程图 (E.B. Marin, Center for Adva
影响力
粉丝
内容
获赞
收藏
    项目客服
    培训客服
    4 0