由于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; }