Windows中如何通过MinGW编译器来使用OpenGL

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

 

posted @ 2013-01-07 02:40  zenny_chen  Views(4775)  Comments(0Edit  收藏  举报