• 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;
    }

    运行:

  • 相关阅读:
    jackson 枚举 enum json 解析类型 返回数字 或者自定义文字 How To Serialize Enums as JSON Objects with Jackson
    Antd Pro V5 中ProTable 自定义查询参数和返回值
    ES6/Antd 代码阅读记录
    es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
    Antd Hooks
    使用.Net Core开发WPF App系列教程(其它 、保存控件内容为图片)
    使用.Net Core开发WPF App系列教程( 三、与.Net Framework的区别)
    使用.Net Core开发WPF App系列教程( 四、WPF中的XAML)
    使用.Net Core开发WPF App系列教程( 二、在Visual Studio 2019中创建.Net Core WPF工程)
    使用.Net Core开发WPF App系列教程( 一、.Net Core和WPF介绍)
  • 原文地址:https://www.cnblogs.com/chen9510/p/10923763.html
Copyright © 2020-2023  润新知