基于对话框的Opengl框架

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

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

2、配置opengl环境

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

基于对话框的Opengl框架_第1张图片

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

////////////opengl头文件/////////////////////
#include "gl\GLUT.H"
#include "gl\GLAUX.H"
#include <stdio.h>
#include <math.h>

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

4、添加消息相应函数

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

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

public:
	HGLRC m_hRC;					//着色描述表
	CDC *m_pDC;						//设备描述表
	BOOL InitOpengl();				//初始化opengl
	BOOL SetupPixelFormat();		//设置图片控件的像素格式
	void RenderScene();				//绘制图像
6、初始化opengl

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

	// TODO: 在此添加额外的初始化代码

	InitOpengl();		//初始化opengl

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
对应的InitOpengl()代码如下:

BOOL CMFC_DlgDlg::InitOpengl()
{
	//获取图片控件DC
	m_pDC=new CClientDC(GetDlgItem(IDC_PIC));
	if(m_pDC==NULL)
		return FALSE;
	//设置图片控件像素
	if (!SetupPixelFormat())
		return FALSE;
	//创建兼容RC
	m_hRC=wglCreateContext(m_pDC->GetSafeHdc());
	if (m_hRC==0)
	{
		return FALSE;
	}
	//激活RC
	if (wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)==FALSE)
	{
		return FALSE;
	}

	//设置投影模式
	GLdouble aspect_ratio;
	GLsizei width,height;
	CRect rect;
	CWnd *pWnd=NULL;
	pWnd=GetDlgItem(IDC_PIC);
	pWnd->GetClientRect(rect);
	width=rect.right-rect.left;
	height=rect.bottom-rect.top;

	glViewport(0,0,width,height);
	aspect_ratio=(GLdouble)width/(GLdouble)height;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,aspect_ratio,0.1,200.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glClearColor(0.0f,0.0f,0.0f,0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);

	return TRUE;
}
7、在上述函数中调用了像素初始化函数SetupPixelFormat()对picture控件的像素进行初始化,其代码如下:

BOOL CMFC_DlgDlg::SetupPixelFormat()
{
	static PIXELFORMATDESCRIPTOR pfd=
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW|
		PFD_SUPPORT_OPENGL|
		PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		24,
		0,0,0,0,0,0,
		0,
		0,
		0,
		0,0,0,0,
		16,
		0,
		0,
		PFD_MAIN_PLANE,
		0,
		0,0,0
	};
	int m_nPixelFormat=ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd);//在窗口找查找该像素格式
	if (m_nPixelFormat==0)
	{
		return FALSE;
	}
	if (SetPixelFormat(m_pDC->GetSafeHdc(),m_nPixelFormat,&pfd)==FALSE)//设置picture控件的像素格式
	{
		return FALSE;
	}
	return TRUE;
}
8、通过上面两步,就完成了初始化,下面开始绘图。为了保证图形在重绘时仍然存在,在对话框的OnPaint()函数中通过调用RenderScene()实现绘图操作,将代码添加到else块中

	else
	{
		RenderScene();							//向缓冲区绘图
		SwapBuffers(m_pDC->GetSafeHdc());		//交换缓冲区

		CDialogEx::OnPaint();
	}
其中,RenderScene()代码如下:

void CMFC_DlgDlg::RenderScene()
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	
	glTranslatef(0.0f,0.0f,-5.0f);
	glBegin(GL_TRIANGLES);
		glColor3f(1.0f,0.0f,0.0f);
		glVertex3f(0.0f,1.0f,1.0f);
		glColor3f(0.0f,1.0f,0.0f);
		glVertex3f(-1.5f,-1.0f,0.0f);
		glColor3f(0.0f,0.0f,1.0f);
		glVertex3f(1.5f,-1.0f,0.0f);
	glEnd();
}
这里为了简单,只画了一个三角形。

9、释放资源

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

void CMFC_DlgDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	if (wglMakeCurrent(NULL,NULL)==FALSE)		//释放RC
	{
		MessageBox("无法释放RC");
	}
	if (wglDeleteContext(m_hRC)==FALSE)			//删除RC
	{
		MessageBox("无法删除RC");
	}
	if (m_pDC)
	{
		delete m_pDC;
	}
	m_pDC=NULL;
}

运行效果如下:

基于对话框的Opengl框架_第2张图片

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


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


参考: MFC单文档框架下的opengl

      Nehe中文教程

你可能感兴趣的:(基于对话框的Opengl框架)