首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 游戏天堂 > 游戏开发 > “计算机图形学之OpenGL”学习笔记(1)
【标  题】:“计算机图形学之OpenGL”学习笔记(1)
【关键字】:OpenGL
【来  源】:http://blog.csdn.net/bcboycn/archive/2006/09/17/1233030.aspx

“计算机图形学之OpenGL”学习笔记(1)

终于开始走上正轨了。

下午本来是想去图书馆看《程序员》的,可是去早了,还没有开门,干脆就回寝室上网。一下午也没有干什么正经事,胡乱找了些enyacranberriesmp3,很没意思。

现在学一下openGL,晚上把虚拟机的思路理一下,,,

 

在开始OpenGL之前有必要复习一下windows编程:

1、  程序前加上#define WIN32_LEANAND_MEAN,表示不适用mfc的代码;当然还需要

#include <windows.h>

#include <windowsx.h>

2、  winmain()入口函数

int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

3、  windows程序框架:msgproc()消息回调;msgloop()消息循环;

4、  一下就不罗嗦的,直接进入正题吧

 

用的是nehe的网上教程,用金山词霸读英文网站真的很爽,呵呵

1、头文件,这些就不需要再解释了

#include <windows.h>        // Header File For Windows

#include <gl\gl.h>                     // Header File For The OpenGL32 Library

#include <gl\glu.h>            // Header File For The GLu32 Library

#include <gl\glaux.h>         // Header File For The Glaux Library

先从WinMain()开始看,nehe从具体函数开始的方法没有大局观,看起来不爽

int WINAPI WinMain(

HINSTANCE       hInstance,              // Instance 句柄

HINSTANCE       hPrevInstance,              // Previous Instance无用,老哪个版本的windows

LPSTR         lpCmdLine,                  // Command Line Parameters命令行参数,无用

int               nCmdShow)                 // Window Show State窗口的初始状态(SW_开头)

{

MSG            msg;                                                               // Windows Message Structure

注:MSG的定义

typedef struct tagMSG {     // msg 
HWND   hwnd;     

Handle to the window whose window procedure receives the message.

UINT   message; 

Specifies the message number.

WPARAM wParam;

Specifies additional information about the message. The exact meaning depends on the value of the message member.

LPARAM lParam; 

Specifies additional information about the message. The exact meaning depends on the value of the message member.

DWORD  time; 

Specifies the time at which the message was posted.

POINT  pt; 

Specifies the cursor position, in screen coordinates, when the message was posted.

} MSG; 

 

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)

备注:

int MessageBox(
  HWND hWnd,          // handle of owner window
  LPCTSTR lpText,     // address of text in message box
  LPCTSTR lpCaption,  // address of title of message box
  UINT uType          // style of message box
);

 

Return Values

The return value is zero if there is not enough memory to create the message box.

If the function succeeds, the return value is one of the following menu-item values returned by the dialog box:

Value

Meaning

IDABORT

Abort button was selected.

IDCANCEL

Cancel button was selected.

IDIGNORE

Ignore button was selected.

IDNO

No button was selected.

本程序是当选择NO时将全屏参数设置成false

IDOK

OK button was selected.

IDRETRY

Retry button was selected.

IDYES

Yes button was selected.

 

{

fullscreen=FALSE;                                                // Windowed Mode

}

 

// Create Our OpenGL Window

if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,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?

备注:

BOOL PeekMessage(
  LPMSG lpMsg,         // pointer to structure for message
  HWND hWnd,           // handle to window
  UINT wMsgFilterMin,  // first message
  UINT wMsgFilterMax,  // last message
  UINT wRemoveMsg      // removal flags
);

wRemoveMsg

Specifies how messages are handled. This parameter can be one of the following values:

Value

Meaning

PM_NOREMOVE

Messages are not removed from the queue after processing by PeekMessage.

PM_REMOVE

Messages are removed from the queue after processing by PeekMessage.

By default, all message types are processed. To specify that only certain message should be processed, specify one of more of the following values:

Value

Meaning

PM_QS_INPUT

Windows NT 5.0 and Windows 98: Process mouse and keyboard messages.

PM_QS_PAINT

Windows NT 5.0 and Windows 98: Process paint messages.

PM_QS_POSTMESSAGE

Windows NT 5.0 and Windows 98: Process all posted messages, including timers and hotkeys.

PM_QS_SENDMESSAGE

Windows NT 5.0 and Windows 98: Process all sent messages.

 

{

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)

The SwapBuffers function exchanges the front and back buffers if the current pixel format for the window referenced by the specified device context includes a back buffer.

这一块没有看懂是干什么用的……
BOOL SwapBuffers(
  HDC  hdc  // device context whose buffers get swapped
);
 

}

}

 

if (keys[VK_F1])                                    // Is F1 Being Pressed?

{

keys[VK_F1]=FALSE;                                   // If So Make Key FALSE

KillGLWindow();                                    // Kill Our Current Window

fullscreen=!fullscreen;                      // Toggle Fullscreen / Windowed Mode

// Recreate Our OpenGL Window

if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))

{

return 0;                                          // Quit If Window Was Not Created

}

}

}

}

 

// Shutdown

KillGLWindow();                                                         // Kill The Window

return (msg.wParam);                                            // Exit The Program

}

2、在程序前定义了几个设备相关变量,nehe对于这的解释是The RC connects OpenGL to the DC.

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

3、然后设置了一个数组来监控键盘消息,设置数组的方法可以在一次按键中处理多个键值。Active变量是用来告诉程序我们的窗口是否被最小化到任务栏上。

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

5、  wndproc的申明

LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

6、  winmain函数首先出现的自定义函数是:createGLwindow,那么就先从它下手:好像挺长的哦!!

 

现看一下刚才在winmain中的调用实例

if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))

{

return 0;                                                          // Quit If Window Was Not Created

}

按照下面的定义,第一个参数是标题,第二个和第三个是定义窗口的大小,这里是一个640*480的窗口,(原来的老游戏都是这个分辨率),最后一个参数是用来设置全屏属性的。初始定义中fullscreen=TRUE

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

备注:将WNDCLASS的结构定义先放在这里,以后再具体讨论

typedef struct _WNDCLASS {

    UINT    style;

    WNDPROC lpfnWndProc;

    int     cbClsExtra;

    int     cbWndExtra;

    HANDLE  hInstance;

    HICON   hIcon;

    HCURSOR hCursor;

    HBRUSH  hbrBackground;

    LPCTSTR lpszMenuName;

    LPCTSTR lpszClassName;

} WNDCLASS;

 

         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

         这里给前面定义的全局变量赋值,在这次调用中fullscreenTRUE(因为fullscreen直接作为参数传了过来)

         fullscreen=fullscreenflag;                         // Set The Global Fullscreen Flag

 

         hInstance                      = GetModuleHandle(NULL);                  // Grab An Instance For Our Window

Return Values

If the function succeeds, the return value is a handle to the specified module.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

这里只是简单了给hInstace申请了一个值

         下面定义了窗口类的具体值

         wc.style                        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC(注:这里是给窗口创建一个私有DC;// 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

                   memset函数是用来开辟一段字符空间用的memset,它的格式如下

void *memset( void *dest, int c, size_t count );

                   因此这里是开一个dmScreenSettings大小的空间用字符0填充

                   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;

                  这一片又很复杂了,,DEVMODE是一个很长的结构体,是DEVMODEA的别名,我先帖下来

typedef struct _devicemodeA {

    BYTE   dmDeviceName[CCHDEVICENAME];

    WORD dmSpecVersion;

    WORD dmDriverVersion;

    WORD dmSize;

    WORD dmDriverExtra;

    DWORD dmFields;

    union {

      struct {

        short dmOrientation;

        short dmPaperSize;

        short dmPaperLength;

        short dmPaperWidth;

      };

      POINTL dmPosition;

    };

    short dmScale;

    short dmCopies;

    short dmDefaultSource;

    short dmPrintQuality;

    short dmColor;

    short dmDuplex;

    short dmYResolution;

    short dmTTOption;

    short dmCollate;

    BYTE   dmFormName[CCHFORMNAME];

    WORD   dmLogPixels;

    DWORD  dmBitsPerPel;

    DWORD  dmPelsWidth;

    DWORD  dmPelsHeight;

    DWORD  dmDisplayFlags;

 &nb