OpenGL窗口总是很忙

时间:2013-09-23 15:02:26

标签: c++ opengl

我有一个小框架,在无边框的屏幕窗口中显示纹理,但是当我启动它时,应用程序在我激活OpenGL窗口时显示一个忙碌的鼠标图标,我似乎无法理解它来自哪里。

以下代码是完整的解决方案(Visual Studio 2010),应该按原样编译。 不幸的是我甚至不知道从哪里开始寻找,因此我在这里复制了完整的代码。 BasicProject创建一个随机纹理,并将其输入OpenGL窗口。

任何人都可以看到为什么代码陷入繁忙的窗口? 从来没有达到过OpenGL回调,但我不明白为什么不这样做。

BasicProject.cpp(切入点):

/** Sample Project for OpenGL-Display functionality
*
* Anton Roth, 2013
*/

#include "stdafx.h"
#include <conio.h>
#include <process.h>
#include <vector>
#include <Windows.h>
#include <cstdlib>
#include <ctime>
#include "OpenGL-Display.h"

void RunOpenGL(void* pParams);
bool applicationRunning = true;
HANDLE threadOGL;

int _tmain(int argc, _TCHAR* argv[]) {
    OGD::OpenGLDisplay_Init(640, 480, 200, 200, 0, "First Display");
    threadOGL = (HANDLE)_beginthread(RunOpenGL, 0, NULL);

    while(!_kbhit()) {
        Sleep(500);
    }

    applicationRunning = false;
    WaitForSingleObject( threadOGL, 500 );

    return 0;
}

void RunOpenGL(void* pParams) {
    std::vector<char> texture;
    texture.resize(640 * 480 * 3);
    std::srand(time(0));

    while(applicationRunning) {
        for(int i = 0; i < 640 * 480 * 3; ++i) {
            texture.at(i) = std::rand() % 255;
        }

        OGD::OpenGLDisplay_Wrapper(&texture.at(0), 640, 480, false, 24, 0);
        int x, y;
        OGD::OpenGLDisplay_MousePos(x, y, 0);
        Sleep(300);
    }
}

OpenGL的Display.h:

#ifndef __OPENGLDISPLAY
#define __OPENGLDISPLAY
#include <windows.h>        // Header File For Windows
#include <stdio.h>          // Header File For Standard Input/Output
#include <gl\gl.h>          // Header File For The OpenGL32 Library
#include <gl\glu.h>         // Header File For The GLu32 Library
#include <vector>

namespace OGD
{
    class OpenGL_Display
    {
        public:
            OpenGL_Display(int newId);
            ~OpenGL_Display();
            void Init_Display(int width, int height, int posX, int posY, LPCSTR className);
            void DrawNewImage(int width, int height, char* imageData, bool flip, int bpp);
            void GetMouseCords(int& x, int& y);
            int ID;
        protected:
            bool CreateGLWindow(char* title, int bits, int posX, int posY, LPCSTR className);
            GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
            int LoadGLTextures();
            int InitGL(GLvoid);
            void UpdateGLBuffers(int width, int height, char* imageData, int bpp);
            int DrawGLScene(bool flip);
            GLvoid KillGLWindow(GLvoid);
            HDC         hDC;        // Private GDI Device Context
            static LRESULT  CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // Declaration For WndProc

            HGLRC       hRC;        // Permanent Rendering Context
            HWND        hWnd;       // Holds Our Window Handle
            HINSTANCE   hInstance;      // Holds The Instance Of The Application

            bool    keys[256];          // Array Used For The Keyboard Routine
            bool    active;     // Window Active Flag Set To TRUE By Default
            bool    fullscreen; // Fullscreen Flag Set To Fullscreen Mode By Default
            bool    g_bExitThread; // end thread
            GLuint  texture;            // Bitmap image buffer
            int     g_iCounter;     // Current buffer being grabbed to
            bool    g_GLdone;   // Counter to make sure no unnecessary updates are made which cause CPU load
            int xPos;
            int yPos;
            int xPos_right;
            int yPos_right;
            int width;
            int height;
    };

    static std::vector<OGD::OpenGL_Display*> oglDisp;

    void OpenGLDisplay_Wrapper(char* image, int width, int height, bool flip, int bpp, int ID);
    void OpenGLDisplay_Init(int width, int height, int posX, int posY, int ID, LPCSTR className);
    void OpenGLDisplay_MousePos(int&x, int&y, int ID);
};

#endif

OpenGL的Display.cpp:

/** Based on code by NeHe tutorials
    Adapted to display live camera display with OpenGL
*/

#include "OpenGL-Display.h"

using namespace OGD;

OpenGL_Display::OpenGL_Display(int newId)
{
    xPos = -1;
    yPos = -1;
    ID = newId;
    width = 1;
    height = 1;
}

OpenGL_Display::~OpenGL_Display()
{
    KillGLWindow();
}

void OpenGL_Display::Init_Display(int newWidth, int newHeight, int posX, int posY, LPCSTR inputName)
{
    width = newWidth;
    height = newHeight;
    className = inputName;

    if (!CreateGLWindow((char*)className, 24, posX, posY, className))
    {
        throw;
    }   
}

LRESULT CALLBACK OpenGL_Display::WndProc(   HWND    hWnd,           // Handle For This Window
                            UINT    uMsg,           // Message For This Window
                            WPARAM  wParam,         // Additional Message Information
                            LPARAM  lParam)         // Additional Message Information
{
    switch (uMsg)                                   // Check For Windows Messages
    {
        case WM_SYSCOMMAND:                         // Intercept System Commands
        {
            switch (wParam)                         // Check System Calls
            {
                case SC_SCREENSAVE:                 // Screensaver Trying To Start?
                case SC_MONITORPOWER:               // Monitor Trying To Enter Powersave?
                return 0;                           // Prevent From Happening
            }
            break;                                  // Exit
        }

        case WM_CLOSE:                              // Did We Receive A Close Message?
        {
            PostQuitMessage(0);                     // Send A Quit Message
            return 0;                               // Jump Back
        }

        case WM_SIZE:                               // Resize The OpenGL Window
        {
            oglDisp.at(0)->ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
            return 0;                               // Jump Back
        }
    }

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


bool OpenGL_Display::CreateGLWindow(char* title, int bits, int posX, int posY, LPCSTR className)
{
    GLuint      PixelFormat;            // Holds The Results After Searching For A Match
    WNDCLASS    wc;                     // Windows Class Structure
    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

    hInstance           = GetModuleHandle(NULL);                // Grab An Instance For Our Window
    wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   // Redraw On Size, And Own DC For Window.
    wc.lpfnWndProc      = 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    = className;                                // Set The Class Name

    RegisterClass(&wc);                                         // Return FALSE

    dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;           // Window Extended Style
    dwStyle=WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;;                         // Windows Style

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size
    //HWND hwndC = GetConsoleWindow();
    // Create The Window
    hWnd=CreateWindowEx(    dwExStyle,                          // Extended Style For The Window
                                className,                          // Class Name
                                title,                              // Window Title
                                //WS_OVERLAPPEDWINDOW,
                                dwStyle |                           // Defined Window Style
                                WS_CLIPSIBLINGS |                   // Required Window Style
                                WS_CLIPCHILDREN,                    // Required Window Style
                                posX, posY,                         // Window Position
                                WindowRect.right-WindowRect.left,   // Calculate Window Width
                                WindowRect.bottom-WindowRect.top,   // Calculate Window Height
                                NULL,                               // No Parent Window
                                NULL,                               // No Menu
                                hInstance,                          // Instance
                                NULL);

    static  PIXELFORMATDESCRIPTOR pfd=              // pfd Tells Windows How We Want Things To Be
    {
        sizeof(PIXELFORMATDESCRIPTOR),              // Size Of This Pixel Format Descriptor
        1,                                          // Version Number
        PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
        PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
        PFD_DOUBLEBUFFER,                           // Must Support Double Buffering
        PFD_TYPE_RGBA,                              // Request An RGBA Format
        bits,                                       // Select Our Color Depth
        0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
        0,                                          // No Alpha Buffer
        0,                                          // Shift Bit Ignored
        0,                                          // No Accumulation Buffer
        0, 0, 0, 0,                                 // Accumulation Bits Ignored
        16,                                         // 16Bit Z-Buffer (Depth Buffer)  
        0,                                          // No Stencil Buffer
        0,                                          // No Auxiliary Buffer
        PFD_MAIN_PLANE,                             // Main Drawing Layer
        0,                                          // Reserved
        0, 0, 0                                     // Layer Masks Ignored
    };

    hDC=GetDC(hWnd);

    PixelFormat=ChoosePixelFormat(hDC,&pfd);

    SetPixelFormat(hDC,PixelFormat,&pfd);

    hRC=wglCreateContext(hDC);

    wglMakeCurrent(hDC,hRC);

    ShowWindow(hWnd,SW_SHOW);                       // Show The Window
    SetForegroundWindow(hWnd);                      // Slightly Higher Priority
    SetFocus(hWnd);                                 // Sets Keyboard Focus To The Window
    ReSizeGLScene(width, height);                   // Set Up Our Perspective GL Screen

    InitGL();

    return TRUE;                                    // Success
}


int OpenGL_Display::LoadGLTextures()                                    // Load Bitmaps And Convert To Textures
{
    // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit

    glGenTextures(1, &texture);                 // Create The Texture
    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // Minimizing filter, in case display is smaller image size
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // Magnifying filter, in case display is smaller image size

    return 1;                                       // Return The Status
}

GLvoid OpenGL_Display::ReSizeGLScene(GLsizei newWidth, GLsizei newHeight)       // Resize And Initialize The GL Window
{
    width = newWidth;
    height = newHeight;
}

int OpenGL_Display::InitGL(GLvoid)                                      // All Setup For OpenGL Goes Here
{
    if (!LoadGLTextures())                              // Jump To Texture Loading Routine
    {
        return FALSE;                                   // If Texture Didn't Load Return FALSE
    }

    return TRUE;                                        // Initialization Went OK
}

void OpenGL_Display::GetMouseCords(int& x, int& y)      // All Setup For OpenGL Goes Here
{
    x = xPos;
    y = yPos;
}

void OpenGL_Display::UpdateGLBuffers(int width, int height, char* imageData, int bpp) {
    glBindTexture(GL_TEXTURE_2D, texture); 
    switch(bpp) {
    case 8:  glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, imageData); break;
    case 16: glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, imageData); break;
    case 24: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); break;
    default: return;
    }

    GLenum mError = glGetError();

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}

int OpenGL_Display::DrawGLScene(bool flip)                                  // Here's Where We Do All The Drawing
{
    if (height==0)                                      // Prevent A Divide By Zero
    {
        height=1;                                       // Making Height Equal One
    }

    glViewport(0,0,width,height);                       // Reset The Current Viewport

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

    // Calculate The Aspect Ratio Of The Window
    gluPerspective(25.0f,1.0f,0.1f,100.0f);

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

    glEnable(GL_TEXTURE_2D);                            // Enable Texture Mapping
    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
    glClearDepth(1.0f);                                 // Depth Buffer Setup
    glDisable(GL_DEPTH_TEST);                           // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations

    GLenum mError = glGetError();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
    glLoadIdentity();                                   // Reset The View
    glTranslatef(0.0f,0.0f,-5.0f);
    mError = glGetError();
    glBindTexture(GL_TEXTURE_2D, texture);
    mError = glGetError();
    glColor4f(1.0, 1.0, 1.0, 1.0);
    mError = glGetError();

    if(flip)
    {
        glBegin(GL_QUADS);
            // Front Face
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  0.5f);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  0.5f);
        glEnd();
        mError = glGetError();
    }
    else
    {
        glBegin(GL_QUADS);
            // Front Face
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  0.5f);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  0.5f);
        glEnd();
        mError = glGetError();
    }
    mError = glGetError();  
    return TRUE;                                        // Keep Going
}

GLvoid OpenGL_Display::KillGLWindow(GLvoid)                             // Properly Kill The Window
{
    if (fullscreen)                                     // Are We In Fullscreen Mode?
    {
        ChangeDisplaySettings(NULL,0);                  // If So Switch Back To The Desktop
        ShowCursor(TRUE);                               // Show Mouse Pointer
    }

    if (hRC)                                            // Do We Have A Rendering Context?
    {
        wglMakeCurrent(NULL,NULL);
        wglDeleteContext(hRC);
        hRC=NULL;                                       // Set RC To NULL
    }

    ReleaseDC(hWnd,hDC);

    DestroyWindow(hWnd);

    UnregisterClass("OpenGL_Display",hInstance);
}

void OpenGL_Display::DrawNewImage(int width, int height, char* imageData, bool flip, int bpp)
{
    BOOL returnVal = wglMakeCurrent(hDC, hRC);

    UpdateGLBuffers(width, height, imageData, bpp); 
    DrawGLScene(flip);
    SwapBuffers(hDC);
    wglMakeCurrent(NULL, NULL);
}

void OGD::OpenGLDisplay_Init(int width, int height, int posX, int posY, int ID, LPCSTR className)
{
    for(unsigned int i = 0; i < oglDisp.size(); ++i) {
        if(oglDisp.at(i)->ID == ID) {
            return;
        }
    }

    oglDisp.push_back(new OGD::OpenGL_Display(ID));
    oglDisp.at(oglDisp.size()-1)->Init_Display(width, height, posX, posY, className); //by default this ID is latest
    wglMakeCurrent(NULL, NULL);
    GLenum mError = glGetError();
}

void OGD::OpenGLDisplay_Wrapper(char* image, int width, int height, bool flip, int bpp, int ID)
{
    for(unsigned int i = 0; i < oglDisp.size(); ++i) {
        if(oglDisp.at(i)->ID == ID) {
            oglDisp.at(i)->DrawNewImage(width, height, image, flip, bpp);   
            return;
        }
    }   
}

1 个答案:

答案 0 :(得分:1)

即使您的窗口是基于OpenGL的,您也应该创建一个消息循环并重复调用GetMessage,TranslateMessage和DispatchMessage。处理WM_PAINT,即使它不需要绘制任何东西。如果您不这样做,Windows会认为您的应用程序没有响应,并显示忙碌的光标(或更糟糕的是,显示“应用程序无响应”对话框。)