如何制作透明背景的opengl动画?

时间:2017-05-01 03:27:42

标签: c++ winapi opengl

这是我的代码,但我无法移动。

我在每次执行此函数时添加了一些代码int rendSC(),我在y轴添加了1个像素。

但它没有动。只显示它第一次画画。

这是我尝试过的一种方式:

  1. 在循环中强制调用rendsc()。失败
  2. 可以UpdateWindow() InvalidWindow()等来刷新窗口,现在就调用rendSC()。也失败
  3. 使用时间来致电rendSC()。故障。

    #define _WIN32_WINNT 0x0500
    
    #include <windows.h>
    #include <windowsx.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    
    #pragma comment (lib, "opengl32.lib")
    #pragma comment (lib, "glu32.lib")
    
    #include <assert.h>
    #include <tchar.h>
    
    #ifdef  assert
    #define verify(expr) if(!expr) assert(0)
    #else verify(expr) expr
    #endif
    
    const TCHAR szAppName[]=_T("TransparentGL");
    const TCHAR wcWndName[]=_T("WS_EX_LAYERED OpenGL");
    
    HDC hDC;            
    HGLRC m_hrc;        
    int w(240);
    int h(240); 
    
    HDC pdcDIB;                 
    HBITMAP hbmpDIB;            
    void *bmp_cnt(NULL);        
    int cxDIB(0); 
    int cyDIB(0);   
    BITMAPINFOHEADER BIH;       
    
    
    BOOL initSC()
    {
        glEnable(GL_ALPHA_TEST);        
        glEnable(GL_DEPTH_TEST);        
        glEnable(GL_COLOR_MATERIAL);
    
        glEnable(GL_LIGHTING);          
        glEnable(GL_LIGHT0);            
    
        glEnable(GL_BLEND);             
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glClearColor(0, 0, 0, 0);
    
        return 0;
    }
    
    void resizeSC(int width,int height)
    {
        glViewport(0,0,width,height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        glMatrixMode(GL_MODELVIEW );
        glLoadIdentity();
    }
    
    BOOL renderSC()
    {   
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
        glPushMatrix();
    
        glColor3f(0, 1, 1);
        glBegin(GL_TRIANGLES);                              // Drawing Using Triangles
            glColor3f(1.0f,0.0f,0.0f);                      // Set The Color To Red
            glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top
            glColor3f(0.0f,1.0f,0.0f);                      // Set The Color To Green
            glVertex3f(-1.0f,-1.0f, 0.0f);                  // Bottom Left
            glColor3f(0.0f,0.0f,1.0f);                      // Set The Color To Blue
            glVertex3f( 1.0f,-1.0f, 0.0f);                  // Bottom Right
        glEnd();
    
        glPopMatrix();
        glFlush();
    
        return 0;
    }
    
    // DIB -> hDC
    void draw(HDC pdcDest)
    {
        assert(pdcDIB);
    
        verify(BitBlt(pdcDest, 0, 0, w, h, pdcDIB, 0, 0, SRCCOPY));
    }
    
    void CreateDIB(int cx, int cy)
    {
        assert(cx > 0); 
        assert(cy > 0);
    
        cxDIB = cx ;
        cyDIB = cy ;
    
        int iSize = sizeof(BITMAPINFOHEADER);   
        memset(&BIH, 0, iSize);
    
        BIH.biSize = iSize;
        BIH.biWidth = cx;   
        BIH.biHeight = cy;  
        BIH.biPlanes = 1;   
        BIH.biBitCount = 24;    
        BIH.biCompression = BI_RGB;
    
        if(pdcDIB) 
            verify(DeleteDC(pdcDIB));
    
        pdcDIB = CreateCompatibleDC(NULL);
        assert(pdcDIB);
    
        if(hbmpDIB) 
            verify(DeleteObject(hbmpDIB));
    
        hbmpDIB = CreateDIBSection(
            pdcDIB,         
            (BITMAPINFO*)&BIH,  
            DIB_RGB_COLORS,     
            &bmp_cnt,       
            NULL,
            0);
    
        assert(hbmpDIB);
        assert(bmp_cnt);
    
        if(hbmpDIB)
            SelectObject(pdcDIB, hbmpDIB);
    }
    
    BOOL CreateHGLRC()
    {
        DWORD dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;
    
        PIXELFORMATDESCRIPTOR pfd ;
        memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR)) ;
        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
        pfd.nVersion = 1;                       
        pfd.dwFlags =  dwFlags ;                
        pfd.iPixelType = PFD_TYPE_RGBA ;        
        pfd.cColorBits = 24 ;                   
        pfd.cDepthBits = 32 ;                   
        pfd.iLayerType = PFD_MAIN_PLANE ;       
    
       int PixelFormat = ChoosePixelFormat(pdcDIB, &pfd);
       if (PixelFormat == 0){
          assert(0);
          return FALSE ;
       }
    
       BOOL bResult = SetPixelFormat(pdcDIB, PixelFormat, &pfd);
       if (bResult==FALSE){
          assert(0);
          return FALSE ;
       }
    
       m_hrc = wglCreateContext(pdcDIB);
       if (!m_hrc){
          assert(0);
          return FALSE;
       }
    
       return TRUE;
    }
    
    LRESULT CALLBACK WindowFunc(HWND hWnd,UINT msg, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
    
        switch(msg) 
        {
            case WM_ERASEBKGND:
                return 0;
            break;
    
            case WM_CREATE:
            break;
    
            case WM_DESTROY:
                if(m_hrc)
                {
                    wglMakeCurrent(NULL, NULL);
                    wglDeleteContext(m_hrc) ;
                }
                PostQuitMessage(0) ;
            break;
    
            case WM_PAINT:
                hDC = BeginPaint(hWnd, &ps);
                renderSC(); // OpenGL -> DIB
                draw(hDC);  // DIB -> hDC
                EndPaint(hWnd, &ps);
            break;
    
            case WM_SIZE:
                w = LOWORD(lParam); h = HIWORD(lParam);         
                wglMakeCurrent(NULL, NULL);
                wglDeleteContext(m_hrc);
    
                CreateDIB(w, h);
                CreateHGLRC();
                verify(wglMakeCurrent(pdcDIB, m_hrc));
    
                initSC();
                resizeSC(w, h);
                renderSC();
            break;
    
            default: 
                return DefWindowProc(hWnd,msg,wParam,lParam);
        }
    
        return 0;
    }
    
    int WINAPI _tWinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str,int nWinMode)
    {   
        WNDCLASSEX wc;
        memset(&wc, 0, sizeof(wc));
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = (WNDPROC)WindowFunc;
        wc.cbClsExtra  = 0;
        wc.cbWndExtra  = 0;
        wc.hInstance = hThisInst;
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) (COLOR_WINDOW);
        wc.lpszClassName = szAppName;
    
        if(!RegisterClassEx(&wc))
        {
            MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
            return FALSE;
        }
    
        HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szAppName, wcWndName,
                        WS_VISIBLE | WS_POPUP, 200, 150, w, h,
                        NULL, NULL, hThisInst, NULL);
        if(!hWnd){
            MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
            return FALSE;
        }
    
        verify(SetLayeredWindowAttributes(hWnd, 0x0, 0, LWA_COLORKEY));
    
        MSG msg;
        while(1) 
        {
            while (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
                if (GetMessage(&msg, NULL, 0, 0))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else return 0;
            }
        } 
    
        return (FALSE); 
    }
    

2 个答案:

答案 0 :(得分:0)

绘制位图上下文是个坏主意。在这种情况下,您将只获得软件上下文(这也意味着您将获得没有任何有用扩展的版本1.1上下文)。

但是,如果这符合您的需要,您将创建非双缓冲上下文,在这种情况下,您应该先调用glFinish(而不是Flush),然后才能将DI​​B中的位复制到窗口。

首选使用带有PFD_DRAW_TO_WINDOW的双缓冲窗口上下文,并避免绘制到位图上下文。

如果您仍希望将渲染结果导入DIB,您应该学习渲染到像FBO这样的纹理技术(将场景渲染到纹理中)以及通过从纹理中读取像素来抓取数据(还有几种方法可以做这一点)。

答案 1 :(得分:0)

现在,这可以成为这样一个窗口

但如果我点击窗口,它将冻结

#include "GLFW/glfw3.h"

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <thread>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#include <windowsx.h>
#endif

GLFWwindow* f_window = NULL;
float ratio = 0;
int width, height;

static void error_callback(int error, const char* description)
{
    fputs(description, stderr);
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

static void mouse_callback(GLFWwindow* window, int a, int b, int c)
{
    int xxx = 0;
}

#ifdef _WIN32

void Render();
void renderFunc();
void timerGlFunc();



LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static bool toDebug = false;

    if (toDebug)
    {
        std::cout << __FUNCTION__ << " "; printf("%02x", msg); std::cout << " ";
        toDebug = false;
    }
    //std::cout << __FUNCTION__ << " " << msg;

    switch (msg)
    {
    case WM_LBUTTONDOWN:
    {
        int xPos = GET_X_LPARAM(lParam);
        int yPos = GET_Y_LPARAM(lParam);

        std::cout << __FUNCTION__ << " "; printf("%02x", msg); std::cout << " ";
        toDebug = true;
        PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(xPos, yPos));
    }
        break;
    case WM_NCLBUTTONDOWN:
        std::cout << __FUNCTION__ << " "; printf("%02x", msg); std::cout << " ";
        toDebug = true;
        break;
    case WM_SYSCOMMAND:
        std::cout << __FUNCTION__ << " "; printf("%02x", msg); std::cout << " ";
        toDebug = true;
        break;
    case WM_CAPTURECHANGED:
        std::cout << __FUNCTION__ << " "; printf("%02x", msg); std::cout << " ";
        toDebug = true;
        break;

    case WM_TIMER:
    {
        if (wParam == 1)
        {
            timerGlFunc();
        }

        //DefWindowProc(hWnd, msg, wParam, lParam);
    }

        break;
    default:
        //Render();
        return DefWindowProc(hWnd, msg, wParam, lParam);;

    }
    return DefWindowProc(hWnd, msg, wParam, lParam);

}

#endif

void mainDraw();


int main(void)
{
    bool first = true;
    std::thread t(mainDraw);
    while (true)
    {
        if (first)
        {
            t.detach();
            first = false;
        }
        Sleep(10);
    }
    exit(EXIT_SUCCESS);


    return 0;
}

void mainDraw()
{
    GLFWwindow* window;

    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
        exit(EXIT_FAILURE);

    glfwWindowHint(GLFW_ALPHA_BITS, 8);
    glfwWindowHint(GLFW_ALPHA_MASK, GL_TRUE);
    glfwWindowHint(GLFW_DECORATED, GL_FALSE);
    glfwWindowHint(GLFW_SAMPLES, 4);

    char* title = "Transparent window example";
    window = glfwCreateWindow(256, 256, title, NULL, NULL);

#ifdef _WIN32
    HWND windowHandle = FindWindow(NULL, title);
    if (windowHandle == NULL)
    {
        printf("NULL HWND");
    }
    SetWindowLong(windowHandle, GWL_WNDPROC, (LONG)WndProc);

    SetTimer(windowHandle, 1, 20, NULL);
#endif

    if (!window)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    f_window = window;

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    glfwSetWindowPos(window, 300, 300);

    glfwSetKeyCallback(window, key_callback);
    glfwSetMouseButtonCallback(window, mouse_callback);

    renderFunc();
    //Sleep(10);


    glfwDestroyWindow(window);

    glfwTerminate();
}

void renderFunc()
{
    BOOL ret;
    MSG msg;
    /*
    while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0)
    {
        if (ret != -1)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    */

    while (!glfwWindowShouldClose(f_window))
    {
        if ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0)
        {
            if (ret != -1)
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        glfwGetFramebufferSize(f_window, &width, &height);
        ratio = width / (float)height;

        glViewport(0, 0, width, height);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
        glMatrixMode(GL_MODELVIEW);

        glLoadIdentity();
        glRotatef((float)glfwGetTime() * 50.f, 0.f, 0.f, 1.f);

        //Render();

        Sleep(10);

        glfwPollEvents();
    }
}

void timerGlFunc()
{
    if (!glfwWindowShouldClose(f_window))
    {
        glfwGetFramebufferSize(f_window, &width, &height);
        ratio = width / (float)height;

        glViewport(0, 0, width, height);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
        glMatrixMode(GL_MODELVIEW);

        glLoadIdentity();
        glRotatef((float)glfwGetTime() * 50.f, 0.f, 0.f, 1.f);

        Render();

        glfwPollEvents();
    }
}

void Render()
{


    glBegin(GL_TRIANGLES);
    glColor3f(1.f, 0.f, 0.f);
    glVertex3f(-0.6f, -0.4f, 0.f);
    glColor4f(0.f, 1.f, 0.f, 0.0f);
    glVertex3f(0.6f, -0.4f, 0.f);
    glColor3f(0.f, 0.f, 1.f);
    glVertex3f(0.f, 0.6f, 0.f);
    glEnd();

    glfwSwapBuffers(f_window);
}