您的位置:首页 > 编程语言 > C语言/C++

VC++2010环境下基于MFC框架的OpenGL的编程环境的配置

2013-05-30 14:38 597 查看


在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\glut.h>

#include <gl\glaux.h>

3:在PreCreateWindow(CREATESTRUCT& cs)这个函数中可以修改一下窗口的风格,比如说窗口的名称背景什么的,当然也可以不修改,如果想修改的话,需要对WNDCLASSEX和CREATESTRUCT这两个结构比较熟悉。在这里,我不进行修改。采用默认的风格。

4:下面开始正题,首先要让窗口支持OpenGL,那就必须要对PIXELFORMATDESCRIPTOR这个结构有所了解,先在View类中新建一个函数SetupPixFormat(CDC *pDC),公有私有无所谓,如下:

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(),公有私有也无所谓,反正是自己调用的,如下:

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消息了。 但是,还要先定义一个CClientDC*的成员,这个成员指向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消息,写下如下代码:

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.0

glBegin(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的时候定义一个时钟,再配合一些变量,就可以做简单的动画了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: