实验3 基于OpenGL的真实感图形渲染.doc_第1页
实验3 基于OpenGL的真实感图形渲染.doc_第2页
实验3 基于OpenGL的真实感图形渲染.doc_第3页
实验3 基于OpenGL的真实感图形渲染.doc_第4页
实验3 基于OpenGL的真实感图形渲染.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

基于OpenGL的真实感图形渲染OpenGL是一个跨平台的图形库,可在Windows、Unix、Mac等平台上运行。本书主要介绍怎样在Windows平台上建立OpenGL程序,并以Visual C+ 6.0编程环境为例来说明整个编程环境的建立和设置。2.5.1VC环境下OpenGL编程本节在VC6.0环境下介绍两种OpenGL应用程序结构:Win32 Console Application和Windows MFC。1Win32 Console Application在该OpenGL应用程序结构中,我们使用GLUT来响应、处理用户的交互操作;尽管GLUT可能无法满足编写功能完整的OpenGL应用程序的要求,但作为学习OpenGL却是一个非常好的起点。首先运行Visual C+ 6.0从“File”菜单中选择“New”菜单项,在弹出的对话框中选择”Projects”标签,如图2-28所示。然后单击“Win32 Console Application”选项,再给应用程序指定目录和名字,如工程名为“ConsoleExpl”。单击“OK”按钮,确认由Visual C+ 6.0创建一个新工程。接着,显示如图图2-29所示的对话框,用以选择应用程序的类型。选择产生一个空的应用程序,单击“Finish”按钮,这样一个新的工程框架建立完成。随后,从“File”菜单中选择“New”菜单项,在弹出的对话框中选择“New”标签,创建一个“C+ Source File”如名字为“main”,并添加到该工程中,如图2-30 所示。 图2-28 选择新工程类型 图2-29 选择应用程序类型通过如下的方法加入OpenGL的库文件:从“Project”菜单中选择“Settings”菜单项,在弹出的对话框中单击“Link”标签,在“Object/library modules”文本框中加入“opengl32.lib glu32.lib glut32.lib glew32.lib”即可,如图2-31所示。 图2-30 创建源文件加入工程 图2-31 OpenGL库文件加入当前工程完成上述步骤后,一个Windows平台下进行OpenGL应用程序开发的环境已形成,便可进入具体的编程阶段。这里,给出一个简单的的OpenGL示例程序(ConsoleExpl),代码如下,运行结果如图2-32所示。/ main.cpp#include #include static GLfloat spin = 0.0;void display(void) glClear(GL_COLOR_BUFFER_BIT); glPushMatrix();/保存模型视图矩阵 glRotatef(spin, 0.0, 0.0, 1.0); /模型旋转变换 glBegin(GL_POLYGON); glColor3f(1.0, 0.0,0.0); /设置当前颜色为红色 glVertex2f(0.0, -25.0); glColor3f(0.0, 1.0, 0.0); /设置当前颜色为绿色 glVertex2f(25.0, -12.5); glColor3f(0.0, 0.0, 1.0); glVertex2f(25.0, 12.5); glColor3f(1.0, 1.0, 0.0); glVertex2f(0, 25.0); glColor3f(1.0, 0.0, 1.0); glVertex2f(-25.0, 12.5); glColor3f(0.0, 1.0, 1.0); glVertex2f(-25.0, -12.5); glEnd(); glPopMatrix(); /恢复模型视图矩阵 glutSwapBuffers(); /交换缓冲区void spinDisplay(void) spin = spin + 2.0; if (spin 360.0) spin = spin - 360.0; glutPostRedisplay(); void init(void) /初始化绘制环境 glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH);void reshape(int w, int h) glViewport (0, 0, (GLsizei) w, (GLsizei) h); /设置视口 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0); /设置正投影 glMatrixMode(GL_MODELVIEW); glLoadIdentity();void mouse(int button, int state, int x, int y) switch (button) case GLUT_LEFT_BUTTON: if (state = = GLUT_DOWN) glutIdleFunc(spinDisplay); /左键单击进行模型旋转 break; case GLUT_MIDDLE_BUTTON: case GLUT_RIGHT_BUTTON: if (state = = GLUT_DOWN) glutIdleFunc(NULL); break; default: break; int main(int argc, char* argv) glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (250, 250); glutInitWindowPosition (100, 100); glutCreateWindow (argv0); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMainLoop(); return 0; 图2-32 ConsoleExpl程序的运行结果对该程序进行如下的简要解释:(1)窗口管理GLUT通过如下几个函数执行初始化窗口所需要的任务:glutInit(int *argc, char *argv)对GLUT进行初始化,并处理所有的命令行参数。glutInit()应该在调用其他任何GLUT函数之前调用。glutInitDisplayMode(unsigned int mode) 指定了是使用RGBA模式还是颜色索引模式(这里使用RGBA);指定是使用单缓冲还是使用双缓冲窗口(这里使用后者);还可以使用这个函数表示希望窗口拥有相关联的深度、模板、多重采样和/或累积缓冲区。例如,如果需要一个双缓冲、RGBA颜色模式以及带有一个深度缓冲区的窗口,可以调用glutInitDisplayMode(GLUT_ DOUBLE |GLUT_RGBA | GLUT_DEPTH)。glutInitWindowPosition(int x, int y) 指定了窗口左上角的屏幕位置(100,100)。glutInitWindowSize(int width, int size) 指定了窗口的大小(250, 250)(以像素为单位)。int glutCreateWindow(char *string)创建了一个支持OpenGL渲染环境的窗口。这个函数返回一个唯一的标识符,标识了这个窗口。注意:在调用glutMainLoop()函数之前,这个窗口并没有显示。(2)显示回调函数glutDisplayFunc(void (*func)(void)是极其重要的事件回调函数,每当GLUT确定一个窗口的内容需要重新显示时,通过glutDisplayFunc()注册的那个回调函数(该例为display)就会被执行。因此,应该把重绘场景所需要的所有代码都放在这个显示回调函数里。如果程序修改了窗口的内容,有时候可能需要调用glutPostRedisplay(),这个函数将会指示glutMainLoop()调用已注册的显示回调函数。(3)运行程序最后,必须调用glutMainLoop()来启动程序。所有已经创建的窗口将会在这时显示,对这些窗口的渲染也开始生效。事件处理循环开始启动,已注册的显示回调函数被触发。一旦进入循环,它就永远不会退出。(4)处理输入事件可以使用下面这些函数注册一些回调函数,当指定的事件发生时,这些函数便会被调用:glutReshapeFunc(void(*func)int w, int h)表示当窗口的大小发生改变时应该采取什么行动(该例为reshape)。glutKeyboardFunc(void(*func)(unsigned char key, int x, int y)和glutMouseFunc(void(*func)(int button, int state, int x, int y)将键盘上的一个键或鼠标上的一个按钮与一个函数相关联,当这个键或按钮被按下或释放时,这个函数就会调用(该例为mouse)。(5)空闲处理可以在glutIdleFunc(void(*func)(void)回调函数中指定一个函数,如果不存在其他尚未完成的事件(例如,当事件循环处于空闲的时候),就执行这个函数。这个回调函数接受一个函数指针作为它的唯一参数。如果向它传递NULL(0),就相当于禁用这个函数。该例中,init()函数初始化绘制环境,其中glClearColor (0.0, 0.0, 0.0, 0.0)设置背景色为黑色、glShadeModel (GL_SMOOTH)设置着色模型为平滑方式。在reshape()函数中,首先设置了视口的大小,然后设置投影方式为正投影,并切换当前矩阵为模型视图矩阵。在display()中,首先将窗口清除为当前的清除颜色,然后进行模型的旋转变换,并绘制一个多边形,最后交换缓冲区。函数spinDisplay()的作用是增大旋转角度并刷新窗口;函数mouse()通过鼠标按钮确定多边形是否进行旋转的切换。2Windows MFC为了编写功能更加完备的OpenGL应用程序,尤其是在友好的用户交互方面,可以采用Windows MFC应用程序框架;在该框架中,利用MFC消息映射机制进行各种响应的处理。由于OpenGL是一个与平台无关的三维图形接口,操作系统必须提供像素格式管理和渲染环境管理。OpenGL的绘图方式与Windows一般绘图方式是不同的,Windows一般的应用程序使用设备描述表(Device Context, DC)进行图形的绘制输出,但OpenGL并不使用标准的设备描述表,而是使用渲染描述表(Rendering Context, RC)完成图形图像的映射,其核心是像素格式的设置。(1)像素格式在进行OpenGL的绘图操作时,实际上是在进行设备像素的操作。OpenGL将数据转化为像素操作写入帧缓存中,OpenGL需要知道Windows的像素格式,或者说需要与其一致起来。在初始化OpenGL时,初始化函数需要一种叫做PIXELFORMATDESCRIPTOR的结构,来完成对像素属性的设置,包括缓存设置、颜色模式、颜色位数、深度缓存位数等。OpenGL通过PIXELFORMATDESCRIPTOR结构指定自己的像素格式,结构如下:typedef struct tag PIXELFORMATDESCRIPTOR WORD nSize; /结构大小 WORD nVersion; /结构版本 DWORD dwFlags; /告知OpenGL如何处理像素 BYTE iPixelType; /颜色模式 BYTE cColorBits; /颜色位数 BYTE cRedBits; /通常为0 BYTE cRedShift; /通常为0 BYTE cGreenBits; /通常为0 BYTE cGreenShift; /通常为0 BYTE cBlueBits; /通常为0 BYTE cBlueShift; /通常为0 BYTE cAlphaBits; /RGBA颜色缓存中Alpha的位数 BYTE cAlphaShift; /现不支持置为0 BYTE cAccumBits; /累积缓存的位数 BYTE cAccumRedBits; /基本不被采用置为0 BYTE cAccumGreenBits; /基本不被采用置为0 BYTE cAccumBlueBits; /基本不被采用置为0 BYTE cAccumAlphaBits; /基本不被采用置为0 BYTE cDepthBits; /深度缓存位数 BYTE cStencilBits; /模板缓存位数 BYTE cAuxBuffers; /辅助缓存位数 BYTE iLayerType; /层面类型 BYTE bReserved; /置0 DWORD dwLayerMask; /置0 DWORD dwVisibleMask; /置0 DWORD dwDamageMask; /置0 PIXELFORMATDESCRIPTOR; (2)渲染描述表如Widows程序的DC一样,OpenGL渲染描述表保存着在窗口中用来渲染一个场景所需的信息。一个OpenGL应用程序必须有一个RC,并且在进行OpenGL绘制之前它应该是当前的。实际上,RC是OpenGL输出与Windows DC联系的机制,在RC存入信息后,OpenGL就可以在Windows系统中更新一个窗口的图形状态。 在创建渲染描述表之前必须创造像素格式,这样,RC才知道怎样选择像素属性。RC是线性安全的,也就是说多个线程可以同时使用一个渲染描述表。在某一时刻一个线程只使用一个RC,且每个OpenGL线程必须有一个当前的RC支持工作。一般情况下,RC的管理需要以下OpenGL函数:wglCreateContext(HDC hDC):创建一个与给定的DC兼容的RC,调用成功返回RC句柄,不成功返回NULL。wglMakeCurrent(HDC hDC,HGLRC hRC):RC当前化,调用成功返回GL_TRUE,否则返回GL_FALSE。如果第二个参数为NULL,则是使当前RC非当前化。wglDeleteContext(HGLRC hRC):删除RC,成功返回GL_TRUE,否则返回GL_FALSE。wglGetCurrentContext():获取当前RC句柄。 wglGetCurrentDC():获取绑定当前RC的DC句柄。下面我们结合一个具体的OpenGL应用程序(工程名为MFCOpenGLExpl,其运行结果和ConsoleExpl一样),分步骤来介绍MFC框架下的OpenGL编程;MFCOpenGLExpl是一通用的基础框架程序,MFC框架下的OpenGL应用程序开发均可参考。描述中将涉及到Visual C+程序设计的基础知识,如数据成员变量的增加、成员函数的创建、消息响应等。第一步:建立工程。首先运行Visual C+ 6.0从“File”菜单中选择“New”菜单项,在弹出的对话框中选择”Projects”标签,如图2-33所示。然后单击“MFC AppWizard(exe)”选项,再给应用程序指定目录和名字MFCOpenGLExpl,并单击“OK”按钮。然后,在弹出的对话框中选择“Single doucument”,并单击“Finish”按钮完成一新工程的创建。图2-33 选择新工程类型第二步:设置OpenGL库。首先包含OpenGL头文件,打开工程中StdAfx.h文件,在其中包含glew.h和glut.h两个文件,如图2-34所示。然后连接OpenGL库文件,从“Project”菜单中选择“Settings”菜单项,在弹出的对话框中单击“Link”标签,在“Object/library modules”文本框中加入“opengl32.lib glu32.lib glut32.lib glew32.lib”即可,如图2-35所示。图2-34 包含OpenGL头文件图2-35 连接OpenGL库文件第三步:添加变量和函数。首先在CMFCOpenGLExplView.h文件中,添加公共数据成员变量m_hRC、 m_pDC、m_rotAngle和成员函数InitializeOpenGL()、SetupPixelFormat()和RenderScene(),如图2-36所示;并在CMFCOpenGLExplView.cpp文件的构造函数中初始化这3个变量,代码如下。图2-36 添加变量和函数CMFCOpenGLExplView:CMFCOpenGLExplView()m_hRC = NULL;m_pDC= NULL; m_rotAngle = 0.0f;利用“MFC ClassWizard”,使CMFCOpenGLExplView类响应WM_CREATE、WM_SIZE、WM_ERASEBKGND、WM_DESTROY、WM_LBUTTONDOWN、WM_RBUTTONDOWN、和WM_TIMER这7个消息,得到相应的7个消息响应函数,如图2-37所示。第四步:设置像素格式。在CMFCOpenGLExplView.cpp文件中定义SetupPixelFormat()成员函数,代码如下。BOOL CMFCOpenGLExplView: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, 32, 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) return FALSE; return TRUE;第五步:使用RC。首先在成员函数InitializeOpenGL()中创建RC,该函数在CMFCOpenGLExplView.cpp文件中定义如下。BOOL CMFCOpenGLExplView:InitializeOpenGL() m_pDC = new CClientDC(this); if(m_pDC = NULL) MessageBox(Error Obtaining DC); return FALSE; if(!SetupPixelFormat() return FALSE; m_hRC = wglCreateContext (m_pDC-GetSafeHdc ();/创建 if(m_hRC = 0) MessageBox(Error Creating RC); return FALSE; if(wglMakeCurrent (m_pDC-GetSafeHdc (), m_hRC)=FALSE) /当前化RC MessageBox(Error making RC Current); return FALSE; glShadeModel(GL_SMOOTH); /设置着色模型方式 glClearColor(0.0f,0.0f,0.0f,0.0f); /设置背景色glClearDepth(1.0f); /设置深度缓存的清除值glMatrixMode( GL_PROJECTION ); glLoadIdentity();glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);/设置正投影 return TRUE;在OnCreate()函数中调用InitializeOpenGL()函数,使得上述的工作有效,代码如下。int CMFCOpenGLExplView:OnCreate(LPCREATESTRUCT lpCreateStruct) if (CView:OnCreate(lpCreateStruct) = -1)return -1;InitializeOpenGL(); return 0;应用程序窗口销毁时,应删除RC,由OnDestroy()完成,代码如下。void CMFCOpenGLExplView:OnDestroy() CView:OnDestroy();/ 释放RC if(:wglMakeCurrent (0,0) = FALSE)MessageBox(Could not make RC non-current); if(:wglDeleteContext (m_hRC)=FALSE) MessageBox(Could not delete RC); if(m_pDC) delete m_pDC; m_pDC = NULL;第六步:绘制场景。首先在成员函数OnSize()中设置视口并切换到模型视图矩阵,该函数在CMFCOpenGLExplView.cpp文件中定义如下。void CMFCOpenGLExplView:OnSize(UINT nType, int cx, int cy) CView:OnSize(nType, cx, cy);if (cy=

温馨提示

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

评论

0/150

提交评论