Opengl:渲染到 Win32 API 上下文

Posted

技术标签:

【中文标题】Opengl:渲染到 Win32 API 上下文【英文标题】:Opengl: Rendering to a Win32 API context 【发布时间】:2016-06-01 14:33:29 【问题描述】:

我正在尝试创建一个 opengl 上下文(至少 ogl 4.5)并对其进行渲染;它适用于 SDL2,但我无法弄清楚为什么它不适用于 Win32:我正在尝试使用 glClearColor()/glClear 将屏幕颜色设置为 RGBA(1, 0, 0, 1),但似乎什么也没发生.这是我的代码: --编辑我按照您的建议更新了代码,但仍然没有呈现任何内容;问题也不是因为 gl 3.x/4.x 功能,因为我在创建摆动上下文后初始化了 GLEW

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HGLRC ourOpenGLRenderingContext;
bool running = true;

int WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd)

    MSG msg =  0 ;
    WNDCLASS wc =  0 ;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = L"oglversionchecksample";
    wc.style = CS_OWNDC;
    if (!RegisterClass(&wc))
        return 1;
    CreateWindowW(wc.lpszClassName, L"openglversioncheck",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, 0);


        while (GetMessage(&msg, NULL, 0, 0) > 0)
            DispatchMessage(&msg);


    return 0;


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

    switch (message)
    
    case WM_PAINT:
        glViewport(0, 0, 100, 100); //render to a viewport of width (100; 100)
        glClearColor(1.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        break;
    case WM_CREATE:
    
        PIXELFORMATDESCRIPTOR pfd =
        
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,    //Flags
            PFD_TYPE_RGBA,            //The kind of framebuffer. RGBA or palette.
            32,                        //Colordepth of the framebuffer.
            0, 0, 0, 0, 0, 0,
            0,
            0,
            0,
            0, 0, 0, 0,
            24,                        //Number of bits for the depthbuffer
            8,                        //Number of bits for the stencilbuffer
            0,                        //Number of Aux buffers in the framebuffer.
            PFD_MAIN_PLANE,
            0,
            0, 0, 0
        ;

        HDC ourWindowHandleToDeviceContext = GetDC(hWnd);

        int  letWindowsChooseThisPixelFormat;
        letWindowsChooseThisPixelFormat = ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
        SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd);

        ourOpenGLRenderingContext = wglCreateContext(ourWindowHandleToDeviceContext);
        wglMakeCurrent(ourWindowHandleToDeviceContext, ourOpenGLRenderingContext);
        MessageBoxA(0, (char*)glGetString(GL_VERSION), "OPENGL VERSION", 0);

        if(glewInit() != GLEW_OK) 
            MessageBoxA(0, (char*)glGetString(GL_VERSION), "Error: Could not init OGL API (GLEW)", 0);
        

    
    break;
    case WM_CLOSE:
        //quit code
        wglDeleteContext(ourOpenGLRenderingContext);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    
    return 0;


【问题讨论】:

在 Windows 中创建现代 OpenGL 渲染上下文需要更多的努力。本质上,您首先必须创建一个代理上下文来加载必要的扩展,然后使用它们创建适当的上下文。我写了一个小型库,它在幕后进行内部代理上下文管理,让您毫不费力地直接进入核心业务:github.com/datenwolf/wglarb 谢谢;如果您将其作为答案,我会接受:) 【参考方案1】:

在 Windows 中创建现代 OpenGL 渲染上下文需要更多的努力。本质上,您首先必须创建一个代理上下文来加载必要的扩展,然后使用它们创建适当的上下文。我写了一个小型库,它在幕后进行内部代理上下文管理,让您毫不费力地直接进入核心业务:http://github.com/datenwolf/wglarb

为了 *** 在答案中包含代码而不是链接的最佳实践,这里是主要实现文件(只有 238 行):

/*
Copyright (c) 2014 Wolfgang 'datenwolf' Draxinger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <GL/gl.h>
#include "wglarb.h"

#define wglarb_BuildAssert(cond) ((void)sizeof(char[1 - 2*!(cond)]))

static HANDLE wglarb_intermediary_mutex = NULL;

static DWORD wglarb_intermediary_lock(void)

    wglarb_BuildAssert( sizeof(PVOID) == sizeof(HANDLE) );

    if( !wglarb_intermediary_mutex ) 
        /* Between testing for the validity of the mutex handle,
         * creating a new mutex handle and using the interlocked
         * exchange there is a race... */

        /* //// START \\\\ */

        HANDLE const new_mutex =
            CreateMutex(NULL, TRUE, NULL);

        HANDLE const dst_mutex =
            InterlockedCompareExchangePointer(
                &wglarb_intermediary_mutex,
                new_mutex,
                NULL );

        /* //// FINISH \\\\ */

        if( !dst_mutex ) 
            /* mutex created in one time initialization and held
             * by calling thread. Return signaled status. */
            return WAIT_OBJECT_0;
        
        /* In this case we lost the race and another thread
         * beat this thread in creating a mutex object.
         * Clean up and wait for the proper mutex. */
        ReleaseMutex(new_mutex);
        CloseHandle(new_mutex);
    
    return WaitForSingleObject(wglarb_intermediary_mutex, INFINITE);


static BOOL wglarb_intermediary_unlock(void)

    return ReleaseMutex(wglarb_intermediary_mutex);


#define WGLARB_INTERMEDIARY_CLASS   "wglarb intermediary"
#define WGLARB_INTERMEDIARY_STYLE   (WS_CLIPSIBLINGS|WS_CLIPCHILDREN)
#define WGLARB_INTERMEDIARY_EXSTYLE 0

static HWND wglarb_intermediary_hWnd = 0;

static BOOL wglarb_intermediary_create_Wnd(void)

    HINSTANCE const hInstance = GetModuleHandle(NULL);

    WNDCLASS wc;
    memset(&wc,0,sizeof(wc));
    wc.hInstance = hInstance;
    wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
    wc.lpfnWndProc = DefWindowProc;
    wc.lpszClassName = WGLARB_INTERMEDIARY_CLASS;
    RegisterClass(&wc);

    wglarb_intermediary_hWnd =
        CreateWindowEx(
            WGLARB_INTERMEDIARY_EXSTYLE,
            WGLARB_INTERMEDIARY_CLASS,
            NULL,
            WGLARB_INTERMEDIARY_STYLE,
            0,0,0,0,
            NULL,NULL,
            hInstance,
            NULL );

    if( !wglarb_intermediary_hWnd ) 
        return FALSE;
    

    return TRUE;


static HDC wglarb_intermediary_hDC = 0;

static BOOL wglarb_intermediary_create_DC(void)

    if( !wglarb_intermediary_hWnd
     && !wglarb_intermediary_create_Wnd() ) 
        return FALSE;
    

    wglarb_intermediary_hDC = GetDC(wglarb_intermediary_hWnd);
    if( !wglarb_intermediary_hDC ) 
        return FALSE;
    

    return TRUE;


static HGLRC wglarb_intermediary_hRC = 0;

static BOOL wglarb_intermediary_create_RC(void)

    if( !wglarb_intermediary_hDC
     && !wglarb_intermediary_create_DC() ) 
        return FALSE;
    

    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd,0,sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int iPF;
    if( !(iPF = ChoosePixelFormat(wglarb_intermediary_hDC, &pfd))
     || !(SetPixelFormat(wglarb_intermediary_hDC, iPF, &pfd))
     || !(wglarb_intermediary_hRC = wglCreateContext(wglarb_intermediary_hDC))
    ) 
        return FALSE;
    

    return TRUE;


static BOOL wglarb_intermediary_makecurrent(HDC *hOrigDC, HGLRC *hOrigRC)

    *hOrigDC = wglGetCurrentDC();
    *hOrigRC = wglGetCurrentContext();

    if( !wglarb_intermediary_hRC
     && !wglarb_intermediary_create_RC() )  
        return FALSE;
    

    return wglMakeCurrent(wglarb_intermediary_hDC, wglarb_intermediary_hRC);


HGLRC WINAPI wglarb_CreateContextAttribsARB(
    HDC hDC,
    HGLRC hShareContext,
    const int *attribList)

    if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) 
        return NULL;
    

    HDC   hOrigDC;
    HGLRC hOrigRC;
    if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) 
        wglarb_intermediary_unlock();
        return NULL;
    

    PFNWGLCREATECONTEXTATTRIBSARBPROC impl =
        (PFNWGLCREATECONTEXTATTRIBSARBPROC)
            wglGetProcAddress("wglCreateContextAttribsARB");

    HGLRC ret = NULL;
    if( impl ) 
        ret = impl(hDC, hShareContext, attribList);
       

    wglMakeCurrent(hOrigDC, hOrigRC);
    wglarb_intermediary_unlock();
    return ret;


BOOL WINAPI wglarb_ChoosePixelFormatARB(
    HDC hdc,
    const int *piAttribIList,
    const FLOAT *pfAttribFList,
    UINT nMaxFormats,
    int *piFormats,
    UINT *nNumFormats)

    if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) 
        return FALSE;
    

    HDC   hOrigDC;
    HGLRC hOrigRC;
    if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) 
        wglarb_intermediary_unlock();
        return FALSE;
    

    PFNWGLCHOOSEPIXELFORMATARBPROC impl = NULL;

    impl = (PFNWGLCHOOSEPIXELFORMATARBPROC)
            wglGetProcAddress("wglChoosePixelFormatARB");
    if( !impl ) 
        /* WGL_EXT_pixel_format uses the same function prototypes
         * as the WGL_ARB_pixel_format extension */
        impl = (PFNWGLCHOOSEPIXELFORMATARBPROC)
                wglGetProcAddress("wglChoosePixelFormatEXT");
    

    BOOL ret = FALSE;
    if( impl ) 
        ret = impl(
            hdc,
            piAttribIList,
            pfAttribFList,
            nMaxFormats,
            piFormats,
            nNumFormats );
       

    wglMakeCurrent(hOrigDC, hOrigRC);
    wglarb_intermediary_unlock();
    return ret;

【讨论】:

不幸的是,这是一个商业项目,所以我必须自己写,但是谢谢;它帮助很大 @Coder32:这是 MIT 许可证。您可以免费使用此代码,即使经过修改,甚至在封闭源程序中,只要您在程序的版权和法律声明中提及它的使用。本质上归结为,您必须在程序分发包(安装程序附带的文件 LEGAL.txt 或放置在程序安装目录中)中的某处放置通知,其中有一行“此程序使用 wglarb 库by Wolfgang Draxinger”,你甚至不必提供它的来源。 哦;谢谢你 !在这种情况下,我们可能会考虑使用它;顺便说一句,伟大的工作:)【参考方案2】:

查看 SDL 的代码以了解它的作用 - 我认为要获得现代(>=3 或 >=4)OpenGL 的上下文有些麻烦。

https://www.opengl.org/wiki/Creating_an_OpenGL_Context_%28WGL%29

【讨论】:

\这部分是源代码的实际来源 (来自 opengl Wiki)也,他们说使用这种方法应该没有任何问题 另外,我用的是glew,所以应该没问题

以上是关于Opengl:渲染到 Win32 API 上下文的主要内容,如果未能解决你的问题,请参考以下文章

opengl:纹理删除

在 Win32API 中注册一个窗口类

OpenGL OpenGL管线 与 可编程管线流程

使用 OpenGL 不渲染 --> 上下文

Opengl_7_ *SwapBuffers

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