【问题标题】:how to make opengl animation with transparent background?如何制作具有透明背景的opengl动画?
【发布时间】:2017-09-28 13:27:06
【问题描述】:

这是我的代码,但我不能让它移动。

我添加了一些代码 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); 
    }
    

【问题讨论】:

    标签: c++ winapi opengl


    【解决方案1】:

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

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

    更喜欢使用双缓冲窗口上下文,使用PFD_DRAW_TO_WINDOW 并避免绘制到位图上下文。

    如果您仍想将渲染结果输入 DIB,您应该学习渲染到纹理技术,例如 FBO(将场景渲染到纹理中)以及通过从纹理中读取像素来获取数据(您还可以使用多种方法)那个)。

    【讨论】:

    • 你能给我一个演示代码吗?因为我的opengl很差。
    • 您到底想达到什么目标?在屏幕上移动四边形?
    • 网上有很多教程,你为什么不挑一个?
    • 因为我找不到它。我曾经尝试过 sfml freeglut glut 等等,但找不到可以做我想做的教程。也许原因是我的英语不好,或者我现在不是win32开发人员。如果你知道google里的关键词可以搜索,请告诉我,非常感谢!
    • 好吧,教程是解释一般概念,所以你可以自己做你想做的事。您可能找不到完全符合您要求的教程。这是一个现代 OpenGL 的好站点:learnopengl.com Hello OpenGL 不是通常的带有一个打印语句的 hello world 程序,它肯定需要更多的知识。花一些时间学习和理解。
    【解决方案2】:

    现在,这可以做一个这样的窗口

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

    #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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 2012-07-07
      • 2011-07-24
      • 2012-07-06
      相关资源
      最近更新 更多