OPenGL与MFC的接口.doc_第1页
OPenGL与MFC的接口.doc_第2页
OPenGL与MFC的接口.doc_第3页
OPenGL与MFC的接口.doc_第4页
OPenGL与MFC的接口.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

OPenGL与MFC的接口2009-12-07 23:23一、 概述 OPenGL 是一个与硬件和窗口系统无关的图形库,在其标准库里提供了核心的3-D 图形指令,包括物体形状的描述、矩阵转换、光照、颜色、纹理、剪裁、位图等的处理函数。常见的材料比如红宝书里边为了使得讨论集中于图形学的概念,因而使用了辅助库glut 处理与操作系统的交互(比如创建窗口、键盘消息、客户区重绘)。这样做使得读者可以将注意力集中于图形学的概念、原理理解以及OpenGL 模型学习,同时也隐藏了OpenGL 与窗口系统 的接口部分。 当需要开发一个有用的应用程序的时候,glut 中简化了的窗口系统难以胜任。另一方面专业的窗口系统则专注于窗口与操作系统以及用户的交互。因而将二者的长处结和起来的应用程序结构式比较合理的,比如使用MS windows 窗口系统处理界面工作,使用OpenGL 处理图形渲染工作。本文假设读者具有MFC 的基本知识。二、 OpenGL 指令的通道渲染环境 事实证明处理复杂任务时采用分治与抽象的策略是科学的选择。把任务的划分为功能明确、相互关联的子任务,当各个子任务完成的时候总的任务就随之解决。这里功能明确 意味着各个子任务的功能并集组成了整体的任务;相互关联 意味着子任务之间需要一定的接口来进行信息传输。一般而言,子模块定义了信息的处理,而接口定义了信息的流动。这样站在功能模块内部来看,其他部分只剩下一个抽象的接口。 设置好OpenGL 跟MFC 的接口以后,程序员就可以专注于图形的绘制,而将窗口维护以及用户交互的任务留给MFC 来做。具体地说是渲染环境和设备环境起到了这个作用。三、 具体操作例子 用一个多视图的MFC 程序为例来演示如何进行环境的搭建。(1) 创建一个多视图的 MFC 应用程序框架。 比如命名为MFC_OpenGL_exp 。则正确创建以后,程序具有 6 个类分别是: CAboutDlg, CChildFrame, CMainFrame, CMFC_OpenGL_expApp, CMFC_OpenGL_expDoc, CMFC_OpenGL_View, 运行结果如下图所示: 图一。 多文档MFC程序框架的运行结果(1) 创建像素描述格式 对这个框架而言,视图类是展现输出的载体。因而我们将对这个类进行改造。在视图类被创建的时候创建像素描述格式,并且设置到设备环境中的。 对 CMFC_OpenGL_expView 类的 WM_CREATE 消息进行响应,添加消息响应函数 OnCreate 。在该函数里边添加如下的代码:/ TODO: Add your specialized creation code here /Step1 , Set the pixelformat descriptor PIXELFORMATDESCRIPTOR pfd = sizeof(PIXELFORMATDESCRIPTOR), 1, /version PFD_DRAW_TO_WINDOW| PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER| PFD_STER EO_DONTCARE, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0, /op alpha buffer, 0, /shift bit ignored 0, /no accumulation buffer 0,0,0,0, 32, /32 bit z buffer 0, 0, PFD_MAIN_PLANE, 0, 0,0,0 ; HDC hDC = :GetDC(this-GetSafeHwnd(); int indxPfd = ChoosePixelFormat(hDC, &pfd); if(!SetPixelFormat(hDC, indxPfd, &pfd) MessageBox(TEXT(Fail to set pixelformat); - 这一步通过 SetPixelFormat 函数设置需要的像素格式描述。像素描述是设备环境的一个包含部分,但是该函数的输入并非我们直接创建的像素描述(变量 pfd )。而是一个整形的索引。原因如下: 每一个设备环境 (DC) 支持一定数量的像素格式,设备环境维护了一个描述列表来保存上述信息。程序创建一个像素格式描述 (PIXELFORMATDESCRIPTOR 型的变量 ) 以后,使用 ChoosePixelFormat 来与描述列表进行对照,该函数返回一个索引。该索引指向与制定像素格式最接近的一个描述。利用这个索引对设备环境进行设置。 也就是说,最终用来设置设备环境的像素格式的是设备环境本身维护的格式描述。这样做使得硬件免于遭受不安全的格式描述的骚扰,也可以使得程序员只关心与程序有关的描述。 有关像素格式描述部分的描述在 MSDN 文档中的描述,参见MSDN:win32 and COM development/graphics and multimedia/OpenGL/SDK document/OpenGL/ win32 extensions to openGL/ openGL on windows NT/pixelformat(2) 创建渲染环境,并且将渲染环境与当前的设备环境关联。 OpenGL 的 wgl* 函数完成相应的功能。具体做法如下(在 OnCreate 中完成)HGLRC hRC= wglCreateContext(hDC);if(!hRC)MessageBox(TEXT(Failed to create rendering context); if(!wglMakeCurrent(hDC, hRC) MessageBox(TEXT(Failed to make the rendering context the current context) HGLRC hRC= wglCreateContext(hDC); if(!hRC) MessageBox(TEXT(Failed to create rendering context); if(!wglMakeCurrent(hDC, hRC) MessageBox(TEXT(Failed to make the rendering context the current context) -第一个函数 wglCreateContext 创建一个与输入(设备环境)参数兼容渲染环境。第二个函数 wlgMakeCurrent 将输入(渲染环境)参数设置为当前的渲染环境。值得注意的是这两个函数的设备环境不一定相同,但是需要保证两个设备环境中的像素格式描述 (PFD) 是一样的。此外需要注意的是生成一个渲染环境是一个必将耗费资源的操作,因此为了保证系统的性能起见,最好在整个运行过程中只生成一次渲染环境。并且在系统退出的时候销毁。因此,具体编程的时候建议在视图类中加入一个 HGLRC 型的成员变量,用于保存生成的渲染环境,以便于程序退出的时候在类的析构函数里边释放。(3)OpenGL 的设置 从原理上讲,完成了以上的设置以后便完成了接口的设置,可以添加 WM_PAINT 消息的响应函数,在其中使用 OpenGL 进行绘图。但是还有一些问题需要注意: (1)窗口的变化 众所周知,当窗口发生变化以后相应的客户区的参数会发生变化,进而引起客户区内容重新绘制。如果不考虑这一点,就会使得图形不能很好地响应窗口形状变化。因此,在 WM_SIZE 的消息响应函数里边必须对视口进行相应的调整。假设程序需要绘制的区域要填充整个客户区。那么相应的代码如下所示:GLsizei width = cx, height = cy; GLdouble aspect; if(cy =0) aspect = (GLdouble) width; else aspect = (GLdouble)width/(GLdouble)height; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-10, 10, -10, 10, 2, 300); glMatrixMode(GL_MODELVIEW); GLsizei width = cx, height = cy; GLdouble aspect; if(cy =0) aspect = (GLdouble) width; else aspect = (GLdouble)width/(GLdouble)height; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-10, 10, -10, 10, 2, 300); glMatrixMode(GL_MODELVIEW);-注意: i glViewport 函数将绘制区域设置为整个窗口的客户区。 ii 上述例子在 WM_SIZE 消息的响应中同样设置了投影方式。具体放在下一节(2) 鼠标响应由 MFC 可以得到以窗口为参照的鼠标位置,进而可以得到以客户区为参照的鼠标位置。根据视口的位置大小参数,可以得到以视口为参照的鼠标位置进而进行命中测试。(4) 其他技巧 完成以上的步骤以后,就能够在 WM_PAINT 的响应函数里边专心使用 OpenGL 画图。假如要画一个透视投影的正方体,背景为黑色。程序代码如下:-void CMFC_OpenGL_exsp2View:OnDraw(CDC* /*pDC*/) CMFC_OpenGL_exsp2Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; / TODO: add draw code for native data here glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslated(0 , 0, 0); /Draw the cube glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, 3.0, -3.0f); glVertex3f(-3.0f, 3.0f, -3.0f); glVertex3f(-3.0f, 3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, 3.0, -3.0f); glVertex3f(3.0f, -3.0f, -3.0f); glVertex3f(3.0f, -3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, -3.0f); glVertex3f(3.0f, -3.0, -3.0f); glVertex3f(-3.0f, -3.0f, -3.0f); glVertex3f(-3.0f, 3.0f, -3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, -3.0, 3.0f); glVertex3f(-3.0f, -3.0f, 3.0f); glVertex3f(-3.0f, 3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(-3.0f, 3.0f, 3.0f); glVertex3f(-3.0f, 3.0, -3.0f); glVertex3f(-3.0f, -3.0f, -3.0f); glVertex3f(-3.0f, -3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, -3.0f, 3.0f); glVertex3f(3.0f, -3.0, -3.0f); glVertex3f(-3.0f, -3.0f, -3.0f); glVertex3f(-3.0f, -3.0f, 3.0f); glEnd(); glPopMatrix(); glDrawBuffer(GL_BACK); SwapBuffers(:GetDC(this-GetSafeHwnd(); void CMFC_OpenGL_exsp2View:OnDraw(CDC* /*pDC*/) CMFC_OpenGL_exsp2Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; / TODO: add draw code for native data here glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslated(0 , 0, 0); /Draw the cube glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, 3.0, -3.0f); glVertex3f(-3.0f, 3.0f, -3.0f); glVertex3f(-3.0f, 3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, 3.0, -3.0f); glVertex3f(3.0f, -3.0f, -3.0f); glVertex3f(3.0f, -3.0f, 3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, -3.0f); glVertex3f(3.0f, -3.0, -3.0f); glVertex3f(-3.0f, -3.0f, -3.0f); glVertex3f(-3.0f, 3.0f, -3.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(3.0f, 3.0f, 3.0f); glVertex3f(3.0f, -3.0, 3.0f); glVer

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论