www.pudn.com > 13_184353_cubemap.rar > main.cpp


/* 
 *		This Code Was Created By Jeff Molofee 2000 
 *		A HUGE Thanks To Fredric Echols For Cleaning Up 
 *		And Optimizing This Code, Making It More Flexible! 
 *		If You've Found This Code Useful, Please Let Me Know. 
 *		Visit My Site At nehe.gamedev.net 
 */ 
 
#include 		// Header File For Windows 
#include 			// Header File For The OpenGL32 Library 
#include 			// Header File For The GLu32 Library 
#include 		// Header File For The Glaux Library 
#include "GLext.h" 
#include "3DS.h" 
#include "Camera.h" 
 
#include                
#include  
 
//Let us use CG Language 
#include  
#include  
 
HDC			hDC=NULL;		// Private GDI Device Context 
HGLRC		hRC=NULL;		// Permanent Rendering Context 
HWND		hWnd=NULL;		// Holds Our Window Handle 
HINSTANCE	hInstance;		// Holds The Instance Of The Application 
int fps; 
 
CCamera cam; 
 
float eyePosition[3]; 
float updirection[3]; 
t3DModel gundam; 
 
 
int state(0);				//refer to render state; 
 
GLuint	base;				// Base Display List For The Font Set 
char* brand=NULL; 
char* vendor=NULL; 
char* version=NULL; 
float last_time(0); 
 
//texture for each face 
GLuint cubeface[6]; 
//texture for cubemap 
GLuint cubemap; 
 
 
 
//Variables for CG 
CGprofile   g_CGprofile_vertex; 
CGprofile   g_CGprofile_pixel; 
CGcontext   g_CGcontext; 
 
//reflection effect program 
CGprogram   g_CGreflection_vertex; 
CGprogram   g_CGreflection_pixel; 
 
CGprogram   g_CGrefraction_vertex; 
CGprogram   g_CGrefraction_pixel; 
 
CGprogram   g_CGdispersion_vertex; 
CGprogram   g_CGdispersion_pixel; 
 
 
 
void InitCG() 
{ 
    // 
    // Search for a valid vertex shader profile in this order: 
    // 
    // CG_PROFILE_ARBVP1 - GL_ARB_vertex_program 
    // CG_PROFILE_VP40   - GL_ARB_vertex_program + GL_NV_vertex_program3 
    // 
 
    if( cgGLIsProfileSupported(CG_PROFILE_ARBVP1) ) 
        g_CGprofile_vertex = CG_PROFILE_ARBVP1; 
    else if( cgGLIsProfileSupported(CG_PROFILE_VP40) ) 
        g_CGprofile_vertex = CG_PROFILE_VP40; 
    else 
    { 
        MessageBox( NULL,"Failed to initialize vertex shader! Hardware doesn't " 
            "support any of the required vertex shading extensions!", 
            "ERROR",MB_OK|MB_ICONEXCLAMATION ); 
        return; 
    } 
 
	// 
	// Search for a valid pixel shader profile in this order: 
	// 
	// CG_PROFILE_ARBFP1 - GL_ARB_fragment_program 
	// CG_PROFILE_FP30   - GL_NV_fragment_program 
	// CG_PROFILE_FP20   - NV_texture_shader & NV_register_combiners 
	// 
	 
	if( cgGLIsProfileSupported(CG_PROFILE_ARBFP1) ) 
        g_CGprofile_pixel = CG_PROFILE_ARBFP1; 
    else if( cgGLIsProfileSupported(CG_PROFILE_FP30) ) 
        g_CGprofile_pixel = CG_PROFILE_FP30; 
	else if( cgGLIsProfileSupported(CG_PROFILE_FP20) ) 
        g_CGprofile_pixel = CG_PROFILE_FP20; 
    else 
    { 
        MessageBox( NULL,"Failed to initialize pixel shader! Hardware doesn't " 
			        "support any of the required pixel shading extensions!", 
			        "ERROR",MB_OK|MB_ICONEXCLAMATION ); 
		return; 
    } 
 
	// Create the context... 
	g_CGcontext = cgCreateContext(); 
 
	// 
	// Create the vertex and pixel shader... 
	// 
	 
	g_CGreflection_vertex = cgCreateProgramFromFile( g_CGcontext, 
										          CG_SOURCE, 
										         "vertex_reflection.cg", 
										         g_CGprofile_vertex, 
										         NULL,  
										         NULL ); 
	g_CGreflection_pixel = cgCreateProgramFromFile( g_CGcontext, 
												CG_SOURCE, 
												"pixel_reflection.cg", 
												g_CGprofile_pixel, 
												NULL, 
												NULL ); 
	 
	g_CGrefraction_vertex = cgCreateProgramFromFile( g_CGcontext, 
										          CG_SOURCE, 
										         "vertex_refraction.cg", 
										         g_CGprofile_vertex, 
										         NULL,  
										         NULL ); 
	g_CGrefraction_pixel = cgCreateProgramFromFile( g_CGcontext, 
												CG_SOURCE, 
												"pixel_refraction.cg", 
												g_CGprofile_pixel, 
												NULL, 
												NULL ); 
 
	g_CGdispersion_vertex = cgCreateProgramFromFile( g_CGcontext, 
										          CG_SOURCE, 
										         "vertex_dispersion.cg", 
										         g_CGprofile_vertex, 
										         NULL,  
										         NULL ); 
	g_CGdispersion_pixel = cgCreateProgramFromFile( g_CGcontext, 
												CG_SOURCE, 
												"pixel_dispersion.cg", 
												g_CGprofile_pixel, 
												NULL, 
												NULL ); 
 
	// 
	// Load the programs using Cg's expanded interface... 
	// 
 
	cgGLLoadProgram( g_CGreflection_vertex ); 
	cgGLLoadProgram( g_CGreflection_pixel ); 
	cgGLLoadProgram( g_CGrefraction_vertex ); 
	cgGLLoadProgram( g_CGrefraction_pixel ); 
	cgGLLoadProgram( g_CGdispersion_vertex ); 
	cgGLLoadProgram( g_CGdispersion_pixel ); 
 
 
	// 
	// Bind some parameters by name so we can set them later... 
	// 
 
} 
 
 
//画这个模型 
 
void DrawModel(t3DModel& Model) 
{ 
  // 遍历模型中所有的对象 
  for(int i = 0; i < Model.numOfObjects; i++) 
  { 
    // 如果对象的大小小于0,则退出 
    if(Model.pObject.size() <= 0) break; 
 
    // 获得当前显示的对象 
    t3DObject *pObject = &Model.pObject[i]; 
       
    // 判断该对象是否有纹理映射 
    if(pObject->bHasTexture) { 
 
      // 打开纹理映射 
      glEnable(GL_TEXTURE_2D); 
      glColor3ub(255, 255, 255); 
      glBindTexture(GL_TEXTURE_2D, Model.texture[pObject->materialID]); 
    } else { 
 
      // 关闭纹理映射 
      glDisable(GL_TEXTURE_2D); 
      glColor3ub(255, 255, 255); 
    } 
    // 开始以g_ViewMode模式绘制 
    glBegin(GL_TRIANGLES);           
      // 遍历所有的面 
      for(int j = 0; j < pObject->numOfFaces; j++) 
      { 
        // 遍历三角形的所有点 
        for(int whichVertex = 0; whichVertex < 3; whichVertex++) 
        { 
          // 获得面对每个点的索引 
          int index = pObject->pFaces[j].vertIndex[whichVertex]; 
       
          // 给出法向量 
          glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z); 
         
          // 如果对象具有纹理 
          if(pObject->bHasTexture) { 
 
            // 确定是否有UVW纹理坐标 
            if(pObject->pTexVerts) { 
              glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y); 
            } 
          } else { 
 
            if(Model.pMaterials.size() && pObject->materialID >= 0)  
            { 
              BYTE *pColor = Model.pMaterials[pObject->materialID].color; 
              glColor3ub(pColor[0], pColor[1], pColor[2]); 
            } 
          } 
          glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z); 
        } 
      } 
 
    glEnd();                // 绘制结束 
  } 
} 
 
//--------------------------------------------------------------------------- 
// get the millseconds from the demo start - time line 
//--------------------------------------------------------------------------- 
float GetTime() 
{ 
  static bool init = false; 
  static bool hires = false; 
  static __int64 freq = 1; 
  if(!init) 
  { 
    hires = !QueryPerformanceFrequency((LARGE_INTEGER *)&freq); 
    if(!hires) 
      freq = 1000; 
    init = true; 
  } 
 
  __int64 now; 
 
  if(hires) 
    QueryPerformanceCounter((LARGE_INTEGER *)&now); 
  else 
    now = GetTickCount(); 
 
  return (float)((double)now / (double)freq); 
} 
 
GLvoid BuildFont(GLvoid)								// Build Our Bitmap Font 
{ 
	HFONT	font;										// Windows Font ID 
	HFONT	oldfont;									// Used For Good House Keeping 
 
	base = glGenLists(96);								// Storage For 96 Characters 
 
	font = CreateFont(	-15,							// Height Of Font 
						0,								// Width Of Font 
						0,								// Angle Of Escapement 
						0,								// Orientation Angle 
						FW_BOLD,						// Font Weight 
						FALSE,							// Italic 
						FALSE,							// Underline 
						FALSE,							// Strikeout 
						ANSI_CHARSET,					// Character Set Identifier 
						OUT_TT_PRECIS,					// Output Precision 
						CLIP_DEFAULT_PRECIS,			// Clipping Precision 
						ANTIALIASED_QUALITY,			// Output Quality 
						FF_DONTCARE|DEFAULT_PITCH,		// Family And Pitch 
						"Arial");					// Font Name 
 
	oldfont = (HFONT)SelectObject(hDC, font);           // Selects The Font We Want 
	wglUseFontBitmaps(hDC, 32, 96, base);				// Builds 96 Characters Starting At Character 32 
	SelectObject(hDC, oldfont);							// Selects The Font We Want 
	DeleteObject(font);									// Delete The Font 
} 
 
GLvoid KillFont(GLvoid)									// Delete The Font List 
{ 
	glDeleteLists(base, 96);							// Delete All 96 Characters 
} 
 
GLvoid glPrint(const char *fmt, ...)					// Custom GL "Print" Routine 
{ 
	char		text[256];								// Holds Our String 
	va_list		ap;										// Pointer To List Of Arguments 
 
	if (fmt == NULL)									// If There's No Text 
		return;											// Do Nothing 
 
	va_start(ap, fmt);									// Parses The String For Variables 
	    vsprintf(text, fmt, ap);						// And Converts Symbols To Actual Numbers 
	va_end(ap);											// Results Are Stored In Text 
 
	glPushAttrib(GL_LIST_BIT);							// Pushes The Display List Bits 
	glListBase(base - 32);								// Sets The Base Character to 32 
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text 
	glPopAttrib();										// Pops The Display List Bits 
} 
 
 
 
 
 
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 
 
LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	// Declaration For WndProc 
 
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)		// Resize And Initialize The GL Window 
{ 
	if (height==0)										// Prevent A Divide By Zero By 
	{ 
		height=1;										// Making Height Equal One 
	} 
 
	glViewport(0,0,width,height);						// Reset The Current Viewport 
 
	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix 
	glLoadIdentity();									// Reset The Projection Matrix 
 
	// Calculate The Aspect Ratio Of The Window 
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,99999.0f); 
 
	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix 
	glLoadIdentity();									// Reset The Modelview Matrix 
} 
 
BOOL LoadCubeMap(GLenum face, LPSTR szPathName) 
{ 
  HDC      hdcTemp;                        // The DC To Hold Our Bitmap 
  HBITMAP    hbmpTemp;                        // Holds The Bitmap Temporarily 
  IPicture  *pPicture;                        // IPicture Interface 
  OLECHAR    wszPath[MAX_PATH+1];                  // Full Path To Picture (WCHAR) 
  char    szPath[MAX_PATH+1];                    // Full Path To Picture 
  long    lWidth;                          // Width In Logical Units 
  long    lHeight;                        // Height In Logical Units 
  long    lWidthPixels;                      // Width In Pixels 
  long    lHeightPixels;                      // Height In Pixels 
  GLint    glMaxTexDim ;                      // Holds Maximum Texture Size 
 
  if (strstr(szPathName, "http://"))                  // If PathName Contains http:// Then... 
  { 
    strcpy(szPath, szPathName);                    // Append The PathName To szPath 
  } 
  else                                // Otherwise... We Are Loading From A File 
  { 
    GetCurrentDirectory(MAX_PATH, szPath);              // Get Our Working Directory 
    strcat(szPath, "\\");                      // Append "\" After The Working Directory 
    strcat(szPath, szPathName);                    // Append The PathName 
  } 
 
  MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);    // Convert From ASCII To Unicode 
  HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture); 
 
  if(FAILED(hr))                            // If Loading Failed 
    return FALSE;                          // Return False 
 
  hdcTemp = CreateCompatibleDC(GetDC(0));                // Create The Windows Compatible Device Context 
  if(!hdcTemp)                            // Did Creation Fail? 
  { 
    pPicture->Release();                      // Decrements IPicture Reference Count 
    return FALSE;                          // Return False (Failure) 
  } 
 
  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);          // Get Maximum Texture Size Supported 
   
  pPicture->get_Width(&lWidth);                    // Get IPicture Width (Convert To Pixels) 
  lWidthPixels  = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540); 
  pPicture->get_Height(&lHeight);                    // Get IPicture Height (Convert To Pixels) 
  lHeightPixels  = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540); 
 
  // Resize Image To Closest Power Of Two 
  if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit 
    lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);  
  else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle 
    lWidthPixels = glMaxTexDim; 
  
  if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit 
    lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f); 
  else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle 
    lHeightPixels = glMaxTexDim; 
   
  //  Create A Temporary Bitmap 
  BITMAPINFO  bi = {0};                        // The Type Of Bitmap We Request 
  DWORD    *pBits = 0;                        // Pointer To The Bitmap Bits 
 
  bi.bmiHeader.biSize      = sizeof(BITMAPINFOHEADER);        // Set Structure Size 
  bi.bmiHeader.biBitCount    = 32;                  // 32 Bit 
  bi.bmiHeader.biWidth    = lWidthPixels;              // Power Of Two Width 
  bi.bmiHeader.biHeight    = lHeightPixels;            // Make Image Top Up (Positive Y-Axis) 
  bi.bmiHeader.biCompression  = BI_RGB;                // RGB Encoding 
  bi.bmiHeader.biPlanes    = 1;                  // 1 Bitplane 
 
  //  Creating A Bitmap This Way Allows Us To Specify Color Depth And Gives Us Imediate Access To The Bits 
  hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0); 
   
  if(!hbmpTemp)                            // Did Creation Fail? 
  { 
    DeleteDC(hdcTemp);                        // Delete The Device Context 
    pPicture->Release();                      // Decrements IPicture Reference Count 
    return FALSE;                          // Return False (Failure) 
  } 
 
  SelectObject(hdcTemp, hbmpTemp);                  // Select Handle To Our Temp DC And Our Temp Bitmap Object 
 
  // Render The IPicture On To The Bitmap 
  pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0); 
 
  // Convert From BGR To RGB Format And Add An Alpha Value Of 255 
  for(long i = 0; i < lWidthPixels * lHeightPixels; i++)        // Loop Through All Of The Pixels 
  { 
    BYTE* pPixel  = (BYTE*)(&pBits[i]);              // Grab The Current Pixel 
    BYTE temp    = pPixel[0];                  // Store 1st Color In Temp Variable (Blue) 
    pPixel[0]    = pPixel[2];                  // Move Red Value To Correct Position (1st) 
    pPixel[2]    = temp;                      // Move Temp Value To Correct Blue Position (3rd) 
 
    // This Will Make Any Black Pixels, Completely Transparent    (You Can Hardcode The Value If You Wish) 
    if ((pPixel[0]==0) && (pPixel[1]==0) && (pPixel[2]==0))      // Is Pixel Completely Black 
      pPixel[3]  = 0;                      // Set The Alpha Value To 0 
    else                              // Otherwise 
      pPixel[3]  = 255;                      // Set The Alpha Value To 255 
  } 
 
//  glGenTextures(1, &texid);                      // Create The Texture 
 
  // Typical Texture Generation Using Data From The Bitmap 
//  glBindTexture(GL_TEXTURE_2D, texid);                // Bind To The Texture ID 
//  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // (Modify This For The Type Of Filtering You Want) 
//  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // (Modify This For The Type Of Filtering You Want) 
//  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);  // (Modify This If You Want Mipmaps) 
 
  glTexImage2D(face, 0, GL_RGBA, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits); 
  glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
  glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
  
  DeleteObject(hbmpTemp);                        // Delete The Object 
  DeleteDC(hdcTemp);                          // Delete The Device Context 
 
  pPicture->Release();                        // Decrements IPicture Reference Count	 
} 
 
void LoadTextures() 
{ 
	char Extension_Name[] = "GL_EXT_texture_cube_map"; 
	// Allocate Memory For Our Extension String 
	char* glextstring=(char *)malloc(strlen((char *)glGetString(GL_EXTENSIONS))+1); 
	strcpy (glextstring,(char *)glGetString(GL_EXTENSIONS));		// Grab The Extension List, Store In glextstring 
	if (!strstr(glextstring,Extension_Name))				// Check To See If The Extension Is Supported 
	{ 
		MessageBox(NULL, "Your renderer cannot support GL_EXT_texture_cube_map!", "Error", MB_OK); 
		exit(0);							// If Not, Return FALSE 
	} 
	free(glextstring);							// Free Allocated Memory 
	glGenTextures(1, &cubemap); 
	glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, cubemap); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT, "lobbyxpos.jpg"); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT, "lobbyxneg.jpg"); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT, "lobbyypos.jpg"); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT, "lobbyyneg.jpg"); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT, "lobbyzpos.jpg"); 
	LoadCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT, "lobbyzneg.jpg"); 
 
	 
 
	CLoad3DS* loader=new(CLoad3DS); 
	loader->BuildTexture("lobbyxpos.jpg", cubeface[0]); 
	loader->BuildTexture("lobbyxneg.jpg", cubeface[1]); 
	loader->BuildTexture("lobbyypos.jpg", cubeface[2]); 
	loader->BuildTexture("lobbyyneg.jpg", cubeface[3]); 
	loader->BuildTexture("lobbyzpos.jpg", cubeface[4]); 
	loader->BuildTexture("lobbyzneg.jpg", cubeface[5]); 
	delete loader; 
 
} 
 
void CubeBox() 
{ 
	glDisable(GL_LIGHTING); 
	glColor3f(1.0f, 1.0f, 1.0f); 
	glEnable(GL_TEXTURE_2D); 
	glBindTexture(GL_TEXTURE_2D, cubeface[0]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(1000, 1000, 1000); 
		glTexCoord2i(0, 0);	glVertex3i(1000, -1000, 1000); 
		glTexCoord2i(1, 0);	glVertex3i(1000, -1000, -1000); 
		glTexCoord2i(1, 1);	glVertex3i(1000, 1000, -1000); 
	glEnd(); 
	 
	glBindTexture(GL_TEXTURE_2D, cubeface[1]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(-1000, 1000, -1000); 
		glTexCoord2i(0, 0);	glVertex3i(-1000, -1000, -1000); 
		glTexCoord2i(1, 0);	glVertex3i(-1000, -1000, 1000); 
		glTexCoord2i(1, 1);	glVertex3i(-1000, 1000, 1000); 
	glEnd(); 
 
	glBindTexture(GL_TEXTURE_2D, cubeface[2]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(-1000, 1000, -1000); 
		glTexCoord2i(0, 0);	glVertex3i(-1000, 1000, 1000); 
		glTexCoord2i(1, 0);	glVertex3i(1000, 1000,1000); 
		glTexCoord2i(1, 1);	glVertex3i(1000, 1000, -1000); 
	glEnd(); 
 
	glBindTexture(GL_TEXTURE_2D, cubeface[3]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(-1000, -1000, 1000); 
		glTexCoord2i(0, 0);	glVertex3i(-1000, -1000, -1000); 
		glTexCoord2i(1, 0);	glVertex3i(1000, -1000,-1000); 
		glTexCoord2i(1, 1);	glVertex3i(1000, -1000, 1000); 
	glEnd(); 
 
	glBindTexture(GL_TEXTURE_2D, cubeface[4]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(-1000, 1000, 1000); 
		glTexCoord2i(0, 0);	glVertex3i(-1000,-1000, 1000); 
		glTexCoord2i(1, 0);	glVertex3i(1000, -1000, 1000); 
		glTexCoord2i(1, 1);	glVertex3i(1000, 1000, 1000); 
	glEnd(); 
 
	glBindTexture(GL_TEXTURE_2D, cubeface[5]); 
	glBegin(GL_QUADS); 
		glTexCoord2i(0, 1);	glVertex3i(1000, 1000, -1000); 
		glTexCoord2i(0, 0);	glVertex3i(1000, -1000, -1000); 
		glTexCoord2i(1, 0);	glVertex3i(-1000,  -1000, -1000); 
		glTexCoord2i(1, 1);	glVertex3i(-1000,  1000, -1000); 
	glEnd(); 
	 
 
	glDisable(GL_TEXTURE_2D); 
} 
 
void EyeMove() 
{ 
	static float angle1=0.0f; 
	eyePosition[0]=600.0f*sin(angle1); 
	eyePosition[1]=600.0f*sin(angle1/4.0f); 
	eyePosition[2]=600.0f*cos(angle1); 
	 
 
	angle1+=0.01f; 
} 
 
GLuint model; 
 
void Scene(); 
int InitGL(GLvoid)										// All Setup For OpenGL Goes Here 
{ 
	//get the info of your renderer 
	brand=(char*)glGetString(GL_RENDERER); 
    vendor=(char*)glGetString(GL_VENDOR); 
	version=(char*)glGetString(GL_VERSION); 
	 
	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading 
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background 
	glClearDepth(1.0f);									// Depth Buffer Setup 
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing 
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do 
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations 
	 
	BuildFont(); 
//	cam.PositionCamera(0.0f, 0.0f, 800.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 
	LoadTextures(); 
 
	CLoad3DS* loader=new(CLoad3DS); 
	loader->Import3DS(&gundam, "GUNDAM91.3DS"); 
	delete loader; 
 
	model=glGenLists(1); 
	glNewList(model, GL_COMPILE); 
	DrawModel(gundam); 
	glEndList(); 
	 
	InitCG(); 
 
	return TRUE;										// Initialization Went OK 
} 
 
void Dispersion() 
{ 
	//cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGreflection_vertex, "modelViewProj"), CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); 
	cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGdispersion_vertex, "modelToWorld"), CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY ); 
	// Identify the texture to use 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap0"),  cubemap ); 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap1"),  cubemap ); 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap2"),  cubemap ); 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap3"),  cubemap ); 
	 
	cgGLSetParameter3fv(cgGetNamedParameter(g_CGdispersion_vertex, "eyePositionW"), eyePosition); 
 
 
	cgGLBindProgram( g_CGdispersion_vertex ); 
	cgGLEnableProfile( g_CGprofile_vertex ); 
 
	cgGLBindProgram( g_CGdispersion_pixel ); 
	cgGLEnableProfile( g_CGprofile_pixel ); 
 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap0") ); 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap1") ); 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap2") ); 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap3") ); 
	 
	glCallList(model); 
 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap0") ); 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap1") ); 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap2") ); 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGdispersion_pixel, "environmentMap3") ); 
	 
	cgGLDisableProfile( g_CGprofile_vertex ); 
	cgGLDisableProfile( g_CGprofile_pixel ); 
 
} 
 
void Refraction() 
{ 
	//cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGreflection_vertex, "modelViewProj"), CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); 
	cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGrefraction_vertex, "modelToWorld"), CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY ); 
	// Identify the texture to use 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGrefraction_pixel, "environmentMap"),  cubemap ); 
	cgGLSetParameter3fv(cgGetNamedParameter(g_CGrefraction_vertex, "eyePositionW"), eyePosition); 
 
 
	cgGLBindProgram( g_CGrefraction_vertex ); 
	cgGLEnableProfile( g_CGprofile_vertex ); 
 
	cgGLBindProgram( g_CGrefraction_pixel ); 
	cgGLEnableProfile( g_CGprofile_pixel ); 
 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGrefraction_pixel, "environmentMap") ); 
	 
	glCallList(model); 
 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGrefraction_pixel, "environmentMap") ); 
	 
	cgGLDisableProfile( g_CGprofile_vertex ); 
	cgGLDisableProfile( g_CGprofile_pixel ); 
 
} 
 
void Reflection() 
{ 
	//cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGreflection_vertex, "modelViewProj"), CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); 
	cgGLSetStateMatrixParameter(cgGetNamedParameter(g_CGreflection_vertex, "modelToWorld"), CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY ); 
	// Identify the texture to use 
    cgGLSetTextureParameter(cgGetNamedParameter(g_CGreflection_pixel, "environmentMap"),  cubemap ); 
	cgGLSetParameter3fv(cgGetNamedParameter(g_CGreflection_vertex, "eyePositionW"), eyePosition); 
 
 
	cgGLBindProgram( g_CGreflection_vertex ); 
	cgGLEnableProfile( g_CGprofile_vertex ); 
 
	cgGLBindProgram( g_CGreflection_pixel ); 
	cgGLEnableProfile( g_CGprofile_pixel ); 
 
	cgGLEnableTextureParameter( cgGetNamedParameter(g_CGreflection_pixel, "environmentMap") ); 
	 
	glCallList(model); 
 
	cgGLDisableTextureParameter( cgGetNamedParameter(g_CGreflection_pixel, "environmentMap") ); 
	 
	cgGLDisableProfile( g_CGprofile_vertex ); 
	cgGLDisableProfile( g_CGprofile_pixel ); 
 
} 
 
 
 
 
void Scene() 
{ 
	glCallList(model); 
} 
 
int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing 
{ 
	static int counter=0; 
	if(fps==0) fps=72; 
	if(GetTime()-last_time>=1.0f) 
	{ 
		fps=counter; 
		counter=0; 
		last_time=GetTime(); 
	} 
	counter++;	 
	 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer 
	glLoadIdentity();									// Reset The Current Modelview Matrix 
	 
	EyeMove(); 
	gluLookAt(eyePosition[0], eyePosition[1], eyePosition[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 
//	cam.SetViewByMouse(); 
	//cam.CheckForMovement(); 
	//cam.Update(); 
	//cam.Look(); 
	CubeBox(); 
	if(state==0) 
		Reflection(); 
	if(state==1) 
		Refraction(); 
	if(state==2) 
		Dispersion(); 
 
	glLoadIdentity(); 
	glColor3f(1.0f, 1.0f, 1.0f); 
	glTranslatef(0.0f,0.0f,-1.0f);						// Move One Unit Into The Screen 
	glRasterPos2f(-0.52f, 0.36f); 
 	glPrint("Enviroment mapping demo");	// Print GL Text To The Screen 
	glRasterPos2f(-0.52f, 0.33f); 
	glPrint("1 - reflection effect"); 
	glRasterPos2f(-0.52f, 0.30f); 
	glPrint("2 - refraction effect"); 
	glRasterPos2f(-0.52f, 0.27f); 
	glPrint("3 - dispersion effect"); 
 
	glRasterPos2f(-0.52f, -0.30f); 
	glPrint("Renderer:%s", brand); 
	glRasterPos2f(-0.52f, -0.33f); 
	glPrint("Vendor:%s", vendor); 
	glRasterPos2f(-0.52f, -0.36f); 
	glPrint("Version:%s", version); 
 
	glRasterPos2f(0.38f, -0.37f); 
	glPrint("FPS:%d", fps); 
	 
	if(state==0) 
	{ 
		glRasterPos2f(0.10f, 0.36f); 
		glPrint("REFLECTION EFFECT"); 
	} 
	if(state==1) 
	{ 
		glRasterPos2f(0.10f, 0.36f); 
		glPrint("REFRACTION EFFECT"); 
	} 
	if(state==2) 
	{ 
		glRasterPos2f(0.10f, 0.36f); 
		glPrint("DISPERSION EFFECT"); 
	} 
 
	 
	return TRUE;										// Everything Went OK 
} 
 
GLvoid KillGLWindow(GLvoid)								// Properly Kill The Window 
{ 
	 
    cgDestroyProgram(g_CGreflection_vertex); 
	cgDestroyProgram(g_CGreflection_pixel); 
     
	cgDestroyProgram(g_CGrefraction_vertex); 
	cgDestroyProgram(g_CGrefraction_pixel); 
     
	cgDestroyProgram(g_CGdispersion_vertex); 
	cgDestroyProgram(g_CGdispersion_pixel); 
	 
	cgDestroyContext(g_CGcontext); 
	 
	 
	 
	 
	KillFont(); 
	if (fullscreen)										// Are We In Fullscreen Mode? 
	{ 
		ChangeDisplaySettings(NULL,0);					// If So Switch Back To The Desktop 
		ShowCursor(TRUE);								// Show Mouse Pointer 
	} 
 
	if (hRC)											// Do We Have A Rendering Context? 
	{ 
		if (!wglMakeCurrent(NULL,NULL))					// Are We Able To Release The DC And RC Contexts? 
		{ 
			MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); 
		} 
 
		if (!wglDeleteContext(hRC))						// Are We Able To Delete The RC? 
		{ 
			MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); 
		} 
		hRC=NULL;										// Set RC To NULL 
	} 
 
	if (hDC && !ReleaseDC(hWnd,hDC))					// Are We Able To Release The DC 
	{ 
		MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); 
		hDC=NULL;										// Set DC To NULL 
	} 
 
	if (hWnd && !DestroyWindow(hWnd))					// Are We Able To Destroy The Window? 
	{ 
		MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); 
		hWnd=NULL;										// Set hWnd To NULL 
	} 
 
	if (!UnregisterClass("OpenGL",hInstance))			// Are We Able To Unregister Class 
	{ 
		MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); 
		hInstance=NULL;									// Set hInstance To NULL 
	} 
} 
 
/*	This Code Creates Our OpenGL Window.  Parameters Are:					* 
 *	title			- Title To Appear At The Top Of The Window				* 
 *	width			- Width Of The GL Window Or Fullscreen Mode				* 
 *	height			- Height Of The GL Window Or Fullscreen Mode			* 
 *	bits			- Number Of Bits To Use For Color (8/16/24/32)			* 
 *	fullscreenflag	- Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE)	*/ 
  
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) 
{ 
	GLuint		PixelFormat;			// Holds The Results After Searching For A Match 
	WNDCLASS	wc;						// Windows Class Structure 
	DWORD		dwExStyle;				// Window Extended Style 
	DWORD		dwStyle;				// Window Style 
	RECT		WindowRect;				// Grabs Rectangle Upper Left / Lower Right Values 
	WindowRect.left=(long)0;			// Set Left Value To 0 
	WindowRect.right=(long)width;		// Set Right Value To Requested Width 
	WindowRect.top=(long)0;				// Set Top Value To 0 
	WindowRect.bottom=(long)height;		// Set Bottom Value To Requested Height 
 
	fullscreen=fullscreenflag;			// Set The Global Fullscreen Flag 
 
	hInstance			= GetModuleHandle(NULL);				// Grab An Instance For Our Window 
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	// Redraw On Size, And Own DC For Window. 
	wc.lpfnWndProc		= (WNDPROC) WndProc;					// WndProc Handles Messages 
	wc.cbClsExtra		= 0;									// No Extra Window Data 
	wc.cbWndExtra		= 0;									// No Extra Window Data 
	wc.hInstance		= hInstance;							// Set The Instance 
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon 
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer 
	wc.hbrBackground	= NULL;									// No Background Required For GL 
	wc.lpszMenuName		= NULL;									// We Don't Want A Menu 
	wc.lpszClassName	= "OpenGL";								// Set The Class Name 
 
	if (!RegisterClass(&wc))									// Attempt To Register The Window Class 
	{ 
		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;											// Return FALSE 
	} 
	 
	if (fullscreen)												// Attempt Fullscreen Mode? 
	{ 
		DEVMODE dmScreenSettings;								// Device Mode 
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	// Makes Sure Memory's Cleared 
		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure 
		dmScreenSettings.dmPelsWidth	= width;				// Selected Screen Width 
		dmScreenSettings.dmPelsHeight	= height;				// Selected Screen Height 
		dmScreenSettings.dmBitsPerPel	= bits;					// Selected Bits Per Pixel 
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; 
 
		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. 
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) 
		{ 
			// If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode. 
			if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) 
			{ 
				fullscreen=FALSE;		// Windowed Mode Selected.  Fullscreen = FALSE 
			} 
			else 
			{ 
				// Pop Up A Message Box Letting User Know The Program Is Closing. 
				MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP); 
				return FALSE;									// Return FALSE 
			} 
		} 
	} 
 
	if (fullscreen)												// Are We Still In Fullscreen Mode? 
	{ 
		dwExStyle=WS_EX_APPWINDOW;								// Window Extended Style 
		dwStyle=WS_POPUP;										// Windows Style 
		ShowCursor(FALSE);										// Hide Mouse Pointer 
	} 
	else 
	{ 
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style 
		dwStyle=WS_OVERLAPPEDWINDOW;							// Windows Style 
	} 
 
	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size 
 
	// Create The Window 
	if (!(hWnd=CreateWindowEx(	dwExStyle,							// Extended Style For The Window 
								"OpenGL",							// Class Name 
								title,								// Window Title 
								dwStyle |							// Defined Window Style 
								WS_CLIPSIBLINGS |					// Required Window Style 
								WS_CLIPCHILDREN,					// Required Window Style 
								0, 0,								// Window Position 
								WindowRect.right-WindowRect.left,	// Calculate Window Width 
								WindowRect.bottom-WindowRect.top,	// Calculate Window Height 
								NULL,								// No Parent Window 
								NULL,								// No Menu 
								hInstance,							// Instance 
								NULL)))								// Dont Pass Anything To WM_CREATE 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	static	PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be 
	{ 
		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor 
		1,											// Version Number 
		PFD_DRAW_TO_WINDOW |						// Format Must Support Window 
		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL 
		PFD_DOUBLEBUFFER,							// Must Support Double Buffering 
		PFD_TYPE_RGBA,								// Request An RGBA Format 
		bits,										// Select Our Color Depth 
		0, 0, 0, 0, 0, 0,							// Color Bits Ignored 
		0,											// No Alpha Buffer 
		0,											// Shift Bit Ignored 
		0,											// No Accumulation Buffer 
		0, 0, 0, 0,									// Accumulation Bits Ignored 
		16,											// 16Bit Z-Buffer (Depth Buffer)   
		0,											// No Stencil Buffer 
		0,											// No Auxiliary Buffer 
		PFD_MAIN_PLANE,								// Main Drawing Layer 
		0,											// Reserved 
		0, 0, 0										// Layer Masks Ignored 
	}; 
	 
	if (!(hDC=GetDC(hWnd)))							// Did We Get A Device Context? 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))	// Did Windows Find A Matching Pixel Format? 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	if(!SetPixelFormat(hDC,PixelFormat,&pfd))		// Are We Able To Set The Pixel Format? 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	if (!(hRC=wglCreateContext(hDC)))				// Are We Able To Get A Rendering Context? 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	if(!wglMakeCurrent(hDC,hRC))					// Try To Activate The Rendering Context 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	ShowWindow(hWnd,SW_SHOW);						// Show The Window 
	SetForegroundWindow(hWnd);						// Slightly Higher Priority 
	SetFocus(hWnd);									// Sets Keyboard Focus To The Window 
	ReSizeGLScene(width, height);					// Set Up Our Perspective GL Screen 
 
	if (!InitGL())									// Initialize Our Newly Created GL Window 
	{ 
		KillGLWindow();								// Reset The Display 
		MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION); 
		return FALSE;								// Return FALSE 
	} 
 
	return TRUE;									// Success 
} 
 
LRESULT CALLBACK WndProc(	HWND	hWnd,			// Handle For This Window 
							UINT	uMsg,			// Message For This Window 
							WPARAM	wParam,			// Additional Message Information 
							LPARAM	lParam)			// Additional Message Information 
{ 
	switch (uMsg)									// Check For Windows Messages 
	{ 
		case WM_ACTIVATE:							// Watch For Window Activate Message 
		{ 
			if (!HIWORD(wParam))					// Check Minimization State 
			{ 
				active=TRUE;						// Program Is Active 
			} 
			else 
			{ 
				active=FALSE;						// Program Is No Longer Active 
			} 
 
			return 0;								// Return To The Message Loop 
		} 
 
		case WM_SYSCOMMAND:							// Intercept System Commands 
		{ 
			switch (wParam)							// Check System Calls 
			{ 
				case SC_SCREENSAVE:					// Screensaver Trying To Start? 
				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave? 
				return 0;							// Prevent From Happening 
			} 
			break;									// Exit 
		} 
 
		case WM_CLOSE:								// Did We Receive A Close Message? 
		{ 
			PostQuitMessage(0);						// Send A Quit Message 
			return 0;								// Jump Back 
		} 
 
		case WM_KEYDOWN:							// Is A Key Being Held Down? 
		{ 
			keys[wParam] = TRUE;					// If So, Mark It As TRUE 
			return 0;								// Jump Back 
		} 
 
		case WM_KEYUP:								// Has A Key Been Released? 
		{ 
			keys[wParam] = FALSE;					// If So, Mark It As FALSE 
			return 0;								// Jump Back 
		} 
 
		case WM_SIZE:								// Resize The OpenGL Window 
		{ 
			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height 
			return 0;								// Jump Back 
		} 
	} 
 
	// Pass All Unhandled Messages To DefWindowProc 
	return DefWindowProc(hWnd,uMsg,wParam,lParam); 
} 
 
int WINAPI WinMain(	HINSTANCE	hInstance,			// Instance 
					HINSTANCE	hPrevInstance,		// Previous Instance 
					LPSTR		lpCmdLine,			// Command Line Parameters 
					int			nCmdShow)			// Window Show State 
{ 
	MSG		msg;									// Windows Message Structure 
	BOOL	done=FALSE;								// Bool Variable To Exit Loop 
 
	// Ask The User Which Screen Mode They Prefer 
	if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) 
	{ 
		fullscreen=FALSE;							// Windowed Mode 
	} 
 
	// Create Our OpenGL Window 
	if (!CreateGLWindow("www.azure.com",640,480,32,fullscreen)) 
	{ 
		return 0;									// Quit If Window Was Not Created 
	} 
 
	while(!done)									// Loop That Runs While done=FALSE 
	{ 
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))	// Is There A Message Waiting? 
		{ 
			if (msg.message==WM_QUIT)				// Have We Received A Quit Message? 
			{ 
				done=TRUE;							// If So done=TRUE 
			} 
			else									// If Not, Deal With Window Messages 
			{ 
				TranslateMessage(&msg);				// Translate The Message 
				DispatchMessage(&msg);				// Dispatch The Message 
			} 
		} 
		else										// If There Are No Messages 
		{ 
			// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene() 
			if (active)								// Program Active? 
			{ 
				if (keys[VK_ESCAPE])				// Was ESC Pressed? 
				{ 
					done=TRUE;						// ESC Signalled A Quit 
				} 
				else								// Not Time To Quit, Update Screen 
				{ 
					DrawGLScene();					// Draw The Scene 
					SwapBuffers(hDC);				// Swap Buffers (Double Buffering) 
				} 
			 
			 
				if (keys['1']) 
					state=0; 
				if (keys['2']) 
					state=1; 
				if (keys['3']) 
					state=2; 
			 
			} 
 
			 
		} 
	} 
 
	// Shutdown 
	KillGLWindow();									// Kill The Window 
	return (msg.wParam);							// Exit The Program 
}