OpenGL MFC单文档环境配置(VS2010)

OpenGL MFC单文档环境配置



本机环境:WIN10    VS2010

环境配置:请查看上一篇博客

一、简介

Windows GDI是通过设备句柄(Device Context(设备描述表)以下简称"DC")来绘图,而OpenGL则需要绘制环境(Rendering Context(着色描述表),以下简称"RC")。每一个GDI命令需要传给它一个DC,但与GDI不同,OpenGL使用当前绘制环境(RC)。但是RC并不能直接完成绘图,只能与特定的DC联系起来,从而完成具体的绘图工作。一旦在一个线程中指定了一个当前RC,在此线程中其后所有的OpenGL命令都使用相同的当前RC。虽然在单一窗口中可以使用多个RC,但在单一线程中只有一个当前RC。下面我将首先产生一个OpenGL RC并使之成为当前RC。这将分为三个步骤:

1、设置窗口像素格式;
2、产生RC;
3、设置为当前RC。

二、搭建MFC中的OpenGL基本框架

1.添加链接库

方法一:打开菜单栏下的项目->属性->配置属性->链接器->输入->附加依赖项里加入

OpenGL32.lib GLu32.lib GLaux.lib glut32.lib



方法二: 在stdafx.h中,添加如下代码:
#pragma comment( lib, "opengl32.lib" )     
#pragma comment( lib, "glu32.lib" )       
#pragma comment( lib, "glut32.lib" )  
#pragma comment( lib, "glaux.lib" )

2.包含头文件

在stdafx.h中:

#include <GL/glu.h>
#include <GL/gl.h>
#include <GL/glut.h>


3、设置窗口显示风格。

窗口创建之前我们必须设置窗口风格包含


WS_CLIPCHILDREN(创建父窗口使用的Windows风格,用于重绘时裁剪子窗口所覆盖的区域)和WS_CLIPSIBLINGS(创建子窗口使用的Windows风格,用于重绘时剪裁其他子窗口所覆盖的区域)


从而避免OpenGL绘制到其他窗口中去。这些应该放在XXXView类 文件的PreCreateWindow()中。代码如下:

BOOL COpenGLStartView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式
	cs.style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	return CView::PreCreateWindow(cs);
}


4.设置窗口像素格式

1.首先向VCOpenGLXXXView类中添加几个保护的成员变量和公共的成员函数(成员函数添加方法就不解释了)。如下:

public:
	HGLRC m_hRC;             //Rendering Context着色描述表  
	CClientDC* m_pDC;        //Device Context设备描述表
	int m_heigth;
	int m_wide;
protected:
	BOOL InitializeOpenGL();    //初始化 OpenGL  
	BOOL SetupPixelFormat();    //设置像素格式  
	void RenderScene();         //绘制场景

2.在View 类中添加四个消息响应函数,如图所示:
WM_CREATE
WM_DESTROY
WM_ERASEBKGND
WM_SIZE


消息响应添加如下:


3.在 XXXView 类的构造函数中进行初始化:

COpenGLStartView::COpenGLStartView()
{
	// TODO: 在此处添加构造代码
	m_pDC = NULL;
	m_hRC = NULL;
}


4.产生一个RC的第一步是定义窗口的像素格式。像素格式决定窗口着所显示的图形在内存中是如何表示的。由像素格式控制的参数包括:颜色深度、缓冲模式和所支持的绘画接口。在下面将在SetupPixelFormat()函数中对这些参数的设置。代码如下:
BOOL COpenGLStartView::SetupPixelFormat(void)  
{  
	static PIXELFORMATDESCRIPTOR pfd =   
	{  
		sizeof(PIXELFORMATDESCRIPTOR),  // pfd结构的大小   
		1,                              // 版本号   
		PFD_DRAW_TO_WINDOW |            // 支持在窗口中绘图   
		PFD_SUPPORT_OPENGL |            // 支持 OpenGL   
		PFD_DOUBLEBUFFER,               // 双缓存模式   
		PFD_TYPE_RGBA,                  // RGBA 颜色模式   
		24,                             // 24 位颜色深度   
		0, 0, 0, 0, 0, 0,               // 忽略颜色位   
		0,                              // 没有非透明度缓存   
		0,                              // 忽略移位位   
		0,                              // 无累计缓存   
		0, 0, 0, 0,                     // 忽略累计位   
		32,                             // 32 位深度缓存       
		0,                              // 无模板缓存   
		0,                              // 无辅助缓存   
		PFD_MAIN_PLANE,                 // 主层   
		0,                              // 保留   
		0, 0, 0                         // 忽略层,可见性和损毁掩模   

	};  
	int pixelFormat;  
	// 为设备描述表得到最匹配的像素格式   
	if((pixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0)  
	{  
		MessageBox( _T("ChoosePixelFormat failed") );  
		return FALSE;  
	}  
	// 设置最匹配的像素格式为当前的像素格式   
	if(SetPixelFormat(m_pDC->GetSafeHdc(), pixelFormat, &pfd) == FALSE)  
	{  
		MessageBox( _T("SetPixelFormat failed") );  
		return FALSE;  
	}  
	return TRUE;  
}  

5.产生RC,设置为当前RC

1.现在像素格式已经设定,我们下一步工作是产生绘制环境(RC)并使之成为当前绘制环境,即编写InitializeOpenGL()函数。代码如下:

BOOL COpenGLStartView::InitializeOpenGL(void)  
{  
	PIXELFORMATDESCRIPTOR pfd;  
	int n;  
	m_pDC=new CClientDC(this);  
	ASSERT(m_pDC != NULL);  
	// 设置当前的绘图像素格式  
	if(!SetupPixelFormat())  
	{  
		return FALSE;  
	}  

	n=::GetPixelFormat(m_pDC->GetSafeHdc());  
	::DescribePixelFormat(m_pDC->GetSafeHdc(), n,sizeof(pfd),&pfd);  
	// 创建绘图描述表  
	m_hRC=wglCreateContext(m_pDC->GetSafeHdc());  
	if(m_hRC == NULL)  
	{  
		return FALSE;  
	}  
	// 使绘图描述表为当前调用现程的当前绘图描述表  
	if( wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC) == FALSE)  
	{  
		return FALSE;  
	}  
	glClearDepth(1.0f);  
	glEnable(GL_DEPTH_TEST);  
	return TRUE;  
}


2.别忘了再OnCreate()函数中调用 InitializeOpenGL()函数。如下所示:
int COpenGLStartView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	if ( InitializeOpenGL())  
	{  
		return 0;  
	}  
	return 0;
}

6. 设置视口

在OnSize()中一般用来设置视口和视锥,因为这些是和窗口大小相关的。代码如下:

void COpenGLStartView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
	m_wide = cx;    //m_wide为在CVCOpenGL2View类中添加的表示视口宽度的成员变量  
	m_heigth = cy;  //m_height为在CVCOpenGL2View类中添加的表示视口高度的成员变量  
	//避免除数为0  
	if(m_heigth==0)  
	{  
		m_heigth=1;  
	}  
	//设置视口与窗口的大小  
	glViewport(0,0,m_wide,m_heigth);  
}

7.绘制场景

1.绘制一个立方体,代码入下:

void COpenGLStartView::RenderScene(void)  
{  
	//设置清平颜色为黑色
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	//清除颜色缓冲区和深度缓冲区
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//透视投影变换
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(80, (double)m_wide / (double)m_heigth, 1.5, 0);/*视角80度,纵横比,进裁剪面,远裁剪面*/
	//视角变换
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(2, 2, 2, 0, 0, 0, 0, 1, 0);/*前三个参数是眼睛的位置,中间三个参数是物体所在的位置,后面三个参数表示向量,头顶朝上的方向*/
	//矩阵堆栈函数,和glPopMatrix()相对应
	glPushMatrix();
	glBegin(GL_LINES);
	glColor3d(1.0, 0.0, 0.0);//X轴 红色
	glVertex3d(0.0, 0.0, 0.0);
	glVertex3d(2.0, 0.0, 0.0);
	glColor3d(0.0, 1.0, 0.0);//Y轴 绿色
	glVertex3d(0.0, 0.0, 0.0);
	glVertex3d(0.0, 2.0, 0.0);
	glColor3d(0.0, 0.0, 1.0);//Z轴 蓝色
	glVertex3d(0.0, 0.0, 0.0);
	glVertex3d(0.0, 0.0, 2.0);
	glEnd();
	glColor3f(1.0, 1.0, 1.0);
	glutWireCube(0.5);


	glPopMatrix();
	glFinish();
	SwapBuffers(wglGetCurrentDC());
}


2.在OnDraw()函数中调用!

void COpenGLStartView::OnDraw(CDC* /*pDC*/)
{
	COpenGLStartDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
	RenderScene();
}

8.一些收尾工作

1.为了使改变窗口大小时严重的闪烁,在OnEraseBkgnd()里做一些操作,避免windows自己的窗口刷新闪烁。OnEraseBkgnd()函数需要重写。如下:

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

2.为了避免内存泄露,OnDestroy()函数中加一些代码,如下:
void COpenGLStartView::OnDestroy()
{
	CView::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	m_hRC = ::wglGetCurrentContext();
	if(::wglMakeCurrent (0,0) == FALSE)
		MessageBox(_T("Could not make RC non-current"));
	if(m_hRC)  
	{  
		if(::wglDeleteContext(m_hRC)==FALSE)  
		{  
			MessageBox(_T("Could not delete RC"));  
		}  
	}  

	if(m_pDC)  
	{  
		delete m_pDC;  
	}  
	m_pDC = NULL;  
}


9.按照上述操作完成后,点击编译;然后运行程序,会出现下图,你们成功了吗?


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值