• 在MFC里面使用自定义的OpenGL类进行绘图(基于VS2010)


    对于OpenGL的学习很多都是基于控制台或者win32,然后MFC类库对于我们各种消息响应是非常优秀的,因为在MFC下面进行OpenGL绘图是非常有必要的。OpenGL绘图的跟一般的绘图都是一样,需要设定一个绘图环境,设置环境的过程:1,定义一个窗口像素格式,2,创建一个一个渲染设备描述表,3,当前绘图设备关联渲染设备描述表,在COpenGL.h中定义一个OpenGL类,这个OpenGL类结构如下:

     1 class COpenGL
     2 {
     3 public:
     4     COpenGL(void);
     5     ~COpenGL(void);
     6     BOOL InitializeOpenGL(CWnd*);     //初始化 OpenGL
     7     BOOL SetupPixelFormat();          //设置 Pixel Format
     8     void RenderScene(HDC);            //绘图 Render Scene
     9     void ReShape(GLint,GLint);        //重置视口
    10     void DestoryGL();                 //销毁绘图设备 
    11 
    12 
    13     HGLRC m_hRC;                  //Rendering Context着色描述表
    14     CDC* m_pDC;                   //Device Context设备描述表
    15 };
    View Code

    在COpenGL.cpp实现

      1 #include "OpenGL.h"
      2 
      3 
      4 COpenGL::COpenGL(void)
      5 {
      6 }
      7 
      8 
      9 COpenGL::~COpenGL(void)
     10 {
     11 }
     12 
     13 //初始化绘图设备
     14 BOOL COpenGL::InitializeOpenGL(CWnd* pWnd)
     15 {
     16     //获取绘图客户区绘图设备上下文DC
     17     m_pDC = new CClientDC(pWnd);
     18 
     19     if(!m_pDC)
     20     {
     21         MessageBoxA(NULL,"获取绘图设备DC失败","警告",MB_OK|MB_ICONWARNING);
     22         return FALSE;
     23     }
     24 
     25     if(!SetupPixelFormat())                              //配置像素格式
     26     {    
     27         MessageBoxA(NULL,"像素格式配置失败","警告",MB_OK|MB_ICONWARNING);
     28         return FALSE;
     29     }
     30 
     31     m_hRC = wglCreateContext (m_pDC->GetSafeHdc ());//创建一个渲染设备描述表RC
     32 
     33     if(!m_hRC)
     34     {
     35         MessageBoxA(NULL,"创建渲染设备描述表失败","警告",MB_OK|MB_ICONWARNING);
     36         return FALSE;
     37     }
     38 
     39     if(!wglMakeCurrent (m_pDC->GetSafeHdc (), m_hRC))//关联设备描述表RC和当前绘图设备上下文DC
     40     {
     41         MessageBoxA(NULL,"渲染设备描述表关联失败","警告",MB_OK|MB_ICONWARNING);
     42         return FALSE;
     43     }
     44     glClearColor(0.0f,0.0f,0.0f,0.0f);               //初始化设备背景颜色为黑色
     45     glClearDepth(1.0f);                               //设置设备绘图深度为1.0
     46 
     47     glEnable(GL_DEPTH_TEST);                       //启用深度测试
     48     return TRUE;                                   //绘图设备初始化成功
     49 }
     50 
     51 //设置像素格式
     52 BOOL COpenGL::SetupPixelFormat()
     53 {
     54     static PIXELFORMATDESCRIPTOR pfd =
     55     {
     56         sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
     57         1,                              // version number
     58         PFD_DRAW_TO_WINDOW |            // support window
     59         PFD_SUPPORT_OPENGL |            // support OpenGL
     60         PFD_DOUBLEBUFFER,                // double buffered
     61         PFD_TYPE_RGBA,                  // RGBA type
     62         24,                             // 24-bit color depth
     63         0, 0, 0, 0, 0, 0,               // color bits ignored
     64         0,                              // no alpha buffer
     65         0,                              // shift bit ignored
     66         0,                              // no accumulation buffer
     67         0, 0, 0, 0,                     // accum bits ignored
     68         16,                             // 16-bit z-buffer
     69         0,                              // no stencil buffer
     70         0,                              // no auxiliary buffer
     71 
     72         PFD_MAIN_PLANE,                 // main layer
     73         0,                              // reserved
     74         0, 0, 0                         // layer masks ignored
     75     };
     76     //选择像素格式
     77     int m_nPixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
     78 
     79     if ( !m_nPixelFormat )
     80         return FALSE;
     81 
     82     //设置像素格式
     83     if ( !SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd))
     84         return FALSE;
     85 
     86     return TRUE;
     87 }
     88 
     89 void COpenGL::ReShape(GLint witdh,GLint height )
     90 {
     91     GLdouble aspect_ratio;                             // width/height ratio
     92     aspect_ratio = (GLdouble)witdh/(GLdouble)height;   //计算宽高比
     93 
     94     if ( 0 >= witdh || 0 >= height )
     95     {
     96         return;
     97     }
     98 
     99     glViewport(0, 0, witdh, height);                  //设置视口
    100 
    101     glMatrixMode(GL_PROJECTION);                        //选取投影模型矩阵
    102     glLoadIdentity();                                    //重置投影模型矩阵
    103 
    104     gluPerspective(45.0f, aspect_ratio, 0.1f, 200.0f);//三维视口模型
    105     //::gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);       //二维视口模型
    106     
    107     glMatrixMode(GL_MODELVIEW);                        //选取模型视图矩阵
    108     glLoadIdentity();                                    //重置模型视图矩阵
    109 }
    110 
    111 void COpenGL::DestoryGL()
    112 {
    113     if(!wglMakeCurrent (0,0))                     //解除设备描述表关联
    114         MessageBoxA(NULL,"设备描述表RC解除关联失败","警告",MB_OK|MB_ICONWARNING);
    115     if(!wglDeleteContext (m_hRC))                 //删除设备描述表
    116         MessageBoxA(NULL,"删除设备描述表RC失败","警告",MB_OK|MB_ICONWARNING);
    117 
    118     if(m_pDC)                                     //删除绘图设备上下文DC
    119         delete m_pDC;
    120     m_pDC = NULL;
    121 }
    122 
    123 void COpenGL::RenderScene(HDC hDC)
    124 {
    125     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
    126     glLoadIdentity();                                 // Reset The Current Modelview Matrix
    127 
    128     glTranslatef(0.0f,0.0f,-6.0f);                   // Move Left 1.5 Units And Into The Screen 6.0
    129     glRotatef(30,0.0f,1.0f,0.0f);                     // Rotate The Triangle On The Y axis ( NEW )
    130 
    131 glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle
    132     glColor3f(1.0f,0.0f,0.0f);                      // Red
    133     glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)
    134 
    135     glColor3f(0.0f,1.0f,0.0f);                      // Green
    136     glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)
    137 
    138     glColor3f(0.0f,0.0f,1.0f);                      // Blue
    139     glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)
    140 
    141     glColor3f(1.0f,0.0f,0.0f);                      // Red
    142     glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)
    143 
    144     glColor3f(0.0f,0.0f,1.0f);                      // Blue
    145     glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)
    146 
    147     glColor3f(0.0f,1.0f,0.0f);                      // Green
    148     glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)
    149 
    150     glColor3f(1.0f,0.0f,0.0f);                      // Red
    151     glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)
    152 
    153     glColor3f(0.0f,1.0f,0.0f);                      // Green
    154     glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)
    155 
    156     glColor3f(0.0f,0.0f,1.0f);                      // Blue
    157     glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)
    158 
    159     glColor3f(1.0f,0.0f,0.0f);                      // Red
    160     glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)
    161 
    162     glColor3f(0.0f,0.0f,1.0f);                      // Blue
    163     glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)
    164 
    165     glColor3f(0.0f,1.0f,0.0f);                      // Green
    166     glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)
    167 glEnd();                                          // Done Drawing The Pyramid
    168 
    169 glFlush();
    170 SwapBuffers(hDC);
    171 }
    View Code

    然后为了在整个MFC程序中可以调用这个类,我们需要在CxxxApp这个类中实例化一个COpenGL类,也有另外一个办法,可以将COpenGL类的成员全部定义为静态方法和静态属性,我这里用了第一种方法。

    然后在CXXXview.cpp中进行各种消息的响应,这里主要是这几个消息:WM_CREATE (for OnCreate), WM_DESTROY (for OnDestroy), WM_SIZE (for OnSize), WM_ERASEBACKGROUND (for OnEraseBkground).具体响应的代码如下:

     1 int CDrawOpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
     2 
     3 {
     4 
     5     if (CView::OnCreate(lpCreateStruct) == -1)
     6 
     7         return -1;
     8 
     9 
    10 
    11     // TODO: 在此添加您专用的创建代码
    12 
    13     //初始化openGL绘图
    14     ((CDrawOpenGLApp*)AfxGetApp())->m_OpenGL.InitializeOpenGL(this);
    15 
    16 
    17     return 0;
    18 
    19 }
    20 void CDrawOpenGLView::OnDraw(CDC* /*pDC*/)
    21 {
    22     CDrawOpenGLDoc* pDoc = GetDocument();
    23     ASSERT_VALID(pDoc);
    24     if (!pDoc)
    25         return;
    26 
    27     // TODO: 在此处为本机数据添加绘制代码
    28 
    29     ((CDrawOpenGLApp*)AfxGetApp())->m_OpenGL.RenderScene(::GetDC(this->m_hWnd));//绘图都放在这
    30 }
    31 void CDrawOpenGLView::OnSize(UINT nType, int cx, int cy)
    32 {
    33     CView::OnSize(nType, cx, cy);
    34 
    35     // TODO: 在此处添加消息处理程序代码
    36     ((CDrawOpenGLApp*)AfxGetApp())->m_OpenGL.ReShape(cx,cy);
    37 }
    38 void CDrawOpenGLView::OnDestroy()
    39 {
    40     CView::OnDestroy();
    41 
    42     // TODO: 在此处添加消息处理程序代码
    43 
    44     ((CDrawOpenGLApp*)AfxGetApp())->m_OpenGL.DestoryGL();
    45 }
    View Code

    做完这些,还有一个为了使改变窗口大小时严重的闪烁,在OnEraseBkgnd里做一些操作,避免windows自己的窗口刷新闪烁。

    BOOL CDrawOpenGLView::OnEraseBkgnd(CDC* pDC)
    {
    	// TODO: 在此添加消息处理程序代码和/或调用默认值
    
    	//return CView::OnEraseBkgnd(pDC);
    	return TRUE;
    }
    

      

    补:1.为了在MFC里面顺利使用OpenGL的各种库函数,你需要在stdafx里面添加opengl的头文件和链接库(我喜欢用#pragam comment()的方式)。代码如下:

    #include <gl/GL.h>
    #include <gl/GLU.h>
    
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"glu32.lib")
    #pragma comment(lib,"glut.lib")
    #pragma comment(lib,"glaux.lib")
    

     温馨提示:1.为了不必要的报错,请在stdafx的最后面加入这些头文件和库文件

    2.设置窗口显示风格。窗口创建之前我们必须设置窗口风格包含WS_CLIPCHILDREN和 WS_CLIPSIBLINGS,从而避免OpenGL绘制到其他窗口中去。这些应该放在PreCreateWindow()中。代码如下:

    BOOL CDrawOpenGLView::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: 在此处通过修改
    	//  CREATESTRUCT cs 来修改窗口类或样式
    	cs.style |=WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
    
    	return CView::PreCreateWindow(cs);
    }
  • 相关阅读:
    asp.net 获得域名,端口,虚拟目录[转]
    在EntityFramework6中执行SQL语句【转】
    Ingress 访问日志分析与监控
    kubernetes之secret
    ingress Whitelisting白名单机制
    Kubernates之从pod中拷贝文件到宿主机
    kubernetes-subpath用法(把文件挂载在已存在的目录下,不覆盖原目录)
    npm 私服工具verdaccio 搭建
    nvm安装、解决nvm command not found问题、卸载
    k8s Pod 扩容和缩容
  • 原文地址:https://www.cnblogs.com/hot-destiny/p/5258237.html
Copyright © 2020-2023  润新知