Novice: Jeff Molofee (Nehe) OpenGL Tutorial - The first lesson

zhaozj2021-02-08  239

Jeff Molofee (nehe) OpenGL Tutorial The first lesson translated by cker {translated: Nehe's tutorial has more than 30 lessons, informative content, and continuously updated. The domestic website is really going to learn. Surprisingly, the routine source code provided by Nehe has different cross-platform different compilation, involving Visual C , Borland C , Visual Basic, Macos X / Glut, Linux / GLX, Code Warrior, Delphi, C Builder, Multiple compilers under different platforms of MASM, ASM, MingW32 & Allegro, and Python, etc. This seems to have never been seen in the Big Big book on the domestic market. Regarding OpenGL, it was the first 3D graphic hardware interface developed by SGI cross-platform industrial standards, with Microsoft's Direct X, not to blow more. Because CKER is just amateur level, there is a need to correct the translation of OpenGL's special terms, please add more correct. I am formatted in the resolution of 1024x768. It is estimated that the deformation is very variant, it is really not good, I'm doing the website! In addition, you should want to run a smooth running routine, your loving machine should be strong enough, the memory should be large enough, but also support 3D hardware accelerated graphics card, TNT always should:) ....... The first lesson Some simple, but this is the framework of almost all OpenGL routines of NEHE. He is too nonsense, but it is not wrong. Welcome to my OpenGL tutorial. I am an ordinary boy who is passionate for OpenGL! I first heard that OpenGL is an OpenGL hardware accelerated driver for 3DFX publishing a VODOO1 card. I immediately realized that OpenGL is the thing that must be learned. Unfortunately, it is difficult to find information about OpenGL from books or networks. I spent N hours to debug your own writing code, even more time to get someone else in IRC and Email. But I found some OpenGL experts to keep their essence, and I am not interested in sharing knowledge. It is really discouraged! I created this website to help people who are interested in OpenGl but need help. In each tutorial, I will explain the role of each line of code as detailed. I will try to make my code easier (you don't have to learn MFC code)! Even if you are a VC, OpenGL's absolute novice should also be able to read the code, and know what happened. My site is just a lot of sites that offer the OpenGL tutorial. If you are an OpenGL's advanced programmer, my site may be too simple, but if you start, I think this site will teach you many things! This section of the tutorial has been thoroughly renovated in January 2000. Will teach you how to set up an OpenGL window. It can be just a window or a full screen, which can be arbitrarily, arbitrary color depth. The code here is very stable and very powerful, you can use in all your OpenGL projects. All my tutorial will be based on this code! All errors have been reported. So there should be no memory leak, and the code is also easy to read and modified. Thank Fredric Echols to modify the code! Let us start from the code directly. The first thing is to open the VC and create a new project. If you don't know how to create, you may not learn OpenGL, but you should learn VC. The code available for download is VC6. Some versions of VC need to change BOOL to bool, true change to true, false changes to false, please modify itself. I compiled these code with VC4 and VC5 and did not find problems.

After you create a new Win32 program (not a console console program), you also need to link the OpenGL library file. The operation is in the VC as follows: Project> Settings, and then click the Link tab. At the beginning of the "Object / Library Modules" option (before kernel32.lib), add OpenGL32.lib Glu32.lib and GLAUX.LIB, click the OK button. You can now start writing your OpenGL program. The first 4 lines of the code include the header file of each library file we use. As shown below: #include #include #include #include // windows header file // OpenGL32 library head The file // GLU32 library header file // GLAUX library header file Next You need to set all the variables you plan to use in your program. The routines in this section will create an empty OpenGL window, so we do not need to set a large pile of variables. There are not many variables that need to be set, but it is very important. You will use them in every OpenGL program you wrote later. The variables set in the first line are rendering context (Color Description Table). Each OpenGL is connected to a coloring description table. Color Description Table Connects all OpenGL calls commands to the Device Context. I defined OpenGL's coloring description table as HRC. To make your program to draw a window, you need to create a device descriptor, which is the content of the second line. Windows Device Description Table is defined as HDC. DC connects the window to the GDI (Graphics Device Interface graphics). The RC connects OpenGL to the DC. The variable of the third line hWnd will save the handle assigned by Windows to our window. Finally, the fourth behavior created an instance (instance). HGLRC HRC = NULL; HDC HDC = NULL; HWND HWND = NULL; Hinstance Hinstance; // Permanent Color Description Table // Private GDI Device Description Table / / Save Our Window Handle / / Save Procedure Example The first line setting below A array used to monitor keyboard actions. There are many ways to monitor the action of the keyboard, but the method here is very reliable, and multiple keys can be processed simultaneously. The Active variable is used to inform the program window to minimize the state. If the window is minimized, we can do anything from the pause code to the exit program. I like to pause the program. This makes the program not to remain in the background. The effect of Fullscreen variable is quite obvious. If our program runs in full-screen, FullScreen's value is true, otherwise false. This global variable is important, which makes each process know if the program is running in full screen. Bool Keys [256]; BOOL ACTIVE = true; bool fullscreen = true; // Active flag for the array // window of the keyboard routine, default to true // full screen logo default settings to full screen mode Now we need Define WndProc first. The reason that must be done is that CreateGLWindow () has a reference to WndProc (), but WndProc () appears after CreateGLWindow (). In the C language, if we want to access the process and program segment after a current block, you must first state the program segment to be accessed first. So the following line code defines WndProc (), making CreateGLWindow () can reference WndProc ().

LRESULT CALLBACK WNDPROC (HWND, UINT, WPARAM, LPARAM) Even you can't change the size of the window (for example, in full screen mode), it will still run once - set our perspective at the beginning of the program. The size of the OpenGL scene will be set to the size of the window in which it is displayed. Glvoid Resizeglscene (Glsizei Width, Glsizei Height) {if (Height == 0) {height = 1;} GLVIEWPORT (0, 0, Width, Height); // Reset and initialize the GL window size / / Prevent zero-free / / Set the Height to 1 // Reset the current viewport below to set the screen. It means that the farther things look smaller. Do this created a realistic scene. Here, perspective is calculated according to the 45 degree view of the window width and height. 0.1f, 100.0f is the starting and end point of our depth in the scene. Glmatrixmode (GL_Projection) indicates that the next two lines of code will affect the Projection Matrix. The projection matrix is ​​responsible for increasing perspective for our scene. GLLoadIdentity () is similar to reset. It restores the selected matrix state into its original state. After calling GLLoadIdentity (), we set a perspective for the scene. Glmatrixmode (GL_ModelView) indicates that any new transformation will affect ModelView Matrix. Our object messages are stored in the model observation matrix. Finally we reset the model observation matrix. If you can't understand the meaning of these terms, please don't worry. In the later tutorial, I will explain to you. Just know if you want to get a wonderful perspective scene, you must do this. glMatrixMode (GL_PROJECTION); glLoadIdentity (); // calculate the ratio of appearance of the window gluPerspective (45.0f, (GLfloat) width / (GLfloat) height, 0.1f, 100.0f); glMatrixMode (GL_MODELVIEW); glLoadIdentity ();} // Select Projection Matrix // Reset Projection Matrix // Select Model Observation Matrix // Reset Model Observation Matrix Next Code Segment, we will make all settings for OpenGL. We will set the color used to clear the screen, turn on the depth cache, enable smooth shading, and so on. This routine will be called until the OpenGL window is created. This process will have a return value. But our initialization here is not so complicated, and now there is no need to worry about this return value. INT INITGL (GLVOID) {// begins with OpenGL all settings to OpenGL. SMOoth Shading is enabled. Shadow is smooth through the fine mixed colors of polygons and smooth external light. I will explain more detailed explanation in another tutorial. Glshademodel (GL_SMOOTH); // Enables shadow smooth next line settings to clear the color used when the screen is cleared. If you are unclear about the working principle of the color, I quickly explain it. The range of color values ​​range from 0.0F to 1.0F. 0.0F represents the most dark situation, 1.0f is the brightest situation. The first parameter after GlclearColor is Red INTENSITY, the second is green, the third is blue. The maximum value is also 1.0f, represents the brightest situation of a specific color component. The last parameter is an alpha value. When it is used to clear the screen, we don't have to care about the fourth number. Now let it be 0.0F. I will use another tutorial to explain this parameter. You can get different colors by mixing three primary colors (red, green, blue). I hope you have learned these in schools.

Therefore, when you use GlclearColor (0.0F, 0.0F, 1.0F, 0.0F), you will use bright blue to clear the screen. If you use GlclearColor (0.5F, 0.0F, 0.0F, 0.0F), you will use the red to clear the screen. Not the brightest (1.0F), nor is the secret (0.0F). To get a white background, you should set all the colors to the brightest (1.0F). To make a black background, you should set all the colors to the darker (0.0F). GlclearColor (0.0F, 0.0F, 0.0F, 0.0F); // The next three lines of black background must be done with the depth buffer. Depending on the depth cache as the layer behind the screen. The depth cache is constantly tracked on the object into the screen. Our program in this section does not actually use depth caching, but almost all on the screen display 3D scene OpenGL programs use depth cache. Its sort determines the object to draw first. This way you will not paint on a circular square to a circle. The depth cache is an important part of OpenGL. GLCLEARDEPTH; GLENABLE (GL_DEPTH_TEST); GLDEPTHFUNC (GL_LEQUAL); // Setting Depth Cache // Enables Depth Test // The type of depth test is then told OpenGL We want to make the best perspective correction. This will be very slightly influenced. But make perspective look good. GLHINT (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // True Fine Perspective Correction Finally, let's return true. If we want to check if the initialization is OK, we can view the value of the returned TRUE or FALSE. If you have any errors, you can add your own code to return false. At present, we don't care about it. Return True;} // Initialization OK Next paragraph includes all drawing code. Any Dongdong that you want to display on the screen will appear in this code. I will add new code here in each tutorial in the future. If you have an understanding of OpenGL, you can return to the TRUE value before you return to the TRUE value to create a basic shape before returning the TRUE value after the GLLoadIdentity () call. If you are OpenGL newbie, wait for my next tutorial. All we have made is to clear the screen into the color determined in front, clear depth caching and reset the scene. We still have not drawn any stuff. Returns the True value to inform us that there is no problem. If you want the program to stop running because some reasons, add the code to return false before returning the TRUE value to inform our program drawing code error. The program is about to exit. INT Drawglscene (GLVOID) {GLCLORAR (GL_COLOR_BUFFER_BIT); GLLOADIDENTITY (); Return True;} // From here, all draw // Clear screen and depth cache // Reset the current model observation matrix // all OK The next code is only called before the program exits. The role of killglwindow () is to release color description tables, device descriptive tables, and window handles sequentially. I have already added a lot of wrong checks. If the program cannot destroy the arbitrary section of the window, the message window with the corresponding error message will pop up, tell you something wrong. Make you check the error in your code easier. GLVOID KILLGLWINDOW (GLVOID) {// Normal Destruction Window Our first thing to do in KillGlWindow () is to check if we are in full screen mode. If so, we have to switch back to the desktop. We should first destroy the window before disabling full-screen mode, but doing this on some graphics cards can cause desktops to crash. So we still disable full screen mode.

This will prevent the desktop crashes and work very well on NVIDIA and 3DFX graphics cards! IF (fullscreen) {// we are in full screen mode? We use ChangeDisplaySettings (NULL, 0) to return to the original desktop. Use null as the first parameter, 0 as the second parameter transfer Forced Windows uses the value currently stored in the registry (default resolution, color depth, refresh frequency, etc.) to effectively restore our original desktop . After switching back to the desktop, we have to re-visible mouse pointers. ChangeDisplaySettings (NULL, 0); showcursor (TRUE);} // Yes, switch back to desktop // Show mouse pointer Next code to see if we have coloring description table (HRC). If not, the program will jump to the back code to see if there is a device descriptor. IF (hrc) {// We have coloring description table? If there is a coloring description table, the following code will look at whether we can release it (separated from HRC from HDC). Here, please pay attention to the error method I use. Basically I just let the program tries to release color description table (by calling WGLmakecurrent (Null, Null), then I will review whether it is successful. The smartly binds the digital code to a line. If (! WGLmakecurrent (null)) { / / Can we release the DC and RC description table? If you cannot release the DC and RC description tables, MessageBox () will pop up the error message, tell us that DC and RC cannot be released. Null means that the message window does not have a parent window. The text will appear on the message window. "Shutdown Error" appears on the title bar of the window. MB_OK's Message window with a button written to the OK word. MB_ICONInInformation will display a circled lowercase in the message window. i (look more formal). MessageBox (NULL, "Release Of DC And Rc Failed.", "Shutdown Error", MB_OK | MB_ICONIOMATION);} Next We tried to delete coloring description table. If you don't succeed, pop up error Message. If (! WgldeleteContext (HRC)) {// Can we delete the RC? If you can't delete the coloring description table, the error message will be popped up to inform us that the RC cannot be successfully deleted. Then HRC is set to null. MessageBox (null, "Release Rendering Context Failed.", "Shutdown Error", MB_OK | MB_ICONICONFORMATION;} hrc = null; // Set the RC to null} Now we look at whether there is a device descriptor, if you try to release it. If you can't release the device Description Table will pop up an error message and then HDC is set to NULL.

IF (HDC &&! ReleaseDC (HWND, HDC)) // We can release DC? {MessageBox (Null, "Release Device Context Failed.", "Shutdown Error", MB_OK | MB_ICONICONFORMATION; HDC = NULL; // DC is set to null} Now let's see if there is a window handle, we call DESTROYWINDOW (hwnd) to try to destroy the window. If you can't pop up the error window, then hwnd is set to NULL. IF (hwnd &&! destroywindow (hwnd)) / / Can destroy the window {MessageBox (Null, "Could Not Release Hwnd.", "Shutdown Error", MB_OK | MB_ICONIONFORMATION); hWnd = null; // Set HWND to Null} The last thing to do is to log out of our window classes. This allows us to destroy the window normally, followed by the other window, does not receive an error message such as "Windows Class Already Registered" (window class registration). IF ("" "" "" "" "" " Set to NULL}} The next code segment creates our OpenGL window. I spent a lot of time to make a decision to create a fixed full-screen mode such as many additional code, or create an easy-to-custom-friendly window but require more code. Of course, I finally chose the latter. I often receive such problems in Email: How to create a window without using full screen? How to change the title bar of the window? How to change the resolution of the window or Pixel Format? The following code has completed all this. ! Although it is best to learn material, this will make you write your own OpenGL program! As you can see, this process returns to the Boolean variable (True or False). He also has 5 parameters: the title bar of the window, the width of the window, the height of the window, the color bits (16/24/32), and full screen logo (True - full screen mode, False - window mode). The returned Boolean value tells us whether the window is successfully created.

Bool CreategLWindow (Char * Title, Int Width, Int Height, Int Bits, Bool Fullscreenflag) {When Windows requires Windows to find the matching pixel format, Windows is saved after the mode value is saved in the variable Pixelformat. Gluint Pixelformat; / / Save the results of the matching match for the WC to save our window classes. Our window information is saved in the window class structure. We can change the appearance and behavior of the window by changing the different fields of the class. Each window belongs to a window class. When you create a window, you must register the class for the window. WNDCLASS WC; // Window Class Structure DWEXSTYLE and DWSTYLE Store Extensions and Usually Window Styles. I am using variables to store styles to be able to be able to change the window's style in order to be able to create the window type I need to create (is the pop-up window under full screen); DWORD DWEXSTYLE; DWORD DWSTYLE; / / Extended Window Style // Window Style The 5-line code below the window The upper left corner of the rectangle and the coordinate value of the lower right corner. We will use these values ​​to adjust our window to make the size of the drawing area happens to be the value of the resolution we need. Usually if we create a 640x480 window, the window of the window accounts for a value of some resolution. Rect windowRect; WindowRect.Lear = (long) 0; windowRect.top = (long) 0; windowRect.bottom = (long) Height; // get the upper left corner of the rectangle and the lower right corner The coordinate value // set the Left to 0 // Set the Right to the required width // Set TOP to 0 // Set the Bottom as the required height. Under the high-line code we make the global variable Fullscreen equal to Fullscreenflag. If we want to run down under full screen, set FullScreenflag to TRUE, but not let the variable fulscreen is equal to FullScreenflag, the FullScreen variable will remain in false. When we destroy the window in full screen mode, the value of the variable FullScreen is not the correct TRUE value, and the computer will mistake the desktop mode and cannot switch back to the desktop. God, I hope that all this is meaningful. That is, Fullscreen's value must always be the value of fullscreenflag, otherwise there will be a problem. {CKER also feels too nonsense here, do not understand .....: (} fullscreen = fullscreenflag; // Set the code in the next section of the global full screen flag, we get the window instance, then define the window Class. CS_HREDRAW and CS_VREDRAW Emissivity Whenever, as long as the window changes. CS_OWNDC creates a private DC for the window. This means that the DC cannot share between the program. Wndproc is the message processing of our program. Since there is no additional window data, the last two fields are set to zero. Then set the instance. Then we set Hicon to null because we don't want to give the window icon. The mouse pointer is set to the standard arrow. Background color does not matter (we Set in GL). We don't want the window menu, so set it to null. Class names can be any name you want. For easy, I will use "OpenGL".

hInstance = GetModuleHandle (NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon ( NULL, IDI_WINLOGO; wc.hcursor = loadcursor (null, idc_arrow); wc.hbrbackground = null; wc.lpszMenuname = null; wc.lpszclassname = "OpenGL"; // Get instances of our window // moving while moving And obtain DC // WndProc processing message for the window // No additional window data // No additional window data // Setting instance // Load Default icon // Mouse pointer // GL does not require background // No need to need menu // Set the class name now register class name. If there is an error, the error message window pops up. After pressing the OK button above, the program exits. IF (! RegisterClass (& WC)) // Try registration window {MessageBox (null, "failed to register the window class.", "error", MB_ok | MB_ICONEXCLAMATION; RETURN FALSE; File: // Exit and return false} The program should run in full screen mode or window mode. If we should be full screen mode, we will try to set up full screen mode. IF (fullscreen) {// Do you want to try a full screen mode? The next part of the code seems to have a problem with the problem to ask about ....... Switch to full screen mode. When switching to full screen mode, there are several important things that you must keep in mind. You must ensure that your width and height used in full screen mode are equivalent to width and height in window mode. The most important thing is to set full screen mode before creating a window. In the code here, you have no need to worry about the width and height, which has been set to the size corresponding to the display mode. DEVMODE dmScreenSettings; memset (& dmScreenSettings, 0, sizeof (dmScreenSettings)); dmScreenSettings.dmSize = sizeof (dmScreenSettings); dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; / / Device mode / / Make sure the size of the memory allocation // devMode structure // Selected screen width // Selected screen height / / The color depth of the selected screen, we allocate it for storage Video settingspace. Set the width, high and color depth of the screen. The following code we tried to set the full screen mode. We have saved all wide, high, color depth messages in DMSCreenSettings. The next line uses ChangeDisplaySettings to try to switch into the mode matching with DMSCREENSETTINGS.

I use the parameter cds_fullscreen to switch the display mode, because do not only remove the status bars at the bottom of the screen, and it is switched back, there is no movement or change your window on the desktop. // Try to set the display mode and return the result. Note: CDS_FULLSCREEN removes the status bar. IF (ChangeDisplaySettings (& DMSCREENSETTINGS, CDS_FULLSCREEN)! = DISP_CHANGE_SUCCESSFUL) {If the pattern fails to set success, we will enter the following code. If you do not match full screen mode, pop-up message window, two options are available: run or exit in window mode. // If the pattern fails, two options are provided: exit or run in the window. 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) {If the user selects windowed mode, the variable fullscreen The value is changed to false and the program continues to run. Fullscreen = false;} else {// Select Window Mode (Fullscreen = FALSE) If the user selects exits, the pop-up message window tells the user that the program will end. And return false telling the program that the window has not been successfully created. The program exits. // 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; // Exit and return false}}} Due to full screen The mode may fail, the user may decide to run under the window, we need to check the value of Fullscreen again before setting the screen / window is true or false. IF (fullscreen) {// is still full screen mode? If we are still full screen mode, set the extended form style for WS_EX_APPWindow, which will force our form to be in the forefront. Then set the form of the form to WS_POPUP. This type of form does not have a border, so that our full screen mode is perfectly displayed. Finally we disable the mouse pointer. When your program is not interactive, it is usually a good idea to ban mouse pointers in full screen mode. DWEXSTYLE = WS_EX_APPWINDOW; DWSTYLE = WS_POPUP; Showcursor (false);} else {// Extended Forms / / Form-State // Hide Mouse Pointer If we use a window instead of full screen mode, we have added in the extension form style. WS_EX_WINDOWEDGE, enhances the 3D sensation of the form. The form style changes WS_OVERLAPPEDWINDOW, create a form with a title bar, a variable size border, menu, and maximizing / minimizing buttons. DWEXSTYLE = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWSTYLE = WS_OVERLAPPEDWINDOW;} // Extended Forms // Form Cact The following row code adjusts the window according to the created form type. The purpose of adjustment is to make the window size is equal to the resolution of our requirements. Typically the border will take up part of the window.

After using AdjustWindowRectex, our OpenGL scene will not be covered by the border. In fact, the window becomes larger to draw borders. This command is invalid in full screen mode. AdjustWindowerRectex (& WindowRect, DWStyle, false, dwexstyle); // Adjusting the window reaches the real-demand size The next section of the code starts to create a window and check if the window is successfully created. We will pass all the parameters required for CREATEWINDOWEX (). Such as extended style, class name (same as the names you use by the registration window), window title, form style, and form of the upper corner coordinate (0,0 are a safe selection), the width and high of the form. We don't have a parent window, nor do they want menus, which are set to NULL. An example of a window is also passed, and the last parameter is set to NULL. Note We include WS_ClipSiblings and WS_CLIPCHILDREN in the formal style. Let OpenGL run normally, these two attributes are necessary. They prevent other forms from drawing in our form. if ((hWnd = CreateWindowEx (dwExStyle, "OpenGL", title, WS_CLIPSIBLINGS |! WS_CLIPCHILDREN | dwStyle, 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL, NULL, hInstance, NULL) )) / / Extension Form Class // Class Name // Window Title // Multi-Form-Class Properties // Multi-Form-Styles Properties // Select Form Properties // Window Position // Calculation Adjustable Window Width // Calculation Adjustable window Height // No Fired Fired Window // No Menu // Instance // Do not pass any stuff to WM_CREATE We check if the window is created normally. If successful, the HWND saves the handle of the window. If you fail, pop up the message window and exit the program. {Killglwindow (); // Reset the display area MessageBox (Null, "Window Creation Error.", "Error", MB_OK | MB_ICONEXCLAMATION; Return False; // Returns the code description pixel format below false}. We chose to support OpenGL and dual cache formats via RGBA (red, green, blue, alpha channel). We tried to find a pixel format that matches our selected color depth (16-bit, 24-bit, 32-bit). Finally, set 16-bit Z-cache. The rest of the parameters either not use or not important (Stent Buffer Template Cache, and ACCULATION BUFFER aggregation buffer).

Static Pixelformatdescriptor PFD = {SizeOf (PixelformATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_Support_opengl | Pfd_doublebuffer, Pfd_Type_RGBA, BITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0}; // PFD tells the window What is the size // version of the appeal format descriptor must support window // must support window // must support window // Support OpenGL // must support dual buffer // Application RGBA format // Select color depth // ignored color bit // no alpha cache // ignore Shift bit // No aggregation cache // ignore gathered position // 16 bit z - Cache (depth cache) // Noneless buffer cache // No auxiliary cache // Main-drawing layer // Reserved // ignore the layer mask If there is no error when the window is created, we will then try to obtain the OpenGL device descriptor. If the DC cannot be obtained, the error message program exits (returning false). IF (! (HDC = GETDC (HWND))) // Get the device description table? {killglwindow (); // Reset the display area MessageBox (Null, "Can't create a GL Device Context.", "Error ", MB_OK | MB_ICONEXCLAMATION; Return False; // Returns False} After trying to get the device descriptor for the OpenGL window, we try to find a pixel format corresponding to our previously selected pixel format. If Windows can't find, pop up an error message and exit the program (return false). IF (! (pixelformat = choosepixelformat (hdc, & pfd)) // Windows finds the corresponding pixel format? {killglwindow (); // Reset the display area MessageBox (Null, "CAN't Find A Suitable Pixelformat. "," Error ", MB_OK | MB_ICONEXCLAMATION; Return False; // Returns False} Windows to find the corresponding pixel format, try to set the pixel format. If you are unable to set, the error message is popped, and the program is exited (returning false).

IF (! setpixelformat (hdc, pixelformat, & pfd)) / / Can set the pixel format? {killglwindow (); // Reset the display area MessageBox (Null, "Can't set the pixelformat.", "error", MB_OK | MB_ICONEXCLAMATION); Return False; // Returns False} After setting the pixel format normally, try to obtain a coloring description table. If you cannot get a color description table, the error message is popped, and the program is exited (returning false). IF (! (!)) / / Can you get a coloring description table? {killglwindow (); // Reset the display area MessageBox (Null, "Can't create a gl rendering context.", "Error ", MB_ok | MB_ICONEXCLAMATION); Return False; // Returns false} If there is still no error until now, we have managed to obtain the device description table and coloring description table. Then, what to do is to activate the coloring description table. If you can't activate, pop up an error message, and exit the program (return false). IF (! WGLmakecurrent (HRC)) // Try to activate Color Description Table {KillGlWindow (); // Reset Display MessageBox (Null, "Can't Activate The Gl Rendering Context.", "Error", MB_OK | MB_ICONEXCLAMATION); RETURN FALSE; / / Returns false} Everything goes well, the OpenGL window has created completed, then you can display it. Set it to the front end window (give it higher priority) and move the focus to this window. Then call ResizeGlscene to set the width and height of the screen to the perspective OpenGL screen. ShowWindow; setForegroundWindow (hwnd); setfocus (hwnd); resizeglscene (width, height); // Display window // 略 提 优 优级 // Setting keyboard focus to this window // Settings Poscope To INITGL (), here you can set the light, texture, and more any stuff that needs to be set. You can define an error check within INITGL (), and return True (everything is normal) or false.

For example, if you load texture in Initgl (), you may want to stop. If you return false, the following code pops up an error message and exits the program. If (! initgl ()) // Initialize the newly built GL window {killglwindow (); // Reset the display area MessageBox (Null, "Initialization Failed.", "Error", MB_OK | MB_ICONEXCLAMATION; Return False; // Return False} The creation window that can be safely creating a safe setting here is successful. We returned True to WinMain () noticed that there is no error to prevent programs from exiting. Return True; // Success} The following code processes all window messages. When we registered a window class, the program jumps to this part of the code processing window message. LRESULT CALLBACK WNDPROC (HWND HWND, UMSG, WPARAM WPARAM, LPARM LPARAM) {// The message // of the window // Additional message content // Additional message content is compared with the value of UMSG, then turn Into the CASE handle, the name of the message we have to process is saved in the UMSG. Switch (UMSG) {// Check the Windows message If the UMSG is equal to WM_ACTIVE, check whether the window is still active. If the window has been minimized, set the variable Active to False. If the window is activated, the value of the variable Active is TRUE. Case WM_Activate: {if (! HiWord (WPARAM)) {Active = true;} else {Active = false;} return 0;} // Surveillance window activation message // Check the minimization status // Program in the activation status // No longer activation // Return message loop If the message is a wm_sysCommand (system command), it is again compared to WPARAM. If WPARAM is SC_SCREENSAVE or SC_MONITORPOWER, it is not a screen protection to run, that is, the display wants to enter power save mode. Returning 0 can prevent these two things. Case wm_syscommand: {switch (wparam) {copy sc_screensave: copy sc_monitorpower: return 0;} Break;} // Interrupt System Command Intercept system commands // Check system call check system calls // screen save? // Display To enter the section Electrical mode? // Blocks occurred // If the UMSG is WM_CLOSE, the window will be turned off. We sent an exit message and the main loop will be interrupted. The variable DONE is set to true, WinMain (), the main loop abort, the program is closed. Case WM_Close: {PostquitMessage (0); RETURN 0;} // Receive a CLOSE message? // Send an exit message If the keyboard key is pressed, the key value can be found by reading the WPARAM.

I set the value of the corresponding array group member of the keyboard array keys [] True. This will be found in this way, you can find what button is pressed. Allows multiple keys simultaneously. Case WM_KeyDown: {Keys [wparam] = true; return 0;} //} // If yes, set to true // Return, if the keyboard is released, you can find the information of WPARAM The key value. Then set the value of the keyboard array keys [] to false. This way to find Key [] know what button is pressed, what button is released. Each key on the keyboard can be represented by a number of 0-255. For example, when we press 40 orning the key, the value of Keys [40] will be set to TRUE. If you let go, it is set to false. This is also the principle of the Key array. Case WM_Keyup: {Keys [WPARAM] = false; return 0;} //} // If yes, set to false // When the window is adjusted, the UMSG is finally equal to the message WM_SIZE. Reading Loword and HiWord for LPARAM can get new widths and heights of the window. Pass them to ResizeGlscene (), OpenGL scenarios will be adjusted to new widths and heights. Case WM_SIZE: {ResizeGlscene (Loword (LPARAM), HiWord (LPARAM)); Return 0;}} // Adjust OpenGL window size // loword = width, hiword = height // Returns the restless message is passed to DEFWINDOWPROC, let Windows handles themselves. // Pass all untreated messages to DEFWIndowProc. Return DefwindowProc (HWND, UMSG, WPARAM, LPARAM);} The following is the entry of our Windows program. The window creation routine will be called, process the window message, and monitor the human machine interaction. INT WinAPI Winmain (Hinstance Hinstance, Hinstance Hprevinstance, LPSTR LPCMDLINE, INT NCMDSHOW) {// Instance // Previous instance // Command line parameter // window Display status We set two variables. MSG is used to check if there is a message waiting to be processed. The initial value of DONE is set to false. This means that our procedure has not been running. The program continues to run as long as the program done remains false. Once the value of DONE changes to True, the program exits. Msg msg; bool done = false; // WindowsX message structure // This code is completely optional for the BOOL variable that exits the loop. The program pops up a message window, ask if the user wants to run in full screen mode. If the user clicks the NO button, the FullScreen variable changes from the default true to false, and the program is also changed in window mode. // Tips Users to select Run Mode IF (MessageBox (Null, "Would You Like to Run in Fullscreen Mode?", "Start Fullscreen?", MB_YESNO | MB_ICONQUESTION == IDNO) {FullScreen = false; file: // window mode } The OpenGL window is then created. The parameter of the CreateGLWindow function is the title, width, height, color depth, and full screen logo. It's that simple! I really appreciate this code. If it is not created, the function returns false. The program exits immediately.

// Create an OpenGL window if ("" CreateGL Framework ("Nehe's OpenGL Framework", 640, 480, 16, fullscreen) {return 0; // Failed exit} The following is the beginning of the loop. As long as DONE keeps False, the loop has been done. While (! done) // Keep loop until done = true {What is the first thing we have to do is to check if there is a message waiting. Use PeekMessage () to check the message without locking our programs. Many programs use getMessage () or work well. But use getMessage (), the program will not do anything before receiving a Paint message or other window message. IF (PEEKMESSAGE (& MSG, NULL, 0, 0, PM_REMOVE)) {// Is there a message waiting? The following code views whether an exit message appears. If the current message is a wm_quit caused by postquitMessage (0), the DONE variable is set to true, and the program will exit. IF (msg.Message == wm_quit) {DONE = true;} else {// Received an exit message? // Yes, Done = true // is not, processing window message If it is not an exit message, we translate the message, then send Message makes wndproc () or Windows to handle them. TranslateMessage (& MSG); DispatchMessage (& MSG);}}} Else {// Translation message // Send message // If there is no message, if there is no message, we draw our OpenGL scene. The first row of the code checks if the window is activated. If the ESC key is pressed, the DONE variable is set to true, and the program will exit. // Draw a scene. Monitor the ESC key and exit message if (active) {if (key) {if (key = true;} elone = true;} elone = true;} Else {// Program activation? // ESC Put it? // ESC When exiting signal // is not exit, refresh screen If the program is activated and the ESC is not pressed, we draw a scene and swap cache (using a dual cache to achieve no flashing animation). We actually draw on another "screen" that you can't see. When we exchange the cache, our current screen is hidden, and now I see the screen that I have just can't see. This is also why we can't see the scene plotting process. The scene is just instant display. Drawglscene (); swapbuffers (hdc);}} // Draw a scenario // Switch (dual cache) little code is recently added (05-01-00). Allow users to press F1 keys to switch between full screen mode and window mode.

if (keys [VK_F1]) {keys [VK_F1] = FALSE; KillGLWindow (); fullscreen = fullscreen;! // reconstruction OpenGL window if (! CreateGLWindow ( "NeHe's OpenGL Framework", 640,480,16, fullscreen)) {return 0 }}}} // F1 button is pressed? // If it makes the value in the corresponding Key array to destroy the current window // Switch full screen / window mode // If the window is not created, the program Exit If The Done Variable IS No Longer False, The Program Quits. We Kill The OpenGL Window Properly So That Everything is Freed Up, And We Exit The Program. If the Done variable is no longer false, the program exits. Normally destroy the OpenGL window, release all memory, exit the program. // Close the program killglwindow (); return (msg.wparam);} // Destroy window // Exit program In this lesson, I tried to explain everything in detail. Each step is related to the settings and created a full-screen OpenGL program. When you press the ESC key program, you will exit and monitor whether the window is activated. I spent 2 weeks to write code, one week to correct BUG and discuss programming guides, 2 days (HTML files for 22 hours). If you have any comments or suggestions, please give me email. If you think there is something wrong or improve, please tell me. I want to be the best OpenGL tutorial and interested in your feedback. {Translator: I also spent three days of spare time to translate, typing. Nehe's documentation seems to be very simple, it seems to be very ridiculous. But if you want to come to such a master, have you seen a few? Or that sentence, I am not a master, I hope you are sincere. } The following is the source code download link. Good luck!

转载请注明原文地址:https://www.9cbs.com/read-2200.html

New Post(0)