基于对话框的Opengl框架

转自:http://blog.csdn.net/longxiaoshi/article/details/8238933
 
 分类:
 

这里,我主要是利用opengl在一个picture控件中绘图,绘制的是一个静态图片,如果想实现动画,可以利用ontimer函数实现。编译器为vs2010。

1、首先创建一个基于对话框的MFC程序,我这里命名为MFC_Dlg。

2、配置opengl环境

首先添加链接库,在菜单栏 项目->属性->配置属性->链接器->输入->附加依赖项,添加glut32.lib,glaux.lib。如图:

然后,在stdafx.h里面添加opengl的头文件,如下:

[cpp] view plain copy
 
  1. ////////////opengl头文件/////////////////////  
  2. #include "glGLUT.H"  
  3. #include "glGLAUX.H"  
  4. #include <stdio.h>  
  5. #include <math.h>  

3、为对话框添加一个picture控件,ID为IDC_PIC。

4、添加消息相应函数

这里主要是为了在窗口销毁时释放DC和RC资源,为对话框添加了WM_DESTORY消息的相应函数。

5、在对话框头文件中添加相应的成员函数以及数据成员,如下:

[cpp] view plain copy
 
  1. public:  
  2.     HGLRC m_hRC;                    //着色描述表  
  3.     CDC *m_pDC;                     //设备描述表  
  4.     BOOL InitOpengl();              //初始化opengl  
  5.     BOOL SetupPixelFormat();        //设置图片控件的像素格式  
  6.     void RenderScene();             //绘制图像  
6、初始化opengl

在对话框的OnInitDialog()中调用了InitOpengl()对opengl进行初始化

[cpp] view plain copy
 
  1. // TODO: 在此添加额外的初始化代码  
  2.   
  3. InitOpengl();       //初始化opengl  
  4.   
  5. return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
对应的InitOpengl()代码如下:
[cpp] view plain copy
 
  1. BOOL CMFC_DlgDlg::InitOpengl()  
  2. {  
  3.     //获取图片控件DC  
  4.     m_pDC=new CClientDC(GetDlgItem(IDC_PIC));  
  5.     if(m_pDC==NULL)  
  6.         return FALSE;  
  7.     //设置图片控件像素  
  8.     if (!SetupPixelFormat())  
  9.         return FALSE;  
  10.     //创建兼容RC  
  11.     m_hRC=wglCreateContext(m_pDC->GetSafeHdc());  
  12.     if (m_hRC==0)  
  13.     {  
  14.         return FALSE;  
  15.     }  
  16.     //激活RC  
  17.     if (wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)==FALSE)  
  18.     {  
  19.         return FALSE;  
  20.     }  
  21.   
  22.     //设置投影模式  
  23.     GLdouble aspect_ratio;  
  24.     GLsizei width,height;  
  25.     CRect rect;  
  26.     CWnd *pWnd=NULL;  
  27.     pWnd=GetDlgItem(IDC_PIC);  
  28.     pWnd->GetClientRect(rect);  
  29.     width=rect.right-rect.left;  
  30.     height=rect.bottom-rect.top;  
  31.   
  32.     glViewport(0,0,width,height);  
  33.     aspect_ratio=(GLdouble)width/(GLdouble)height;  
  34.     glMatrixMode(GL_PROJECTION);  
  35.     glLoadIdentity();  
  36.     gluPerspective(45.0f,aspect_ratio,0.1,200.0);  
  37.     glMatrixMode(GL_MODELVIEW);  
  38.     glLoadIdentity();  
  39.   
  40.     glClearColor(0.0f,0.0f,0.0f,0.0f);  
  41.     glClearDepth(1.0f);  
  42.     glEnable(GL_DEPTH_TEST);  
  43.   
  44.     return TRUE;  
  45. }  
7、在上述函数中调用了像素初始化函数SetupPixelFormat()对picture控件的像素进行初始化,其代码如下:
[cpp] view plain copy
 
  1. BOOL CMFC_DlgDlg::SetupPixelFormat()  
  2. {  
  3.     static PIXELFORMATDESCRIPTOR pfd=  
  4.     {  
  5.         sizeof(PIXELFORMATDESCRIPTOR),  
  6.         1,  
  7.         PFD_DRAW_TO_WINDOW|  
  8.         PFD_SUPPORT_OPENGL|  
  9.         PFD_DOUBLEBUFFER,  
  10.         PFD_TYPE_RGBA,  
  11.         24,  
  12.         0,0,0,0,0,0,  
  13.         0,  
  14.         0,  
  15.         0,  
  16.         0,0,0,0,  
  17.         16,  
  18.         0,  
  19.         0,  
  20.         PFD_MAIN_PLANE,  
  21.         0,  
  22.         0,0,0  
  23.     };  
  24.     int m_nPixelFormat=ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd);//在窗口找查找该像素格式  
  25.     if (m_nPixelFormat==0)  
  26.     {  
  27.         return FALSE;  
  28.     }  
  29.     if (SetPixelFormat(m_pDC->GetSafeHdc(),m_nPixelFormat,&pfd)==FALSE)//设置picture控件的像素格式  
  30.     {  
  31.         return FALSE;  
  32.     }  
  33.     return TRUE;  
  34. }  
8、通过上面两步,就完成了初始化,下面开始绘图。为了保证图形在重绘时仍然存在,在对话框的OnPaint()函数中通过调用RenderScene()实现绘图操作,将代码添加到else块中
[cpp] view plain copy
 
  1. else  
  2. {  
  3.     RenderScene();                          //向缓冲区绘图  
  4.     SwapBuffers(m_pDC->GetSafeHdc());        //交换缓冲区  
  5.   
  6.     CDialogEx::OnPaint();  
  7. }  
其中,RenderScene()代码如下:
[cpp] view plain copy
 
  1. void CMFC_DlgDlg::RenderScene()  
  2. {  
  3.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  
  4.     glLoadIdentity();  
  5.       
  6.     glTranslatef(0.0f,0.0f,-5.0f);  
  7.     glBegin(GL_TRIANGLES);  
  8.         glColor3f(1.0f,0.0f,0.0f);  
  9.         glVertex3f(0.0f,1.0f,1.0f);  
  10.         glColor3f(0.0f,1.0f,0.0f);  
  11.         glVertex3f(-1.5f,-1.0f,0.0f);  
  12.         glColor3f(0.0f,0.0f,1.0f);  
  13.         glVertex3f(1.5f,-1.0f,0.0f);  
  14.     glEnd();  
  15. }  
这里为了简单,只画了一个三角形。

9、释放资源

在写程序,如果忘记释放DC和RC,将会导致内存泄露,随着程序运行次数的增多,内存占有量越来越大。这里在WM_DESTORY的消息响应函数中释放资源,

[cpp] view plain copy
 
  1. void CMFC_DlgDlg::OnDestroy()  
  2. {  
  3.     CDialogEx::OnDestroy();  
  4.   
  5.     // TODO: 在此处添加消息处理程序代码  
  6.     if (wglMakeCurrent(NULL,NULL)==FALSE)       //释放RC  
  7.     {  
  8.         MessageBox("无法释放RC");  
  9.     }  
  10.     if (wglDeleteContext(m_hRC)==FALSE)         //删除RC  
  11.     {  
  12.         MessageBox("无法删除RC");  
  13.     }  
  14.     if (m_pDC)  
  15.     {  
  16.         delete m_pDC;  
  17.     }  
  18.     m_pDC=NULL;  
  19. }  

运行效果如下:

到此,整个框架就建立起来了,其他的绘图操作都可以在RenderScene()中实现。如果想实现动画效果,只需要设置一个定时器,并在WM_TIMER消息响应函数中改变图形位置并调用RenderScene()即可,并且在OnDestroy中killtimer。

我也是初学者,有什么不对,大家请指正!

原文地址:https://www.cnblogs.com/hjlweilong/p/5672245.html