• 基于MFC的OpenGL程序<转>


    原贴地址:https://www.cnblogs.com/pinking/p/6180225.html

    首先,使用的库是GLUT以及GLAUX,先下载两者,添加查找路径以及链接

     
    一、单文本文件  
    工程openGLMFC
    1、创建单文本文件
     
     
     
     
    2、添加路径、链接
    方法如之前篇章所示,
    链接库为opengl32.lib ;glu32.lib ;glut32.lib ;glaux.lib
     
    3、头文件
    在stdafx.h中加入下列语句:
    //openGL 所需要的头文件
    #include <gl/gl.h>
    #include <gl/glu.h>
    #include <gl/glut.h>
    #include <gl/glaux.h>
    4、设置窗口风格
    将窗口风格设为WS_CLIPCHILDREN WS_CLIPSIBLINGS,从而避免OpenGL绘制到其他窗口中去。这些应该放在PreCreateWindow()中。
    BOOL CopenGLMFCView::PreCreateWindow(CREATESTRUCT& cs)
    {
        // TODO: Modify the Window class or styles here by modifying
        //  the CREATESTRUCT cs
        cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        return CView::PreCreateWindow(cs);
    }
    5、变量、函数声明
    初始化GL,考虑到使用设备上下文、绘图上下文,
    先在openGLMFCView.h中声明需要的变量以及函数
    HGLRC m_hRC;    //RC 绘图上下文
    CDC* m_pDC;        //DC 设备上下文
    BOOL InitializeOpenGL();    //初始化 OpenGL
    BOOL SetupPixelFormat();    //为 DC 建立像素格式
    6、创建消息响应函数
    初始化需要在WM_CREATE触发
    资源释放在WM_DESTROY触发
    窗口大小变化时 WM_SIZE触发,需要调整绘图
    由于使用opengl绘制背景,故不需要窗口自己在绘制背景了,需要改写 WM_ERASEBACKGROUND消息触发的事件
     
    故,打开classWizard,在openGLMFCView类中添加上面四个消息响应函数

    OnCreate   OnDestroy  OnSize  OnEraseBkground

    7、初始化

    将通过建立像素格式和绘制上下文来初始化OpenGL. 在InitializeOpenGL()中会创建一个设备上下文(DC),为这个DC选择一个像素格式,创建和这个DC相关的绘制上下文(RC),然后选择这个RC.这个函数会调用SetupPixelFormat()来建立像素格式。

    int CopenGLMFCView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CView::OnCreate(lpCreateStruct) == -1)
            return -1;
     
        // TODO:  Add your specialized creation code here
        InitializeOpenGL();
        return 0;
    }
     
    BOOL CopenGLMFCView::InitializeOpenGL()
    {
        //客户区获得DC
        m_pDC = new CClientDC(this);
        //Failure to Get DC
        if (m_pDC == NULL)
        {
            MessageBox(L"Error Obtaining DC");
            return FALSE;
        }
        //为DC建立像素格式
        if (!SetupPixelFormat())
        {
            return FALSE;
        }
        //创建 RC
        m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());
        //Failure to Create Rendering Context
        if (m_hRC == 0)
        {
            MessageBox(L"Error Creating RC");
            return FALSE;
        }
        //设定OpenGL当前线程的渲染环境。
        //以后这个线程所有的OpenGL调用都是在这个hdc标识的设备上绘制。
        if (::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC) == FALSE)
        {
            MessageBox(L"Error making RC Current");
            return FALSE;
        }
        //背景颜色
        ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        //深度缓存 1最大,让任何都能显示出来
        ::glClearDepth(1.0f);
        //如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作
        ::glEnable(GL_DEPTH_TEST);
        return TRUE;
    }
    //建立像素格式
    /////////////////////////////////////////////////////////////////////////////
    BOOL CopenGLMFCView::SetupPixelFormat()
    {
        static PIXELFORMATDESCRIPTOR pfd =
        {
            sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
            1,                              // version number
            PFD_DRAW_TO_WINDOW |            // support window
            PFD_SUPPORT_OPENGL |            // support OpenGL
            PFD_DOUBLEBUFFER,                // double buffered
            PFD_TYPE_RGBA,                  // RGBA type
            24,                             // 24-bit color depth
            0, 0, 0, 0, 0, 0,               // color bits ignored
            0,                              // no alpha buffer
            0,                              // shift bit ignored
            0,                              // no accumulation buffer
            0, 0, 0, 0,                     // accum bits ignored
            16,                             // 16-bit z-buffer
            0,                              // no stencil buffer
            0,                              // no auxiliary buffer
            PFD_MAIN_PLANE,                 // main layer
            0,                              // reserved
            0, 0, 0                         // layer masks ignored
        };
        int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
        if (m_nPixelFormat == 0)
        {
            return FALSE;
        }
        if (::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd) == FALSE)
        {
            return FALSE;
        }
        return TRUE;
    }

    8、绘制场景

    在绘制场景时,一般包括如下步骤:1)清空缓存。2)绘制场景。3)Flush掉渲染流水线。4)若设置了双缓冲,则交换前后台缓冲区。

    void CopenGLMFCView::OnDraw(CDC* /*pDC*/)
    {
        CopenGLMFCDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        if (!pDoc)
            return;
     
        // TODO: add draw code for native data here
     
        // 清除颜色、深度缓存
        ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        //可以添加渲染函数
     
        // Flush掉渲染流水线
        ::glFinish();
        // 交换前后缓存区
        ::SwapBuffers(m_pDC->GetSafeHdc());
     
    }

     9、背景绘制修改

     

    试试改变窗口的大小,你会看到很严重的闪烁,并且关闭程序后会报告内存泄露,因此我们这就来解决这两个问题吧。

    发生闪烁的原因是Windows先绘制背景,然后再是OpenGL绘制,因为我们已经让OpenGL负责清空背景色,因此我们不需要Windows去清空背景了

    BOOL CopenGLMFCView::OnEraseBkgnd(CDC* pDC)
    {
        // TODO: Add your message handler code here and/or call default
     
        return TRUE;//CView::OnEraseBkgnd(pDC);
    }

     内存泄露的原因是我们在InitializeOpenGL()中使用了new运算符来为CClientDC对象分配内存,因此需要显示delete掉。

    void CopenGLMFCView::OnDestroy()
    {
        CView::OnDestroy();
      
        // TODO: Add your message handler code here
        if (::wglMakeCurrent(0, 0) == FALSE)
        {
            MessageBox(L"Could not make RC non-current");
        }
      
        //Delete the rendering context
        if (::wglDeleteContext(m_hRC) == FALSE)
        {
            MessageBox(L"Could not delete RC");
        }
        //Delete the DC
        if (m_pDC)
        {
            delete m_pDC;
        }
        //Set it to NULL
        m_pDC = NULL;
    }
    10、大小调整
    在OnSize()中一般用来设置视口和视锥,因为这些是和窗口大小相关的。基本操作包括设置视口,选择投影矩阵,设置模型视图矩阵。
    void CopenGLMFCView::OnSize(UINT nType, int cx, int cy)
    {
        CView::OnSize(nType, cx, cy);
     
        // TODO: Add your message handler code here
        GLdouble aspect_ratio; // width/height ratio
     
        if (0 >= cx || 0 >= cy)
        {
            return;
        }
        // select the full client area
        ::glViewport(0, 0, cx, cy);
        // compute the aspect ratio
        // this will keep all dimension scales equal
        aspect_ratio = (GLdouble)cx / (GLdouble)cy;
        // select the projection matrix and clear it
        ::glMatrixMode(GL_PROJECTION);
        ::glLoadIdentity();
        // select the viewing volume
        ::gluPerspective(45.0f, aspect_ratio, .01f, 200.0f);
     
        // switch back to the modelview matrix and clear it
        ::glMatrixMode(GL_MODELVIEW);
        ::glLoadIdentity();
    }

    二、基于对话框

     
    工程:openGLMFCDialog
    1-3步骤同上
    4、变量函数声明
    在openGLMFCDialogDlg.h文件中,声明如上。
    其余步骤同上,不同点在于,需要将OnDraw里面的写到
    OnPaint函数里面,其中IsIconic()是判断是否为最小化,可以放到else里面即可。
    得到结果
    -----------------------------------------------------------------------------------------------------------------
    原贴地址:https://www.cnblogs.com/pinking/p/6180225.html
  • 相关阅读:
    SEO值得学习建议
    ClientValidationFunction
    readystate的五种状态
    XMLHTTP对象参考
    Provider详解
    有缺点,向左走向右走
    DotNetBar 6.6.0.4 for Vs2005 (+特殊补丁)
    [无敌]一些web开发中常用的、做成cs文件的js代码 转帖来的
    AjaxPro.NET框架生成高效率的Tree(Asp.net 2.0)(示例代码下载)
    Vista 下使用Visual Studio 2005 开发Oracle 方面程序出现的数据连结问题及解决方案
  • 原文地址:https://www.cnblogs.com/wainiwann/p/10003384.html
Copyright © 2020-2023  润新知