使用cygwin编译器在自定义win32窗口上的OpenGL不起作用

时间:2014-07-09 09:49:18

标签: c++ winapi opengl cygwin eclipse-cdt

我根据NeHe的第一个教程编写了一些代码,它创建了一个窗口并初始化了gl上下文。这在vc ++中完全正常。然后我尝试使用cygwin编译器在eclipse c ++环境中复制相同的代码并开始出现问题。

窗口编译没有任何错误(许多警告,但没有错误),exe打开一个win32窗口,我已经编码到窗口的所有功能也工作(例如全屏模式) ,改变分辨率)唯一的问题是,不应该用红色刷新窗户的背景,因为我应该得到一个黑色正方形而且它就是它。

对我来说,这看起来像一个opengl初始化问题。一直试图解决这个问题两天,但我找不到任何解决方案,我希望有人能看出我做错了什么。

以下是代码摘录。

初始方法

#include <iostream>
#include <windows.h>
#include <gl/glew.h>
#include <string>

#define GLEW_STATIC

using namespace std;

#include <glWindow.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    MSG msg;
    GLboolean Exit = FALSE;
    glWindow screen("Dark Light", 640, 480, 16);

    while(!Exit){
        if (screen.LastError() == errNone && screen.WndState() != glExit){
            // Is There A Message Waiting?
            if (PeekMessage(&msg, screen.Handles().Window(), 0, 0, PM_REMOVE)){
                // Have We Received A Quit Message?
                if (msg.message == WM_QUIT){
                    screen.WndState() = glExit;
                }
                // If Not, Deal With Window Messages
                else{
                    TranslateMessage(&msg);             // Translate The Message
                    DispatchMessage(&msg);                  // Dispatch The Message
                }
            }
            // If There Are No Messages
            else{
                if (screen.WndState() == glActive){
                    if (screen.KeysState(VK_ESCAPE)){
                        screen.WndState() = glExit;
                    }
                    else{
                        // Draw The Scene
                        screen.Draw();
                    }
                }

                if (screen.KeysState(VK_F1)){
                    screen.KeysState(VK_F1) = FALSE;
                    screen.ToggleFullscreen();
                }

                if (screen.KeysState(VK_SPACE)){
                    screen.KeysState(VK_SPACE) = FALSE;
                    screen.SetResolution(800, 600);
                }
            }
        }
        else{
            Exit = true;
        }
    }

    // Shutdown
    return 0;
}

glWindow.h

#ifndef GLWINDOW_H
#define GLWINDOW_H

#include <string>

using namespace std;


enum glWndState
{
    glActive = 0, glPaused = 1, glExit = 2
};

enum glWndErrors
{
    errNone = 0, errCreateWC = 1, errCreateWnd = 2, errCreateDC = 3, errMatchPixelFormat = 4,
    errSetPixelFormat = 5, errCreateRC = 6, errActivateRC = 7, errInitGL = 8, errChangeRC = 9,
    errReleaseRC = 10, errReleaseDC = 11, errDestroyWnd = 12, errDestroyWC = 13, errGoToFullscreen = 14,
    errGoToWindowed = 15, errGetInstance = 16
};

class glWndSettings
{
private:
    GLsizei _width;
    GLsizei _height;
    GLboolean _fullscreen;
    GLint _bits;
    PIXELFORMATDESCRIPTOR _pfd;
    DEVMODE _screenSettings;

public:
    glWndSettings(GLsizei width, GLsizei height, GLint bits);
    glWndErrors glSetStyle(HWND hWnd);
    glWndErrors glSetStyle(HWND hWnd, GLboolean fullscreen, GLboolean save = TRUE);
    glWndErrors glSetResolution(HWND hWnd, GLsizei width, GLsizei height);

    GLsizei& Width();
    GLsizei& Height();
    GLboolean& Fullscreen();
    GLint& Bits();
    PIXELFORMATDESCRIPTOR& PixelFormatDescription();
};

class glWndHandles
{
private:
    string _className;
    HINSTANCE _hInstance;
    WNDCLASS _wc;
    HWND _hWnd;
    HDC _hDC;
    HGLRC _hRC;
    GLuint _pixelFormat;

public:
    glWndHandles(HICON icon, string title, WNDPROC wndProc);
    ~glWndHandles();
    glWndErrors glDefWindow(PIXELFORMATDESCRIPTOR pfd);

    HINSTANCE& Instance();
    WNDCLASS& WinClass();
    HWND& Window();
    HDC& DeviceContext();
    HGLRC& RenderContext();
};

class glWndFPS
{
    GLint _framesCounter;
    GLint _fps;
public:
    glWndFPS();

    GLvoid NewFrame();
    GLvoid ResetFrames();
    GLint FPS();
};

class glWindow
{
    glWndHandles _handles;
    glWndSettings _settings;
    glWndFPS _fps;
    glWndErrors _error;
    glWndState _state;
    bool _keys[256];
    string _title;

    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
    glWindow(string title, int width, int height, int bits);
    ~glWindow();

    int InitGL();
    GLvoid Draw();
    GLvoid DisplayFPS();
    GLvoid SetTitle(string title);
    GLvoid SetResolution(GLsizei width, GLsizei height);
    GLvoid SetFullscreen(GLboolean fullscreen);
    GLvoid ToggleFullscreen();

    glWndHandles& Handles();
    glWndSettings& Settings();
    glWndFPS& fpsInfo();
    glWndErrors& LastError();
    glWndState& WndState();
    bool& KeysState(int key);

    GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
};

#endif /* GLWINDOW_H_ */

glWindow.cpp

#include <stdio.h>
#include <windows.h>
#include <GL/glew.h>
#include <glm/gtc/matrix_transform.hpp>

using namespace std;

#include "glWindow.h"

glWndSettings::glWndSettings(GLsizei width, GLsizei height, GLint bits){
    _fullscreen = FALSE;

    _width = width;
    _height = height;
    _bits = bits;

    _pfd.nSize              =   sizeof(PIXELFORMATDESCRIPTOR);  // Size Of This Pixel Format Descriptor
    _pfd.nVersion           =   1;                              // Version Number
    _pfd.dwFlags            =   PFD_DRAW_TO_WINDOW |            // Format Must Support Window
                                PFD_SUPPORT_OPENGL |            // Format Must Support OpenGL
                                PFD_DOUBLEBUFFER;               // Must Support Double Buffering

    _pfd.iPixelType         =   PFD_TYPE_RGBA;                  // Request An RGBA Format
    _pfd.cColorBits         =   bits;                           // Select Our Color Depth

    _pfd.cRedBits           =   0; _pfd.cRedShift = 0;
    _pfd.cGreenBits         =   0; _pfd.cGreenShift = 0;
    _pfd.cBlueBits          =   0; _pfd.cBlueShift = 0;         // Color Bits Ignored
    _pfd.cAlphaBits         =   0; _pfd.cAlphaShift = 0;            // No Alpha Buffer

    _pfd.cAccumBits         =   0;
    _pfd.cAccumRedBits      =   0;
    _pfd.cAccumGreenBits    =   0;
    _pfd.cAccumBlueBits     =   0;
    _pfd.cAccumAlphaBits    =   0;

    _pfd.cDepthBits         =   16;                             // 16Bit Z-Buffer (Depth Buffer)
    _pfd.cStencilBits       =   0;                              // No Stencil Buffer
    _pfd.cAuxBuffers        =   0;                              // No Auxiliary Buffer
    _pfd.iLayerType         =   PFD_MAIN_PLANE;                 // Main Drawing Layer
    _pfd.bReserved          =   0;                              // Reserved

    _pfd.dwLayerMask        =   0;
    _pfd.dwVisibleMask      =   0;
    _pfd.dwDamageMask       =   0;                              // Layer Masks Ignored
}
glWndErrors glWndSettings::glSetStyle(HWND hWnd){
    GLboolean fullscreen = !_fullscreen;
    return glSetStyle(hWnd, fullscreen);
}
glWndErrors glWndSettings::glSetStyle(HWND hWnd, GLboolean fullscreen,  GLboolean save){
    DWORD dwExStyle = 0;
    DWORD dwStyle = 0;

    if (save)
        _fullscreen = fullscreen;

    if (fullscreen){
        dwExStyle = WS_EX_APPWINDOW;
        dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

        memset(&_screenSettings, 0, sizeof(_screenSettings));   // Makes Sure Memory's Cleared
        _screenSettings.dmSize = sizeof(_screenSettings);       // Size Of The Devmode Structure
        _screenSettings.dmPelsWidth = _width;                   // Selected Screen Width
        _screenSettings.dmPelsHeight = _height;                 // Selected Screen Height
        _screenSettings.dmBitsPerPel = _bits;                   // Selected Bits Per Pixel
        _screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
        if (ChangeDisplaySettings(&_screenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){
            return errGoToFullscreen;
        }
        while(ShowCursor(FALSE) >= 0);
    }
    else{
        dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
        dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;

        if (ChangeDisplaySettings(NULL, 0) != DISP_CHANGE_SUCCESSFUL){
            return errGoToWindowed;
        }
        while(ShowCursor(TRUE) < 0);
    }

    RECT windowRect;
    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

    AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size

    ShowWindow(hWnd, SW_HIDE);
    DWORD oldExStyle = SetWindowLongPtr(hWnd, GWL_EXSTYLE, dwExStyle);
    DWORD oldStyle = SetWindowLongPtr(hWnd, GWL_STYLE, dwStyle);
    SetWindowPos(hWnd, HWND_TOP, 0, 0, windowRect.right, windowRect.bottom, SWP_NOZORDER);
    ShowWindow(hWnd, SW_SHOW);

    return errNone;
}
glWndErrors glWndSettings::glSetResolution(HWND hWnd, GLsizei width, GLsizei height){
    _width = width; _height = height;
    glSetStyle(hWnd, _fullscreen);

    return errNone;
}

GLsizei& glWndSettings::Width(){
    return _width;
}
GLsizei& glWndSettings::Height(){
    return _height;
}
GLboolean& glWndSettings::Fullscreen(){
    return _fullscreen;
}
GLint& glWndSettings::Bits(){
    return _bits;
}
PIXELFORMATDESCRIPTOR& glWndSettings::PixelFormatDescription(){
    return _pfd;
}

glWndHandles::glWndHandles(HICON icon, string title, WNDPROC wndProc){
    _hInstance = NULL;
    _hWnd = NULL;
    _hDC = NULL;
    _hRC = NULL;
    _pixelFormat = NULL;

    _className = title;

    _wc.style               = CS_HREDRAW | CS_VREDRAW |         // Redraw On Size
                              CS_OWNDC;                         // Own DC For Window.
    _wc.lpfnWndProc         = wndProc;                          // WndProc Handles Messages
    _wc.cbClsExtra          = NULL;                             // No Extra Window Data
    _wc.cbWndExtra          = NULL;                             // No Extra Window Data
    _wc.hInstance           = NULL;                             // Set The Instance
    _wc.hIcon               = icon;                             // 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       = _className.c_str();               // Set The Class Name
}
glWndHandles::~glWndHandles(){
    // Are We Able To Release The DC And RC Contexts?
    if (_hRC){
        if (!wglMakeCurrent(NULL, NULL))
            MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

        // Are We Able To Delete The RC?
        if (!wglDeleteContext(_hRC))
            MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
    }

    // Are We Able To Release The DC
    if (_hDC && !ReleaseDC(_hWnd, _hDC))
        MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

    // Are We Able To Destroy The Window?
    if (_hWnd && !DestroyWindow(_hWnd))
        MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

    // Are We Able To Unregister Class
    if (!UnregisterClass(_className.c_str(), _hInstance))
        MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
glWndErrors glWndHandles::glDefWindow(PIXELFORMATDESCRIPTOR pfd){
    if ((_hInstance = GetModuleHandle(NULL))){
        _wc.hInstance = _hInstance;
    }
    else{
        MessageBox(NULL,  "Failed To Get Window's Instance.",  "ERROR", MB_OK|MB_ICONEXCLAMATION);
        return errGetInstance;
    }

    if (!RegisterClass(&_wc)){
        MessageBox(NULL,  "Failed To Register The Window Class.",  "ERROR", MB_OK|MB_ICONEXCLAMATION);
        return errCreateWC;
    }

    if (!(_hWnd=CreateWindowEx( NULL,                           // Extended Style For The Window
                                _wc.lpszClassName,              // Class Name
                                _className.c_str(),             // Window Title
                                NULL,                           // Style For The Window
                                0, 0, 300, 300,                 // Window's Position and Size
                                NULL,                           // No Parent Window
                                NULL,                           // No Menu
                                _hInstance,                     // Instance
                                NULL))){
        MessageBox(NULL, "Window Creation Error.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errCreateWnd;
    }

    //Get Window's Device Context
    if (!(_hDC = GetDC(_hWnd))){
        MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errCreateDC;
    }

    // Did Windows Find A Matching Pixel Format?
    if (!(_pixelFormat = ChoosePixelFormat(_hDC, &pfd))){
        MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errMatchPixelFormat;
    }

    // Are We Able To Set The Pixel Format?
    if(!SetPixelFormat(_hDC, _pixelFormat, &pfd)){
        MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errSetPixelFormat;
    }

    if (!(_hRC=wglCreateContext(_hDC))){
        MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errCreateRC;
    }

    if(!wglMakeCurrent(_hDC,_hRC)){
        MessageBox(NULL, "Can't Activate The GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
        return errActivateRC;
    }

//  GLenum err = glewInit();
//
//  if (err != GLEW_OK){
//      MessageBox(NULL, (char*)glewGetErrorString(err), "ERROR", MB_OK|MB_ICONEXCLAMATION);
//      return errInitGL;
//  }

    return errNone;
}

HINSTANCE& glWndHandles::Instance(){
    return _hInstance;
}
WNDCLASS& glWndHandles::WinClass(){
    return _wc;
}
HDC& glWndHandles::DeviceContext(){
    return _hDC;
}
HGLRC& glWndHandles::RenderContext(){
    return _hRC;
}
HWND& glWndHandles::Window(){
    return _hWnd;
}

glWndFPS::glWndFPS(){
    _framesCounter = 0; _fps = 0;
}
GLvoid glWndFPS::NewFrame(){
    _framesCounter++;
}
GLvoid glWndFPS::ResetFrames(){
    _fps = _framesCounter; _framesCounter = 0;
}
GLint glWndFPS::FPS(){
    return _fps;
}

glWindow* owner;
LRESULT CALLBACK glWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
    // Check For Windows Messages
    switch (uMsg){
        // Watch For Window Activate Message
        case WM_ACTIVATE:{
            // Check Minimization State
            if (!HIWORD(wParam)){
                // Program Is Active
                owner->_state = glActive;
            }
            else{
                // Program Is No Longer Active
                owner->_state = glPaused;
            }

            // Return To The Message Loop
            return 0;
        }
        // Intercept System Commands
        case WM_SYSCOMMAND:{
            // Check System Calls
            switch (wParam){
                // Screensaver Trying To Start?
                case SC_SCREENSAVE:
                // Monitor Trying To Enter Powersave?
                case SC_MONITORPOWER:
                // Prevent From Happening
                return 0;
            }
            break;
        }
        // Did We Receive A Close Message?
        case WM_CLOSE:{
            // Send A Quit Message
            PostQuitMessage(0);
            return 0;
        }
        // Is A Key Being Held Down?
        case WM_KEYDOWN:{
            // If So, Mark It As TRUE
            owner->_keys[wParam] = TRUE;
            return 0;
        }
        // Has A Key Been Released?
        case WM_KEYUP:{
            // If So, Mark It As FALSE
            owner->_keys[wParam] = FALSE;
            return 0;
        }
        // Resize The OpenGL Window
        case WM_SIZE:{
            if (owner->Settings().Fullscreen() && IsWindowVisible(hWnd)){
                if (wParam == SIZE_MINIMIZED)
                    owner->Settings().glSetStyle(hWnd, FALSE, FALSE);
                else if (wParam == SIZE_RESTORED)
                    owner->Settings().glSetStyle(hWnd, TRUE, FALSE);
            }

            // LoWord=Width, HiWord=Height
            owner->ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
            return 0;
        }
        case WM_KILLFOCUS:{
            if (IsWindowVisible(hWnd) && owner->Settings().Fullscreen())
                ShowWindow(hWnd, SW_MINIMIZE);

            return 0;
        }

        case WM_TIMER:{
            if (wParam == 1)
                owner->DisplayFPS();

            return 0;
        }
    }

    // Pass All Unhandled Messages To DefWindowProc
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

glWindow::glWindow(string title, int width, int height, int bits)
    :_settings(width, height, bits), _handles(LoadIcon(NULL, IDI_WINLOGO), title, (WNDPROC)WndProc)
{
    for (int i = 0; i < 256; i++){
        _keys[i] = false;
    }
    _error = errNone; _state = glActive; owner = this;
    _title = title;

    if ((_error = _handles.glDefWindow(_settings.PixelFormatDescription())) != errNone){
        return;
    }

    _settings.glSetStyle(_handles.Window(), false);
    SetForegroundWindow(_handles.Window());                     // Slightly Higher Priority
    SetFocus(_handles.Window());                                // Sets Keyboard Focus To The Window

    // Initialize Our Newly Created GL Window
    if (!InitGL()){
        MessageBox(NULL, "Initialization Failed.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
        _error = errInitGL;
        return;
    }

    SetTimer(_handles.Window(), 1, 1000, NULL);
}

glWindow::~glWindow(void){
    if (_settings.Fullscreen()){
        ChangeDisplaySettings(NULL,0);          // If So Switch Back To The Desktop
        ShowCursor(TRUE);                       // Show Mouse Pointer
    }
}

int glWindow::InitGL(){
    glShadeModel(GL_SMOOTH);
    glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

    glClearDepth(1.0f);                         // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                    // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                     // The Type Of Depth Test To Do

    // Really Nice Perspective Calculations
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    return TRUE;                                // Initialization Went OK
}

GLvoid glWindow::Draw(){
    //Clear The Screen And The Depth Buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();                           // Reset The Current Modelview Matrix

    SwapBuffers(_handles.DeviceContext());

    fpsInfo().NewFrame();
}

glWndErrors& glWindow::LastError(){
    return _error;
}
glWndState& glWindow::WndState(){
    return _state;
}
glWndHandles& glWindow::Handles(){
    return _handles;
}
glWndSettings& glWindow::Settings(){
    return _settings;
}
glWndFPS& glWindow::fpsInfo(){
    return _fps;
}
bool& glWindow::KeysState(int key){
    return _keys[key];
}

GLvoid glWindow::DisplayFPS(){
    fpsInfo().ResetFrames();
    char fps[100];
    sprintf(fps, "%d", fpsInfo().FPS());

    SetTitle(_title + " : ");
    SetTimer(_handles.Window(), 1, 1000, NULL);
}
GLvoid glWindow::SetTitle(string title){
    SetWindowText(_handles.Window(), title.c_str());
}
GLvoid glWindow::SetResolution(GLsizei width, GLsizei height){
    _settings.glSetResolution(_handles.Window(), width, height);
}
GLvoid glWindow::SetFullscreen(GLboolean fullscreen){
    _settings.glSetStyle(_handles.Window(), fullscreen);
}
GLvoid glWindow::ToggleFullscreen(){
    _settings.glSetStyle(_handles.Window());
}

GLvoid glWindow::ReSizeGLScene(GLsizei width, GLsizei height){
    if (height == 0 && width == 0){
        return;
    }

    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);                // Select The Projection Matrix
    glLoadIdentity();                           // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    glm::perspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);

    glMatrixMode(GL_MODELVIEW);                 // Select The Modelview Matrix
    glLoadIdentity();                           // Reset The Modelview Matrix
}

编译器输出

g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\glWindow.o" "..\\src\\glWindow.cpp"
g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\hello.o" "..\\src\\hello.cpp" 
g++ -mwindows -o hello.exe "src\\hello.o" "src\\glWindow.o" -lgl -lglew32 -lglu32 -lopengl32 -lgdi32 

1 个答案:

答案 0 :(得分:2)

你是如何编译Cygwin构建的?具体你链接哪些图书馆?

可以为本机GUI系统(Win32)编译Cygwin或使用X11。但OpenGL在两种情况之间经历了两个截然不同的堆栈。在Win32的情况下,它通过WGL,在X11的情况下,它通过GLX。现在,如果您意外地链接了基于GLX的OpenGL API(-lGL),那么所有OpenGL符号都在那里,所以事情似乎表面上看起来很好,但是没有输出。您必须链接opengl32.lib,即-lopengl32,以便使用基于WGL的绑定。