如何在mfc中进行opengl编程初始化环境

您好,很高兴为您解答。

1:新建一个MFC的工程,单文档的工程。

2:工程建好之后,可以先编译运行一下。下面就是要把View的窗口初始化为OpenGL的编程环境。当然以下所有的操作都是在View类中进行的。

先在Project->Settings->Link中,加上opengl32.lib

glu32.lib glut.lib glaux.lib,然后在View.h的类定义中加上如下引用。

#include <gl\gl.h>

#include <gl\glu.h>?

#include <gl\glaux.h>

3:首先要让窗口支持OpenGL,那就必须要对PIXELFORMATDESCRIPTOR这个结构有所了解,先在View类中新建一个函数SetupPixFormat(CDC

*pDC),类型:看下面的函数就知道为BOOL,(方法:在classview中,找到**view类,鼠标右击,添加函数)公有私有无所谓,如下:

BOOL?

CTestGLInitialView::SetupPixFormat(CDC?*pDC)?

//我建立的工程名叫TestGLInitial{static?PIXELFORMATDESCRIPTOR?pfd?=?

//定义像素格式{?sizeof(PIXELFORMATDESCRIPTOR),?//?

上述格式描述符的大小?1,?//?

版本号?PFD_DRAW_TO_WINDOW?|//?

格式支持窗口?PFD_SUPPORT_OPENGL?|//?

格式必须支持OpenGL?PFD_DOUBLEBUFFER,?//?

必须支持双缓冲?PFD_TYPE_RGBA,//?申请?RGBA?

格式?24,?//?

24位色彩深度,即1.67千万的真彩色?0,?0,?0,?0,?0,?0,?//?

忽略的色彩位?0,?//?

无Alpha缓存?0,?//?

忽略Shift?Bit?0,?

//?无累加缓存?0,?0,?0,?0,?//?

忽略聚集位?32,?//?32位?

Z-缓存?(深度缓存)?0,?

//?无蒙板缓存?0,?//?

无辅助缓存?PFD_MAIN_PLANE,//?

主绘图层?0,?//?

Reserved?0,?0,?0//?

忽略层遮罩};

int?nIndex?=?ChoosePixelFormat(pDC->GetSafeHdc(),?&pfd);?

//选择刚刚定义的像素格式if(?nIndex?==?0?)?return?FALSE;return?

SetPixelFormat(pDC->GetSafeHdc(),?nIndex,?&pfd);?

//设置像素格式}

这个函数的主要目的就是设置窗口的像素格式,使之支持OpenGL,明白这点就行了。在创建窗口的时候,调用这个函数。

5:刚刚那个函数是用来在创建窗口是调用的,在创建窗口时,还需要对OpenGL的环境做一些初始化,再定义一个函数InitialGL(),(方法:在classview中,找到**view类,鼠标右击,添加函数)公有私有也无所谓,反正是自己调用的,如下:

BOOL?

CTestGLInitialView::InitialGL()

{

glShadeModel(GL_SMOOTH);?

//?启用阴影平滑

glClearColor(0.0f,?0.0f,?0.0f,?

0.0f);?//?

黑色背景

glClearDepth(1.0f);

//?

设置深度缓存

glEnable(GL_DEPTH_TEST);?

//?

启用深度测试

glDepthFunc(GL_LEQUAL);

//?所作深度测试的类型

glHint(GL_PERSPECTIVE_CORRECTION_HINT,?

GL_NICEST);//?告诉系统对透视进行修正

return?

TRUE;

//?初始化?OK

}

这里的代码我都是抄的NeHe教程上面的代码。

6:现在可以捕获WM_CREATE消息了(方法:view-->classvizard -->messages

maps:classname

选**view,找到WM_CREATE,添加函数,编辑代码)。但是,还要先定义一个CClientDC*的成员,(方法:在classview中,找到**view类,鼠标右击,添加函数成员变量。类型:CClientDC*,名字:m_pDC)这个成员指向View窗口自己,是用来传递给SetupPixFormat(CDC

*pDC)函数的,没别的意思。

现在,来捕获WM_CREATE消息(),写上如下代码:

int?

CTestGLInitialView::OnCreate(LPCREATESTRUCT?lpCreateStruct)

{

if?

(CView::OnCreate(lpCreateStruct)?==?-1)

return?-1;

//?

TODO:?Add?your?specialized?creation?code?here

m_pDC?=?new?

CClientDC(this);

SetupPixFormat(m_pDC);

HGLRC?hrc?=?

wglCreateContext(m_pDC->GetSafeHdc());

wglMakeCurrent(m_pDC->GetSafeHdc(),?

hrc);

InitialGL();

return?

0;

}

当然,当窗口关闭的时候,还应该要释放一些资源。捕获WM_DESTROY消息,(方法:view-->classvizard

-->messages maps:classname 选**view,找到WM_DESTROY,添加函数,编辑代码)写下如下代码:

void?

CTestGLInitialView::OnDestroy()

{

CView::OnDestroy();

//?TODO:?Add?

your?message?handler?code?here

HGLRC?hrc?=?

wglGetCurrentContext();

wglMakeCurrent(NULL,?

0);

wglDeleteContext(hrc);

delete?

m_pDC;

}

现在可以编译一下了,没有错误。

7:现在,OpenGL的环境已经初始化差不多了。可以开始做图了,先定义一个作图的函数DrawScene(),写上如下的代码:

BOOL?

CTestGLInitialView::DrawScene()

{

glClear(GL_COLOR_BUFFER_BIT?|?

GL_DEPTH_BUFFER_BIT);//?

清除屏幕和深度缓存

glLoadIdentity();

//?

重置当前的模型观察矩阵

SwapBuffers(m_pDC->GetSafeHdc());

//?交换缓冲区

return?TRUE;

}

然后,要在OnDraw中,调用这个函数:

void?

CTestGLInitialView::OnDraw(CDC*?pDC)

{

CTestGLInitialDoc*?pDoc?=?

GetDocument();

ASSERT_VALID(pDoc);

//?TODO:?add?draw?code?for?native?data?

here

DrawScene();

}

8:运行一下,黑色的背景出来了。

9:这时,可以修改DrawScene()这个作图函数,作图。画出NeHe第3课的那个三角形和正方形来。写代码如下:

BOOL?

CTestGLInitialView::DrawScene(){glClear(GL_COLOR_BUFFER_BIT?|?

GL_DEPTH_BUFFER_BIT);//?

清除屏幕和深度缓存glLoadIdentity();

//?重置当前的模型观察矩阵

glTranslatef(-1.5f,0.0f,-6.0f);?//?左移?

1.5?单位,并移入屏幕?

6.0glBegin(GL_TRIANGLES);?//?

绘制三角形glColor3f(1.0f,?0.0f,?0.0f);glVertex3f(?0.0f,?1.0f,?

0.0f);?//?上顶点glColor3f(0.0f,?1.0f,?

0.0f);glVertex3f(-1.0f,-1.0f,?0.0f);?//?

左下glColor3f(0.0f,?0.0f,?1.0f);glVertex3f(?1.0f,-1.0f,?

0.0f);?//?

右下glEnd();

//?

三角形绘制结束glTranslatef(3.0f,0.0f,0.0f);?

//?右移3单位glColor3f(0.0f,?0.0f,?

1.0f);glBegin(GL_QUADS);

//?绘制正方形glVertex3f(-1.0f,?1.0f,?0.0f);?

//?左上glVertex3f(?1.0f,?1.0f,?0.0f);?//?

右上glVertex3f(?1.0f,-1.0f,?0.0f);?//?

左下glVertex3f(-1.0f,-1.0f,?0.0f);?//?

右下?

glEnd();SwapBuffers(m_pDC->GetSafeHdc());

//?交换缓冲区return?TRUE;}

运行一下,发现图形没有出现,这个怎么回事呢。原来是因为还没有定义投影方式和视口。即用正交投影还是透视投影。定义投影,还要捕获WM_SIZE消息。写如下代码:

void?

CTestGLInitialView::OnSize(UINT?nType,?int?cx,?int?

cy)

{

CView::OnSize(nType,?cx,?cy);

//?TODO:?Add?your?message?

handler?code?here

if?(0?==?

cy)?//?

防止被零除

{

cy?=?

1;//?

将Height设为1

}

glViewport(0,?0,?cx,?cy);

//?重置当前的视口

glMatrixMode(GL_PROJECTION);?//?

选择投影矩阵

glLoadIdentity();//?

重置投影矩阵

//?

设置视口的大小

gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);

//?选择模型观察矩阵

glLoadIdentity();//?

重置模型观察矩阵

}

再运行一下,图形已经出来了。以后,就可以在DrawScene()写任何画图的代码了,当窗口重绘的时候,都可以自动适应。如果要做一段可以运动的3D图画,可以再捕获WM_TIMER消息,通过在OnCreate的时候定义一个时钟,再配合一些变量,就可以做简单的动画了

如若满意,请点击右侧采纳答案,如若还有问题,请点击追问

希望我的回答对您有所帮助,望采纳!

~?O(∩_∩)O~