由於Windows下,微軟自己的Visual C編譯器至今對C99標准支持得非常可憐;而同時,基於GNU規范的C編譯器(GCC,LLVM Clang等)可直接使用C99並加上GNU擴展語言特性(稱為gnu99標准),而在LLVM Clang3.0之后,又能很好地支持gnu11標准。因此選擇GNU規范的編譯器來做基於C語言為主的軟件開發是最合適的。
MinGW是Windows平台上對GCC編譯器的整合,其中包含了大部分Windwos API,可直接使用。另外,也有D3D8和D3D9的庫。
下載MinGW的安裝器可到這個地址:http://sourceforge.net/projects/mingw/files/
然后點擊“Download mingw-get-inst-xxxx.exe”這個超鏈接即可下載。
在安裝MinGW時,自己可以選擇所需要安裝的組件。當然,即便是全選也不會占很大空間。
安裝好了MinGW之后,將MinGW目錄下的bin目錄添加到環境變量PATH中。然后,我們可以使用Eclipse for CPP的IDE來編輯和調試代碼。打開Eclipse之后,此IDE會自己搜索GCC編譯器,非常方便。
我們用Eclipse和MinGW來寫OpenGL代碼前,先把一些必要的庫加上。我們進入到Project->Properties->C/C++ Build->Settings->MinGW C Linker中。然后在Libraries(-l)中分別添加:opengl32、glu32、glaux和gdi32這四個庫。然后我們就可以通過下列代碼來測試了:
/* ============================================================================ Name : openglTest.c Author : Zenny Chen Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <windows.h> /* must include this before GL/gl.h */ #include <GL/gl.h> /* OpenGL header file */ #include <GL/glu.h> /* OpenGL utilities header file */ static void display() { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); glFlush(); } static void InitGLContext(GLsizei width, GLsizei height) { glClearColor(0.4f, 0.4f, 0.4f, 1.0f); glViewport(0, 0, width, height); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); static const GLfloat vertices[] = { 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f }; glVertexPointer(2, GL_FLOAT, 0, vertices); static const GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f }; glColorPointer(4, GL_FLOAT, 0, colors); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); } static LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static PAINTSTRUCT ps; switch(uMsg) { case WM_PAINT: display(); BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; case WM_SIZE: InitGLContext(LOWORD(lParam), HIWORD(lParam)); PostMessage(hWnd, WM_PAINT, 0, 0); return 0; case WM_CHAR: switch (wParam) { case 27: /* ESC key */ PostQuitMessage(0); break; } return 0; case WM_CLOSE: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } static HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height, BYTE type, DWORD flags) { int pf; HDC hDC; HWND hWnd; WNDCLASS wc; PIXELFORMATDESCRIPTOR pfd; static HINSTANCE hInstance = 0; /* only register the window class once - use hInstance as a flag. */ if (!hInstance) { hInstance = GetModuleHandle(NULL); wc.style = CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WindowProc; 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"; if (!RegisterClass(&wc)) { MessageBox(NULL, "RegisterClass() failed: " "Cannot register window class.", "Error", MB_OK); return NULL; } } hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x, y, width, height, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { MessageBox(NULL, "CreateWindow() failed: Cannot create a window.", "Error", MB_OK); return NULL; } hDC = GetDC(hWnd); /* there is no guarantee that the contents of the stack that become the pfd are zeroed, therefore _make sure_ to clear these bits. */ memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags; pfd.iPixelType = type; pfd.cColorBits = 32; pf = ChoosePixelFormat(hDC, &pfd); if (pf == 0) { MessageBox(NULL, "ChoosePixelFormat() failed: " "Cannot find a suitable pixel format.", "Error", MB_OK); return 0; } if (SetPixelFormat(hDC, pf, &pfd) == FALSE) { MessageBox(NULL, "SetPixelFormat() failed: " "Cannot set format specified.", "Error", MB_OK); return 0; } DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); ReleaseDC(hWnd, hDC); return hWnd; } int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) { HDC hDC; /* device context */ HGLRC hRC; /* opengl context */ HWND hWnd; /* window */ MSG msg; /* message */ hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0); if (hWnd == NULL) exit(1); hDC = GetDC(hWnd); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); ShowWindow(hWnd, nCmdShow); while(GetMessage(&msg, hWnd, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } wglMakeCurrent(NULL, NULL); ReleaseDC(hWnd, hDC); wglDeleteContext(hRC); DestroyWindow(hWnd); return msg.wParam; }