zoukankan      html  css  js  c++  java
  • Windows API 搭建OpenGL窗口

    步骤:

    1、创建windows窗口,得到窗口句柄hwnd

    2、获取该窗口的设备环境hDC(当然也可以获取其他的设备环境,但我们一般是在创建的窗口上绘制)

    3、创建OpenGL绘制环境RC,这个只能从hDC创建

    4、将hDC和RC绑定到当前的线程

    注:RC表示OpenGL的绘制环境,所有的OpenGL命令都会在RC这个绘制环境中作用,所以必须在RC绑定到当前线程之后才能调用OpenGL命令,否则运行出错,内存访问错误。

      一般的笔刷绘制,在hDC下即可。

    封装的窗口类如下:

      GLWindow.h

    #pragma once
    #include <windows.h>
    #include <GL/glew.h>
    #include <iostream>
    class GLContext
    {
    public:
        GLContext();
        ~GLContext();
        void Setup(HWND,HDC);
        void SetupPixelFormat(HDC);
    private:
        HWND hWnd;
        HDC hDC;
        HGLRC hRC;
        int format;
    };
    
    GLContext::GLContext()
    {
        this->hWnd = 0;
        this->hDC = 0;
        this->hRC = 0;
        this->format = 0;
    }
    GLContext::~GLContext()
    {
    }
    
    void GLContext::SetupPixelFormat(HDC hDC) {
        int pixelFormat;
    
        PIXELFORMATDESCRIPTOR pfd =
        {
            sizeof(PIXELFORMATDESCRIPTOR),  // size
            1,                          // version
            PFD_SUPPORT_OPENGL |        // OpenGL window
            PFD_DRAW_TO_WINDOW |        // render to window
            PFD_DOUBLEBUFFER,           // support double-buffering
            PFD_TYPE_RGBA,              // color type
            32,                         // prefered color depth
            0, 0, 0, 0, 0, 0,           // color bits (ignored)
            0,                          // no alpha buffer
            0,                          // alpha bits (ignored)
            0,                          // no accumulation buffer
            0, 0, 0, 0,                 // accum bits (ignored)
            16,                         // depth buffer
            0,                          // no stencil buffer
            0,                          // no auxiliary buffers
            PFD_MAIN_PLANE,             // main layer
            0,                          // reserved
            0, 0, 0,                    // no layer, visible, damage masks
        };
    
        pixelFormat = ChoosePixelFormat(hDC, &pfd);
        SetPixelFormat(hDC, pixelFormat, &pfd);
    }
    
    void GLContext::Setup(HWND hwnd, HDC hdc) {
        this->hWnd = hwnd;
        this->hDC = hdc;
        SetupPixelFormat(hDC);
        hRC = wglCreateContext(hDC);
        wglMakeCurrent(hDC, hRC);
    
        //initialize glew
        glewExperimental = GL_TRUE;
        glewInit();
        if (AllocConsole())
        {
            freopen("CONOUT$", "w+t", stdout);
            freopen("CONOUT$", "w+t", stderr);
            const GLubyte* Devise = glGetString(GL_RENDERER);    //返回一个渲染器标识符,通常是个硬件平台  
            const GLubyte* str = glGetString(GL_VERSION);
            printf("OpenGL实现的版本号:%s
    ", str);
            printf("硬件平台:%s
    ", Devise);
        }
    }
    
    
    
    
    LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    class GLWindow
    {
    public:
        GLWindow();
        ~GLWindow();
        void Setup(HINSTANCE, HINSTANCE, LPSTR, int);
        //LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
        void RegisterDisplayFunc(void (*display)()) {
            this->Display = display;
        }
        void Run();
    
    private:
        void(*Display)();
    
    private:
        bool exiting = false;
        long windowWidth = 800;
        long windowHeight = 600;
        long windowBits = 64;
        bool fullscreen = false;
    
        WNDCLASSEX windowClass;     // window class
        HWND       hwnd;            // window handle
        HDC           hDC;
        MSG        msg;             // message
        DWORD      dwExStyle;       // Window Extended Style
        DWORD      dwStyle;         // Window Style
        RECT       windowRect;
    
        GLContext glContext;
    };
    GLWindow::GLWindow() {}
    GLWindow::~GLWindow() {}
    
    void GLWindow::Setup(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        windowRect.left = (long)0;                        // Set Left Value To 0
        windowRect.right = (long)windowWidth; // Set Right Value To Requested Width
        windowRect.top = (long)0;                         // Set Top Value To 0
        windowRect.bottom = (long)windowHeight;   // Set Bottom Value To Requested Height
        
                                                  // fill out the window class structure
        windowClass.cbSize = sizeof(WNDCLASSEX);
        windowClass.style = CS_HREDRAW | CS_VREDRAW;
        windowClass.lpfnWndProc = MainWindowProc;    //当窗体触发任何一个事件时,便会调用该函数  
        windowClass.cbClsExtra = 0;
        windowClass.cbWndExtra = 0;
        windowClass.hInstance = hInstance;
        windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  // default icon
        windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);      // default arrow
        windowClass.hbrBackground = NULL;                             // don't need background
        windowClass.lpszMenuName = NULL;                             // no menu
        windowClass.lpszClassName = L"Windows API";
        windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);      // windows logo small icon
    
                                                                // register the windows class
        if (!RegisterClassEx(&windowClass)) {
            puts("Register Class Failed");
        }
        dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window Extended Style
        dwStyle = WS_OVERLAPPEDWINDOW;                    // Windows Style
        AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size
    
                                                                        // class registered, so now create our window
        hwnd = CreateWindowEx(NULL,                                 // extended style
            L"Windows API",                          // class name
            L"OpenGL",      // app name
            dwStyle | WS_CLIPCHILDREN |
            WS_CLIPSIBLINGS,
            0, 0,                               // x,y coordinate
            windowRect.right - windowRect.left,
            windowRect.bottom - windowRect.top, // width, height
            NULL,                               // handle to parent
            NULL,                               // handle to menu
            hInstance,                          // application instance
            NULL);                              // no extra params
    
        ShowWindow(hwnd, SW_SHOW);          // display the window
        UpdateWindow(hwnd);                 // update the window
        hDC = GetDC(hwnd);
        glContext.Setup(hwnd,hDC);
    }
    
    LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        int height, width;
    
        // dispatch messages
        switch (uMsg)
        {
        case WM_CREATE:         // window creation
            break;
    
        case WM_DESTROY:            // window destroy
        case WM_QUIT:
            CloseWindow(hWnd);
            break;
        case WM_CLOSE:                  // windows is closing
    
                                        // deselect rendering context and delete it
                                        //wglMakeCurrent(hDC, NULL);
                                        //wglDeleteContext(hRC);
                                        // send WM_QUIT to message queue
            PostQuitMessage(0);
            break;
    
        case WM_SIZE:
            height = HIWORD(lParam);        // retrieve width and height
            width = LOWORD(lParam);
            break;
    
        case WM_ACTIVATEAPP:        // activate app
            break;
    
        case WM_PAINT:              // paint
            PAINTSTRUCT ps;
            BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
    
        case WM_LBUTTONDOWN:        // left mouse button
            break;
    
        case WM_RBUTTONDOWN:        // right mouse button
            break;
    
        case WM_MOUSEMOVE:          // mouse movement
            break;
    
        case WM_LBUTTONUP:          // left button release
            break;
    
        case WM_RBUTTONUP:          // right button release
            break;
    
        case WM_KEYUP:
            break;
    
        case WM_KEYDOWN:
            int fwKeys;
            LPARAM keyData;
            fwKeys = (int)wParam;    // virtual-key code 
            keyData = lParam;          // key data 
    
            switch (fwKeys)
            {
                case VK_ESCAPE:
                    PostQuitMessage(0);
                    break;
                default:
                    break;
            }
            break;
    
        default:
            break;
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    void GLWindow::Run() {
        while (true)
        {
            (*Display)();
            SwapBuffers(hDC);
            while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
            {
                if (!GetMessage(&msg, NULL, 0, 0))
                {
                    exiting = true;
                    break;
                }
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }

    主函数调用代码示例:

    #include <Windows.h>
    #include <cameras/phc.h>
    #include "shader.h"
    #include "Cube.h"
    #include "GLWindow.h"
    redips::PhC phc;
    GLWindow window;
    
    Shader* shader;
    Cube* cube;
    
    void Display() {
        cube->Draw(*shader, phc);
    }
    
    void Initialize(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
        phc.lookAt(redips::float3(0, 0, 200), redips::float3(0, 0, 0), redips::float3(0, 1, 0));
        window.Setup(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
        window.RegisterDisplayFunc(Display);
    
        shader = new Shader("./joint.vert", "./joint.frag");
        cube = new Cube();
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {    
        Initialize(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
        
        window.Run();
        return 1;
    }

    运行:

  • 相关阅读:
    python pickle模块
    python struct模块
    python threading模块
    python queue模块
    python3 requests模块 基本操作
    python json模块
    C语言回调函数
    工厂方法模式
    git fetch, git pull 以及 FETCH_HEAD
    git删除远程文件夹或文件的方法
  • 原文地址:https://www.cnblogs.com/chen9510/p/10923763.html
Copyright © 2011-2022 走看看