1、计算机图形学上机实验指导指导教师:张加万 老师助 教:张怡2009-10-1030目 录1.计算机图形学实验 (一) OPENGL 基础 .- 1 -1.1 综述 .- 1 -1.2 在 VC 中新建项目 .- 1 -1.3 一个 OPENGL 的例子及说明 .- 1 -2.计算机图形学实验 (二) OPENGL 变换 .- 5 -2.1 变换 .- 5 -3.计算机图形学实验 (三) - 画线、画圆算法的实现 .- 9 -3.1 MFC 简介 .- 9 -3.2 VC6 的界面 .- 10 -3.3 示例的说明 .- 11 -4.计算机图形学实验(四) - 高级 OPENGL 实验 .- 1
2、4 -4.1 光照效果 .- 14 -4.2 雾化处理 .- 17 -5.计算机图形学实验(五)- 高级 OPENGL 实验 .- 21 -5.1 纹理映射 .- 21 -5.2 反走样 .- 25 -6.计算机图形学实验 (六) OPENGL IN MS-WINDOWS .- 27 -6.1 实验目标: .- 27 -6.2 分形 .- 28 -计算机图形学实验指导- 1 -1.计算机图形学实验 (一) OpenGL 基础1.1 综述这次试验的目的主要是使大家初步熟悉 OpenGL 这一图形系统的用法,编程平台是 Visual C+,它对 OpenGL 提供了完备的支持。OpenGL 提供了
3、一系列的辅助函数,用于简化 Windows 操作系统的窗口操作,使我们能把注意力集中到图形编程上,这次试验的程序就采用这些辅助函数。本次实验不涉及面向对象编程,不涉及 MFC。1.2 在 VC 中新建项目1.2.1 新建一个项目选择菜单 File 中的 New 选项,弹出一个分页的对话框,选中页 Projects 中的Win32 Console Application 项,然后填入你自己的 Project name,如 Test,回车即可。VC 为你创建一个工作区(WorkSpace ),你的项目 Test 就放在这个工作区里。1.2.2 为项目添加文件为了使用 OpenGL,我们需要在项目中
4、加入三个相关的 Lib 文件:glu32.lib、glaux.lib、opengl32.lib,这三个文件位于 c:program filesmicrosoft visual studiovc98lib 目录中。选中菜单 Project-Add To Project-Files 项(或用鼠标右键),把这三个文件加入项目,在 FileView 中会有显示。这三个文件请务必加入,否则编译时会出错。或者将这三个文件名添加到 Project-Setting-Link-Object/library Modules 即可。点击工具条中 New Text File 按钮,新建一个文本文件,存盘为 Test.
5、c 作为你的源程序文件,再把它加入到项目中,然后就可以开始编程了。1.3 一个 OpenGL 的例子及说明1.3.1 源程序 请将下面的程序写入源文件 Test.c,这个程序很简单,只是在屏幕上画两根线。计算机图形学实验指导- 2 -#include #include #include #include /初始化 OpenGL 场景void myinit (void)glClearColor (0.0, 0.0, 0.0, 0.0); /将背景置成黑色 glShadeModel (GL_FLAT); /设置明暗处理 /用户的绘图过程void CALLBACK display(void)glCl
6、ear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /清除缓存glBegin(GL_LINES); /开始画一根白线glColor3f (1.0f, 1.0f, 1.0f); /设置颜色为白色 /设置第一根线的两个端点,请注意:OpenGL 坐标系的原点是在屏幕左下角glVertex2f(10.0f, 50.0f);glVertex2f(110.0f, 50.0f);glColor3f (1.0f, 0.0f, 0.0f); /设置颜色为红色 /设置第二根线的两个端点glVertex2f(110.0f, 50.0f);glVertex2f(110.
7、0f, 150.0f);glEnd(); /画线结束glFlush (); /绘图结束/主过程:/ 初始化 Windows 的窗口界面/ 并初始化 OpenGL 场景,绘图int main(int argc, char* argv)auxInitDisplayMode (AUX_RGB); /初始化显示模式,采用 RGB 彩色系统。auxInitPosition (0, 0, 400, 150); /初始化窗口位置、大小auxInitWindow (“Display Lists“); /初始化窗口,设置标题myinit ();auxMainLoop(display); /循环运行 displa
8、y 过程,display 由用户编写return(0);1.3.2 程序说明 计算机图形学实验指导- 3 -每个函数的具体含义在程序注释中已作了叙述,不再多说。OpenGL 的函数在格式上很有特点,它以 gl 为前缀,并且函数名的最后一个字母指出所用的数据类型,如:glColor3f(),字母 f 指明要使用浮点数。字母前的数字指明参数个数或指明二维还是三维,如:glVertex2f()是要设置二维的点。OpenGL 采用的是状态机的方式,用户设定一种状态,程序照此运行。如:glBegin(GL_LINES)设定画线状态(GL_LINES 是 OpenGL 已定义好的常量),glColor3f
9、()设定绘图所用颜色。main()函数中的几个 aux 前缀函数是 OpenGL 提供的辅助库,用以初始化窗口,大家不必深究,我们关注的是 display()函数,它是我们真正绘图的地方。函数 glColor3f()以 RGB 方式设置颜色,格式为: glColor3f(red, green, blue),每种颜色值在(0.0, 1.0)之间。为了能显示更多的颜色,最好把系统设置成 16位真彩色模式。函数 glVertex2f(x, y)设置二维顶点。函数 glBegin(UINT State)、glEnd()是最基本的作图函数,下面对它作一介绍。如上所述,OpenGL 是一个状态机,glBe
10、gin(UINT State)可以设定如下状态:GL_POINTS 画点GL_LINES 画线,每两个顶点(Vertex) 为一组GL_LINE_STRIP 画线,把若干个顶点顺次连成折线GL_LINE_LOOP 画线,把若干个顶点顺次连成封闭折线GL_TRIANGLES画三角形,每三个顶点为一组GL_QUADS 画四边形,每四个顶点为一组GL_POLYGON 画多边形还有 GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS_STRIP 等等。大家可以把每一种状态都试一试。程序可以有多组 glBegin()、glEnd()并列的形式,如:. .glBein
11、g(GL_LINES);.glEnd();glBeing(GL_QUADS);. .glEnd();. .计算机图形学实验指导- 4 -除了上述的基本图元外,函数 glRectf(x1, y1, x2, y2)可以画一个矩形,但这个函数不能放在 glBegin()和 glEnd()之间,下面的两句程序是画一个蓝色的矩形。glColor3f (0.0f, 0.0f, 1.0f);glRectf(10.0f, 10.0f, 50.0f,50.0f);教材中给出的例子,同学们可以对这些代码也进行测试。 计算机图形学实验指导- 5 -2.计算机图形学实验 (二) OpenGL 变换2.1 变换下面向大
12、家介绍 OpenGL 中坐标变换的方法,以下这个例子是模拟机器人的手臂,用上下左右键可以挥动。#include #include #include #include void myinit(void);void CALLBACK elbowAdd (void);void CALLBACK elbowSubtract (void);void CALLBACK shoulderAdd (void);void CALLBACK shoulderSubtract (void);void CALLBACK display(void);void CALLBACK myReshape(GLsizei w,
13、GLsizei h);static int shoulder = 0, elbow = 0;/shoulder:肩部角度,elbow: 肘部角度/下面四个函数是用户的键盘事件处理程序void CALLBACK elbowAdd (void) elbow = (elbow + 5) % 360;void CALLBACK elbowSubtract (void) elbow = (elbow - 5) % 360;void CALLBACK shoulderAdd (void) shoulder = (shoulder + 5) % 360;void CALLBACK shoulderSubtr
14、act (void) shoulder = (shoulder - 5) % 360;/用户的绘图过程void CALLBACK display(void)glClear(GL_COLOR_BUFFER_BIT);glColor3f (1.0, 1.0, 1.0);glPushMatrix();/把当前的变换矩阵压入 OpenGL 内部栈中,用以保存当前矩阵/画机器人的上臂glTranslatef (-1.0, 0.0, 0.0);计算机图形学实验指导- 6 -/用平移矩阵乘当前矩阵,格式为:glTranslatef(x,y,z)glRotatef (GLfloat) shoulder, 0.
15、0, 0.0, 1.0);/用旋转矩阵乘当前矩阵,格式/为 glRotatef (角度,x 轴,y/轴,z 轴)/这里是绕 Z 轴旋转glTranslatef (1.0, 0.0, 0.0); /再用平移矩阵乘当前矩阵,注意顺序auxWireBox(2.0, 0.4, 1.0); /辅助库函数,画一个三维的/Box,格式为: /auxWireBox(width, height, depth)/画机器人的前臂,请注意平移矩阵和旋转矩阵的变化glTranslatef (1.0, 0.0, 0.0);glRotatef (GLfloat) elbow, 0.0, 0.0, 1.0);glTransl
16、atef (1.0, 0.0, 0.0);auxWireBox(2.0, 0.4, 1.0);glPopMatrix(); /恢复刚才的矩阵glFlush(); /结束绘图void myinit (void) glShadeModel (GL_FLAT);/在窗口改变大小时调用void CALLBACK myReshape(GLsizei width, GLsizei height)glViewport(0, 0, width, height); /定义视口glMatrixMode(GL_PROJECTION); /定义投影变换模式glLoadIdentity(); /用单位矩阵替换当前变换矩
17、阵gluPerspective(65.0, (GLfloat) width/(GLfloat) height, 1.0, 20.0);/建立一个透视投影矩阵,并乘当前矩阵,格式为:/ gluPerspective(视域的角度,宽高比,/视点到近裁剪面的距离(总为正),/视点到远裁剪面的距离(总为正)glMatrixMode(GL_MODELVIEW); /定义造型变换模式glLoadIdentity(); /用单位矩阵替换当前变换矩阵glTranslatef (0.0, 0.0, -5.0); /用平移矩阵乘当前矩阵/ 主过程:/ 初始化 Windows 的窗口界面/ 并初始化 OpenGL
18、场景,并处理输入事件,如:键盘,鼠标的操作int main(int argc, char* argv)auxInitDisplayMode (AUX_SINGLE | AUX_RGB);auxInitPosition (0, 0, 400, 400);auxInitWindow (“Composite Modeling Transformations“);myinit ();计算机图形学实验指导- 7 -/定义键盘处理程序,格式:auxKeyFunc(按键的虚拟代码,用户的处理函数名)auxKeyFunc (AUX_LEFT, shoulderSubtract);/函数 shoulderSub
19、tract()处理左 /方向键auxKeyFunc (AUX_RIGHT, shoulderAdd);/函数 shoulderAdd()处理右方向键auxKeyFunc (AUX_UP, elbowAdd); /函数 elbowAdd()处理上方向键auxKeyFunc (AUX_DOWN, elbowSubtract); /函数 elbowSubtract()处理下方向 /键auxReshapeFunc (myReshape); /定义窗口大小改变时调用的函数auxMainLoop(display); /循环运行 display 过程,display 由用户编写return(0);这个例子涉
20、及了三维的造型,出现了许多新函数。auxKeyFunc ()实现了人机的键盘交互,思路和 Windows 编程的消息处理完全一样。AUX_LEFT 是预定义好的常量,类似的常量还有很多,下面再列出一部分:AUX_RETURN、AUX_ESCAPE 、AUX_SPACE 、 AUX_A、AUX_B 、AUX_C、AUX_D 等等。例子中的四个处理函数只是改变一下肩和肘的角度,以使手臂能动起来。auxReshapeFunc ()事实上也是定义消息处理, myReshape()所作的工作主要就是通过一系列的投影和造型变换,把三维的场景映射到二维的视口上,再通过视口将坐标转换到窗口坐标,并随窗口的改变
21、而改变。OpenGL 的 Z 轴垂直屏幕,你目光的方向是其负向,视点位于原点。myReshape()中最后一句glTranslatef (0.0, 0.0, -5.0)等于把你的视点移到了 Z 轴+5.0 处。display()中用到了 glPushMatrix()和 glPopMatrix(),事实上 glPushMatrix()可以理解为建立一个局部坐标系,glPopMatrix()恢复全局坐标系,它们可以嵌套使用。这两个函数会很频繁的用到。auxWireBox()画的是一个线框的 Box,这样的函数还有auxWireSphere(radius);auxSolidSphere(radius
22、);auxWireCube(size);auxSolidCube(size);auxWireTorus(innerRadius, outerRadius);auxSolidTorus(innerRadius, outerRadius);auxWireCylinder(radius, height);auxSolidCylinder(radius, height);计算机图形学实验指导- 8 -上面的例子里用 glTranslatef (0.0, 0.0, -5.0)模拟了视点的变换,其实这一句可以放到 display()中,效果是一样的,由于 display()是不断被调用的,所以你的视点就可
23、以不断改变,当然你也可以旋转变换视点,但请注意,变换方向一定要相反。再与 glPushMatrix()和 glPopMatrix()相配合,就可以作出在场景里巡游的效果。还有一个方法可以改变视点,函数gluLookAt(eye_x, eye_y, eye_z, centerx, centery, centerz, upx, upy, upz)参数:eyex, eyey, eyez 指定视点的位置centerx, centery, centerz指定参考点(“ 目光” 的焦点)upx, upy, upz指定向上向量的方向请同学任选一种方法,使你的视点尽量任意改变,只有从这时起,你才是真正进入了 VR(Virtual Reality)世界。要获得更详尽的资料,请按 F1 参考联机帮助。