在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);
}
原文地址:https://www.cnblogs.com/hot-destiny/p/5258237.html