outdated: 29.Blitter Function, RAW Texture Loading
在这篇中两个点。
一个是raw格式图片的贴图:
int ReadTextureData(char* filename, P_TEXTURE_IMAGE buffer) { FILE* f; int done = 0; int stride = buffer->width * buffer->format; unsigned char* p = NULL; f = fopen(filename, "rb"); if (f != NULL) { for (int i = buffer->height - 1; i >= 0; --i) { p = buffer->data + (i * stride); for (int j = 0; j < buffer->width; ++j) { for (int k = 0; k < buffer->format - 1; ++k, ++p, ++done) { *p = fgetc(f); } *p = 255; ++p; } } fclose(f); } else { MessageBox(NULL, "Unable To Open Image File", "IMAGE ERROR", MB_OK | MB_ICONINFORMATION); } return done; }
一个双重贴图即部分覆盖,图像数据,以及两个贴图的开始部分,范围以及模式是重点:
// Copy any section of a (src) texture and paste it into a destination (dst) texture void Blit(P_TEXTURE_IMAGE src, P_TEXTURE_IMAGE dst, int src_xstart, int src_ystart, int src_width, int src_height, int dst_xstart, int dst_ystart, int blend, int alpha) { unsigned char* s; unsigned char* d; // Source and destination // Clamp alpha if value is out of range if (alpha > 255) alpha = 255; if (alpha < 0) alpha = 0; // Check for incorrect blend flag values if (blend < 0) blend = 0; if (blend > 1) blend = 1; // Start row-dst (row * width in pixel * bytes per pixel) d = dst->data + (dst_ystart * dst->width * dst->format); s = src->data + (src_ystart * src->width * src->format); // Start row-src (row * width in pixel * bytes per pixel) for (int i = 0; i < src_height; ++i) { s = s + (src_xstart * src->format); // Move through src data by bytes per pixel d = d + (dst_xstart * dst->format); // Move through dst data by bytes per pixel for (int j = 0; j < src_width; ++j) { for (int k = 0; k < src->format; ++k, ++s, ++d) { if (blend) { // Multiply src data*alpha add dst data(255-alpha) *d = ((*s * alpha) + (*d * (255 - alpha))) >> 8; } else { // Keep in 0-255 range with >> 8 *d = *s; // No blending just do a straight copy } } } d = d + (dst->width - (src_width + dst_xstart)) * dst->format; s = s + (src->width - (src_width + src_xstart)) * src->format; } }
下面为代码,同样修改部分位于双行星号内。
1 /******************************************************************************************************************************************/ 2 /******************************************************************************************************************************************/ 3 #include <windows.h> 4 #include <math.h> 5 #include <stdio.h> 6 #include <gl/glew.h> 7 #include <GL\glut.h> 8 #include <GL/GLUAX.H> 9 #pragma comment(lib, "legacy_stdio_definitions.lib") 10 11 /* 12 * Every OpenGL program is linked to a Rendering Context. 13 * A Rendering Context is what links OpenGL calls to the Device Context. 14 * In order for your program to draw to a Window you need to create a Device Context. 15 * The DC connects the Window to the GDI (Graphics Device Interface). 16 */ 17 18 HGLRC hRC = NULL; // Permanent rendering context 19 HDC hDC = NULL; // Private GDI device context 20 HWND hWnd = NULL; // Holds our window handle 21 HINSTANCE hInstance; // Holds the instance of the application 22 23 /* 24 * It's important to make this global so that each procedure knows if 25 * the program is running in fullscreen mode or not. 26 */ 27 28 bool keys[256]; // Array used for the keyboard routine 29 bool active = TRUE; // Window active flag set to TRUE by default 30 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default 31 32 DEVMODE DMsaved; // Saves the previous sacreen settings 33 34 GLfloat xrot; 35 GLfloat yrot; 36 GLfloat zrot; 37 38 GLuint texture[1]; 39 40 typedef struct Texture_Image { 41 int width; 42 int height; 43 int format; // Number of bytes per pixel 44 unsigned char* data; 45 } TEXTURE_IMAGE; 46 47 typedef TEXTURE_IMAGE* P_TEXTURE_IMAGE; 48 49 P_TEXTURE_IMAGE t1; 50 P_TEXTURE_IMAGE t2; 51 52 53 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc 54 55 P_TEXTURE_IMAGE AllocateTextureBuffer(GLint w, GLint h, GLint f) 56 { 57 P_TEXTURE_IMAGE ti = NULL; 58 unsigned char* c = NULL; // Pointer to block memory for image 59 60 ti = (P_TEXTURE_IMAGE)malloc(sizeof(TEXTURE_IMAGE)); 61 if (ti != NULL) { 62 ti->width = w; 63 ti->height = h; 64 ti->format = f; 65 c = (unsigned char*)malloc(w * h * f); 66 if (c != NULL) { 67 ti->data = c; 68 } 69 else { 70 MessageBox(NULL, "Could Not Allocate Memory For A Texture Buffer", "BUFFER ERROR", MB_OK | 71 MB_ICONINFORMATION); 72 return NULL; 73 } 74 } 75 else { 76 MessageBox(NULL, "Could Not Allocate An Image Structure", "IMAGE STRUCTURE ERROR", MB_OK | 77 MB_ICONINFORMATION); 78 return NULL; 79 } 80 return ti; 81 } 82 83 void DeallocateTexture(P_TEXTURE_IMAGE t) 84 { 85 if (t) { 86 if (t->data) { 87 free(t->data); 88 } 89 free(t); 90 } 91 } 92 93 int ReadTextureData(char* filename, P_TEXTURE_IMAGE buffer) 94 { 95 FILE* f; 96 int done = 0; 97 int stride = buffer->width * buffer->format; 98 unsigned char* p = NULL; 99 100 f = fopen(filename, "rb"); 101 if (f != NULL) { 102 for (int i = buffer->height - 1; i >= 0; --i) { 103 p = buffer->data + (i * stride); 104 for (int j = 0; j < buffer->width; ++j) { 105 for (int k = 0; k < buffer->format - 1; ++k, ++p, ++done) { 106 *p = fgetc(f); 107 } 108 *p = 255; 109 ++p; 110 } 111 } 112 fclose(f); 113 } 114 else { 115 MessageBox(NULL, "Unable To Open Image File", "IMAGE ERROR", MB_OK | MB_ICONINFORMATION); 116 } 117 return done; 118 } 119 120 void BuildTexture(P_TEXTURE_IMAGE tex) 121 { 122 glGenTextures(1, &texture[0]); 123 glBindTexture(GL_TEXTURE_2D, texture[0]); 124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 126 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, tex->width, tex->height, GL_RGBA, GL_UNSIGNED_BYTE, 127 tex->data); 128 } 129 // Copy any section of a (src) texture and paste it into a destination (dst) texture 130 void Blit(P_TEXTURE_IMAGE src, P_TEXTURE_IMAGE dst, int src_xstart, int src_ystart, int src_width, 131 int src_height, int dst_xstart, int dst_ystart, int blend, int alpha) 132 { 133 unsigned char* s; 134 unsigned char* d; // Source and destination 135 136 // Clamp alpha if value is out of range 137 if (alpha > 255) alpha = 255; 138 if (alpha < 0) alpha = 0; 139 // Check for incorrect blend flag values 140 if (blend < 0) blend = 0; 141 if (blend > 1) blend = 1; 142 // Start row-dst (row * width in pixel * bytes per pixel) 143 d = dst->data + (dst_ystart * dst->width * dst->format); 144 s = src->data + (src_ystart * src->width * src->format); 145 // Start row-src (row * width in pixel * bytes per pixel) 146 for (int i = 0; i < src_height; ++i) { 147 s = s + (src_xstart * src->format); // Move through src data by bytes per pixel 148 d = d + (dst_xstart * dst->format); // Move through dst data by bytes per pixel 149 for (int j = 0; j < src_width; ++j) { 150 for (int k = 0; k < src->format; ++k, ++s, ++d) { 151 if (blend) { 152 // Multiply src data*alpha add dst data(255-alpha) 153 *d = ((*s * alpha) + (*d * (255 - alpha))) >> 8; 154 } 155 else { // Keep in 0-255 range with >> 8 156 *d = *s; // No blending just do a straight copy 157 } 158 } 159 } 160 d = d + (dst->width - (src_width + dst_xstart)) * dst->format; 161 s = s + (src->width - (src_width + src_xstart)) * src->format; 162 } 163 } 164 /******************************************************************************************************************************************/ 165 /******************************************************************************************************************************************/ 166 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize and initialize the GL window 167 { 168 if (height == 0) { // Prevent a divide by zero by 169 height = 1; // Making height equal one 170 } 171 172 glViewport(0, 0, width, height); // Reset the current viewport 173 174 /* 175 * The following lines set the screen up for a perspective view. 176 * Meaning things in the distance get smaller. This creates a realistic looking scene. 177 * The perspective is calculated with a 45 degree viewing angle based on 178 * the windows width and height. The 0.1f, 100.0f is the starting point and 179 * ending point for how deep we can draw into the screen. 180 * 181 * The projection matrix is responsible for adding perspective to our scene. 182 * glLoadIdentity() restores the selected matrix to it's original state. 183 * The modelview matrix is where our object information is stored. 184 * Lastly we reset the modelview matrix. 185 */ 186 187 glMatrixMode(GL_PROJECTION); // Select the projection matrix 188 glLoadIdentity(); // Reset the projection matrix 189 190 // Calculate the aspect ratio of the window 191 gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 192 // glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f); // Create orhto 640X480 view (0, 0, at the top) 193 194 glMatrixMode(GL_MODELVIEW); // Seclet the modelview matrix 195 glLoadIdentity(); // Reset the modelview matrix 196 } 197 /******************************************************************************************************************************************/ 198 /******************************************************************************************************************************************/ 199 200 int InitGL(GLvoid) // All setup for OpenGL goes here 201 { 202 t1 = AllocateTextureBuffer(256, 256, 4); 203 if (ReadTextureData("Data/Monitor.raw", t1) == 0) { 204 MessageBox(NULL, "Could Not Read 'Monitor.raw' Image Data", "TEXTURE ERROR", MB_OK | MB_ICONINFORMATION); 205 return false; 206 } 207 t2 = AllocateTextureBuffer(256, 256, 4); 208 if (ReadTextureData("Data/GL.raw", t2) == 0) { 209 MessageBox(NULL, "Could Not Read 'GL.raw' Image Data", "TEXTURE ERROR", MB_OK | MB_ICONINFORMATION); 210 return false; 211 } 212 213 // Image to blend in, original image, src start X & Y, src width & height, 214 // dst location X & Y, blend flag, alpha value 215 Blit(t2, t1, 127, 127, 128, 128, 64, 64, 1, 127); 216 217 BuildTexture(t1); 218 219 DeallocateTexture(t1); 220 DeallocateTexture(t2); 221 222 glEnable(GL_TEXTURE_2D); 223 glShadeModel(GL_SMOOTH); 224 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background 225 glClearDepth(1.0f); // Depth buffer setup 226 glEnable(GL_DEPTH_TEST); 227 glDepthFunc(GL_LESS); 228 229 return TRUE; 230 } 231 232 /* 233 * For now all we will do is clear the screen to the color we previously decided on, 234 * clear the depth buffer and reset the scene. We wont draw anything yet. 235 */ 236 bool DrawGLScene(GLvoid) // Here's where we do all the drawing 237 { 238 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 239 240 glLoadIdentity(); 241 glTranslatef(0.0f, 0.0f, -5.0f); 242 glRotatef(xrot, 1.0f, 0.0f, 0.0f); 243 glRotatef(yrot, 1.0f, 0.0f, 0.0f); 244 glRotatef(zrot, 0.0f, 0.0f, 1.0f); 245 246 glBindTexture(GL_TEXTURE_2D, texture[0]); 247 glBegin(GL_QUADS); 248 // Front face 249 glNormal3f(0.0f, 0.0f, 1.0f); 250 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); 251 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); 252 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); 253 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); 254 // Back face 255 glNormal3f(0.0f, 0.0f, -1.0f); 256 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); 257 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); 258 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); 259 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 260 // Top face 261 glNormal3f(0.0f, 1.0f, 0.0f); 262 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); 263 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); 264 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); 265 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); 266 // Bottom face 267 glNormal3f(0.0f, -1.0f, 0.0f); 268 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); 269 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); 270 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 271 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); 272 // Right face 273 glNormal3f(1.0f, 0.0f, 0.0f); 274 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); 275 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); 276 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); 277 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); 278 // Left face 279 glNormal3f(-1.0f, 0.0f, 0.0f); 280 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 281 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); 282 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); 283 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); 284 glEnd(); 285 286 xrot += 0.03f; 287 yrot += 0.02f; 288 zrot += 0.04f; 289 return true; 290 } 291 292 /* 293 * The job of KillGLWindow() is to release the Rendering Context, 294 * the Device Context and finally the Window Handle. 295 */ 296 297 GLvoid KillGLWindow(GLvoid) // Properly kill the window 298 { 299 if (fullscreen) { // Are we in fullscreen mode 300 if (!ChangeDisplaySettings(NULL, CDS_TEST)) { // If the shortcut doesn't work 301 ChangeDisplaySettings(NULL, CDS_RESET); // Do it anyway (to get the values out of the registry) 302 ChangeDisplaySettings(&DMsaved, CDS_RESET); 303 } 304 else { 305 ChangeDisplaySettings(NULL, CDS_RESET); // If so switch back to the desktop 306 } 307 //******************************************************************************************************************************************/ 308 //******************************************************************************************************************************************/ 309 /* 310 * We use ChangeDisplaySettings(NULL,0) to return us to our original desktop. 311 * After we've switched back to the desktop we make the cursor visible again. 312 */ 313 ShowCursor(TRUE); // Show mouse pointer 314 } 315 316 if (hRC) { // Do we have a rendering context 317 if (!wglMakeCurrent(NULL, NULL)) { // Are we able to release the DC and RC contexts 318 MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 319 } 320 321 if (!wglDeleteContext(hRC)) { // Are we able to delete the RC 322 MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 323 hRC = NULL; // Set RC to NULL 324 } 325 326 if (hDC && !ReleaseDC(hWnd, hDC)) { // Are we able to release the DC 327 MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 328 hDC = NULL; // Set DC to NULL 329 } 330 if (hWnd && !DestroyWindow(hWnd)) { // Are we able to destroy the window 331 MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 332 hWnd = NULL; // Set hWnd to NULL 333 } 334 335 if (!UnregisterClass("OpenGL", hInstance)) { // Are we able to unregister class 336 MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 337 hInstance = NULL; // Set hInstance to NULL 338 } 339 } 340 } 341 /* 342 * The next section of code creates our OpenGL Window. 343 */ 344 345 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) 346 { 347 /* 348 * Find a pixel format that matches the one we want 349 */ 350 GLuint PixelFormat; // Holds the result after serching for a match 351 352 /* 353 * Before you create a window, you MUST register a Class for the window 354 */ 355 WNDCLASS wc; // Windows class structure 356 357 /* 358 * dwExStyle and dwStyle will store the Extended and normal Window Style Information. 359 */ 360 DWORD dwExStyle; // Window extend style 361 DWORD dwStyle; // Window style 362 363 364 RECT WindowRect; // Grabs rectangle upper left/lower right values 365 WindowRect.left = (long)0; // Set left value to 0 366 WindowRect.right = (long)width; // Set right value to requested width 367 WindowRect.top = (long)0; // Set top value to 0 368 WindowRect.bottom = (long)height; // Set bottom value to requested height 369 370 fullscreen = fullscreenflag; // Set the global fullscreen flag 371 372 /* 373 * The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 374 * CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 375 * WndProc is the procedure that watches for messages in our program. 376 * No extra Window data is used so we zero the two fields. Then we set the instance. 377 * Next we set hIcon to NULL meaning we don't want an ICON in the Window, 378 * and for a mouse pointer we use the standard arrow. The background color doesn't matter 379 * (we set that in GL). We don't want a menu in this Window so we set it to NULL, 380 * and the class name can be any name you want. I'll use "OpenGL" for simplicity. 381 */ 382 hInstance = GetModuleHandle(NULL); // Grab an instance for our window 383 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on move, and own DC for window 384 wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc handles message 385 wc.cbClsExtra = 0; // No extra window date 386 wc.cbWndExtra = 0; // No extra window date 387 wc.hInstance = hInstance; // set the instance 388 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load the default icon 389 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer 390 wc.hbrBackground = NULL; // No background requried for GL 391 wc.lpszMenuName = NULL; // We don't want a menu 392 wc.lpszClassName = "OpenGL"; // set the class name 393 394 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DMsaved); // Save the current display state 395 396 if (!RegisterClass(&wc)) { // Attempt to register the window class 397 MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 398 return FALSE; // Exit and return false 399 } 400 401 if (fullscreen) { // attempt fullsreen model 402 403 /* 404 T* here are a few very important things you should keep in mind when switching to full screen mode. 405 * Make sure the width and height that you use in fullscreen mode is the same as 406 * the width and height you plan to use for your window, and most importantly, 407 * set fullscreen mode BEFORE you create your window. 408 */ 409 DEVMODE dmScreenSettings; // Device mode 410 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared 411 dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size of devmode structure 412 dmScreenSettings.dmPelsWidth = width; // Select window width 413 dmScreenSettings.dmPelsHeight = height; // Select window height 414 dmScreenSettings.dmBitsPerPel = bits; // Select bits per pixel 415 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 416 417 /* 418 * In the line below ChangeDisplaySettings tries to switch to a mode that matches 419 * what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 420 * because it's supposed to remove the start bar at the bottom of the screen, 421 * plus it doesn't move or resize the windows on your desktop when you switch to 422 * fullscreen mode and back. 423 */ 424 //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar 425 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { 426 //If the mode fails, offer two options. Quit or run in a window 427 if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use" 428 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) 429 { 430 fullscreen = FALSE; // Select windowed mode (fullscreen=FLASE) 431 } 432 else { 433 // Pop up a message box letting user know the programe is closing. 434 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP); 435 return FALSE; // Exit and return FALSE 436 } 437 } 438 } 439 440 if (fullscreen) { // Are we still in fullscreen mode 441 442 /* 443 * If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 444 * which force a top level window down to the taskbar once our window is visible. 445 * For the window style we'll create a WS_POPUP window. 446 * This type of window has no border around it, making it perfect for fullscreen mode. 447 448 * Finally, we disable the mouse pointer. If your program is not interactive, 449 * it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though. 450 */ 451 dwExStyle = WS_EX_APPWINDOW; // Window extended style 452 dwStyle = WS_POPUP; // Window style 453 ShowCursor(FALSE); // Hide mosue pointer 454 } 455 else { 456 457 /* 458 * If we're using a window instead of fullscreen mode, 459 * we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 460 * For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 461 * WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 462 * window menu, and minimize / maximize buttons. 463 */ 464 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style 465 dwStyle = WS_OVERLAPPEDWINDOW; // Window style 466 } 467 468 /* 469 * By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 470 * instead, the window will be made larger to account for the pixels needed to draw the window border. 471 * In fullscreen mode, this command has no effect. 472 */ 473 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust window to true resqusted 474 475 /* 476 * WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 477 * These styles prevent other windows from drawing over or into our OpenGL Window. 478 */ 479 if (!(hWnd = CreateWindowEx(dwExStyle, // Extended style for the window 480 "OpenGL", // Class name 481 title, // Window title 482 WS_CLIPSIBLINGS | // Requried window style 483 WS_CLIPCHILDREN | // Requried window style 484 dwStyle, // Select window style 485 0, 0, // Window position 486 WindowRect.right - WindowRect.left, // Calculate adjusted window width 487 WindowRect.bottom - WindowRect.top, // Calculate adjusted window height 488 NULL, // No parent window 489 NULL, // No menu 490 hInstance, // Instance 491 NULL))) // Don't pass anything to WM_CREATE 492 { 493 KillGLWindow(); //Reset the display 494 MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 495 return FALSE; // Retrurn FALSE; 496 } 497 498 /* 499 * aside from the stencil buffer and the (slow) accumulation buffer 500 */ 501 static PIXELFORMATDESCRIPTOR pfd = // pfd tells windows how we want things to be 502 { 503 sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 504 1, // Version number 505 PFD_DRAW_TO_WINDOW | // Format must support window 506 PFD_SUPPORT_OPENGL | // Format must support OpenGL 507 PFD_DOUBLEBUFFER, // Must support double buffer 508 PFD_TYPE_RGBA, // Request an RGBA format 509 bits, // Select our color depth 510 0, 0, 0, 0, 0, 0, // Color bits ignored 511 0, // No alpha buffer 512 0, // shift bit ignored 513 0, // No accumulation buffer 514 0, 0, 0, 0, // Accumulation bits ignored 515 16, // 16Bits Z_Buffer (depth buffer) 516 0, // No stencil buffer 517 0, // No auxiliary buffer 518 PFD_MAIN_PLANE, // Main drawing layer 519 0, // Reserved 520 0, 0, 0 // Layer makes ignored 521 }; 522 523 if (!(hDC = GetDC(hWnd))) { // Did we get a device context 524 KillGLWindow(); // Reset the display 525 MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 526 return FALSE; // Return FALSE 527 } 528 529 if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { // Did window find a matching pixel format 530 KillGLWindow(); // Reset the display 531 MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 532 return FALSE; // Return FALSE; 533 } 534 535 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { // Are we able to set the pixel format 536 KillGLWindow(); // Reset the display 537 MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 538 return FALSE; // Return FALSE; 539 } 540 541 if (!(hRC = wglCreateContext(hDC))) { // Are we able to rendering context 542 KillGLWindow(); // Reset the display 543 MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 544 return FALSE; // Return FASLE; 545 } 546 547 if (!wglMakeCurrent(hDC, hRC)) { // Try to activate the rendering context 548 KillGLWindow(); // Reset the display 549 MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 550 return FALSE; // Return FALSE 551 } 552 553 /* 554 * ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen. 555 */ 556 ShowWindow(hWnd, SW_SHOW); // Show the window 557 SetForegroundWindow(hWnd); // slightly higher priority 558 SetFocus(hWnd); // Sets keyboard focus to the window 559 ReSizeGLScene(width, height); // Set up our perspective GL screen 560 561 /* 562 * we can set up lighting, textures, and anything else that needs to be setup in InitGL(). 563 */ 564 if (!InitGL()) { // Initialize our newly created GL window 565 KillGLWindow(); // Reset the display 566 MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 567 return FALSE; // Return FALSE 568 } 569 return TRUE; 570 } 571 572 LRESULT CALLBACK WndProc(HWND hWnd, // Handle for this window 573 UINT uMsg, // Message for this window 574 WPARAM wParam, // Additional message information 575 LPARAM lParam) // Additional message information 576 { 577 switch (uMsg) { // Check for window message 578 case WM_ACTIVATE: { // Check minimization state 579 if (!HIWORD(wParam)) { 580 active = TRUE; // Program is active 581 } 582 else { 583 active = FALSE; // Program is no longer active 584 } 585 return 0; // Return to the message loop 586 } 587 case WM_SYSCOMMAND: { // Intercept system commands 588 switch (wParam) { // Check system calls 589 case SC_SCREENSAVE: // Screensaver trying to start 590 case SC_MONITORPOWER: // Monitor trying to enter powersave 591 return 0; // Prevent form happening 592 } 593 break; // Exit 594 } 595 case WM_CLOSE: { // Did we receive a close message 596 PostQuitMessage(0); // Send a quit message 597 return 0; 598 } 599 case WM_KEYDOWN: { // Is a key being held down 600 keys[wParam] = TRUE; // if so, mark it as TRUE 601 return 0; // Jump back 602 } 603 case WM_KEYUP: { // Has a key been released 604 keys[wParam] = FALSE; // if so, mark it as FALSE 605 return 0; // Jump back 606 } 607 case WM_SIZE: { // Resize the OpenGL window 608 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord = width HiWord = height 609 return 0; // Jump back 610 } 611 } 612 return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass all unhandled message to DefWindwProc 613 } 614 615 int WINAPI WinMain(HINSTANCE hInstance, // Instance 616 HINSTANCE hPrevInstance, // Previous instance 617 LPSTR lpCmdLine, // Command line parameters 618 int nCmdShow) // Window show state 619 { 620 MSG msg; // Window message structure 621 BOOL done = FALSE; // Bool variable to exit loop 622 // Ask the user which screen mode they prefer 623 if (MessageBox(NULL, "Would you like to run in fullscreen mode?", 624 "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) 625 { 626 fullscreen = FALSE; // Window mode 627 } 628 // Create our OpenGL window 629 if (!CreateGLWindow("3D Shapes", 800, 600, 32, fullscreen)) { // (Modified) 630 return 0; // Quit if window was not create 631 } 632 while (!done) { // Loop that runs until donw = TRUE 633 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Is there a message wating 634 if (msg.message == WM_QUIT) { // Havw we received a quit message 635 done = TRUE; // if so done = TRUE 636 } 637 else { // If not, deal with window message 638 TranslateMessage(&msg); // Translate message 639 DispatchMessage(&msg); // Dispatch message 640 } 641 } 642 else { 643 // Draw the scene. Watch for ESC key and quit message from DrawGLScene() 644 if (active) { // Program active 645 if (keys[VK_ESCAPE]) { // Was ESC pressed 646 done = TRUE; // ESC signalled a quit 647 } 648 else { // Not time to quit, update screen 649 DrawGLScene(); // Draw scene 650 SwapBuffers(hDC); // Swap buffers (double buffering) 651 //******************************************************************************************************************************************/ 652 //******************************************************************************************************************************************/ 653 } 654 } 655 //******************************************************************************************************************************************/ 656 //******************************************************************************************************************************************/ 657 658 /* 659 * It allows us to press the F1 key to switch from fullscreen mode to 660 * windowed mode or windowed mode to fullscreen mode. 661 */ 662 if (keys[VK_F1]) { // Is F1 being pressed 663 keys[VK_F1] = FALSE; // If so make key FASLE 664 KillGLWindow(); // Kill our current window 665 fullscreen = !fullscreen; // Toggle fullscreen / window mode 666 //Recreate our OpenGL window(modified) 667 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { 668 return 0; // Quit if window was not create 669 } 670 } 671 } 672 } 673 // Shutdown 674 KillGLWindow(); // Kill the window 675 return (msg.wParam); // Exit the program 676 }
Thanks for Nehe's tutorials, this is his home.