《面向对象的程序设计》课程设计作业.docx_第1页
《面向对象的程序设计》课程设计作业.docx_第2页
《面向对象的程序设计》课程设计作业.docx_第3页
《面向对象的程序设计》课程设计作业.docx_第4页
《面向对象的程序设计》课程设计作业.docx_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

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

文档简介

郑州大学环境与水利学院面向对象的程序设计课程设计计 算 说 明 书专 业: 地理信息系统 学生姓名: 学生学号: 指导教师: 2011年 12 月 7 日Lesson 07 Texture Filters, Lighting & Keyboard Control第八课 纹理滤波方式,和键盘控制In this tutorial Ill teach you how to use three different texture filters. Ill teach you how to move an object using keys on the keyboard, and Ill also teach you how to apply simple lighting to your OpenGL scene. Lots covered in this tutorial, so if the previous tutorials are giving you problems, go back and review. Its important to have a good understanding of the basics before you jump into the following code. Were going to be modifying the code from lesson one again. As usual, if there are any major changes, I will write out the entire section of code that has been modified. Well start off by adding a few new variables to the program.这一课我将教你如何使用三种不同的纹理滤波方式。我将教你如何使用键盘来移动场景中的对象,还会教你在OpenGL场景中添加简单的光照。这一课包含了很多内容,所以如果你之前的课程仍存在问题,就先回头复习一下。学习后面的代码之前,很好的理解基础知识十分重要。 我们准备在第一课的代码上稍作修改。跟以前一样,只要有任何大的改动,我都会写出整段被改动的代码。我们将以添加几个新的变量作为开始。#include/ Window头文件#include/ Standard Input/Output(ADD)头文件#include/ The OpenGL32 Library头文件#include/ The GLu32 Library头文件#include/ The GLaux Library头文件HDC hDC=NULL; / GDI Device ContextHGLRC hRC=NULL; / Rendering ContextHWND hWnd=NULL; / 窗体Window句柄HINSTANCE hInstance; / 程序Instance句柄bool keys256; / 用于键盘控制的矩阵bool active=TRUE; / 窗体激活标志bool fullscreen=TRUE; / 全屏标志,缺省为真The lines below are new. Were going to add three boolean variables. BOOL means the variable can only be TRUE or FALSE. We create a variable called light to keep track of whether or not the lighting is on or off. The variables lp and fp are used to store whether or not the L or F key has been pressed. Ill explain why we need these variables later on in the code. For now, just know that they are important下面几行是新的。我们将增加三个布尔变量。BOOL意味着变量只能是TRUE和FALSE。我们创造了 light 变量跟踪光照是否打开。变量lp和fp用来存储L 和F键是否按下。后面我会解释为什么我们在代码中需要这些变量。现在,仅仅先记住他们很重要。BOOL light; / 光源的开/关BOOL lp; / L键按下了么?BOOL fp; / F键按下了么?Now were going to set up five variables that will control the angle on the x axis (xrot), the angle on the y axis (yrot), the speed the crate is spinning at on the x axis (xspeed), and the speed the crate is spinning at on the y axis (yspeed). Well also create a variable called z that will control how deep into the screen (on the z axis) the crate is现在我们设置5个变量来控制绕x轴和y轴旋转角度的步长,以及绕x轴和y轴的旋转速度。另外我们还创建了一个z变量来控制进入屏幕的深度。GLfloat xrot; / X 旋转GLfloat yrot; / Y 旋转GLfloat xspeed; / X 旋转速度GLfloat yspeed; / Y 旋转速度GLfloat z=-5.0f; / 深入屏幕的距离Now we set up the arrays that will be used to create the lighting. Well use two different types of light. The first type of light is called ambient light. Ambient light is light that doesnt come from any particular direction. All the objects in your scene will be lit up by the ambient light. The second type of light is called diffuse light. Diffuse light is created by your light source and is reflected off the surface of an object in your scene. Any surface of an object that the light hits directly will be very bright, and areas the light barely gets to will be darker. This creates a nice shading effect on the sides of our crate. Light is created the same way color is created. If the first number is 1.0f, and the next two are 0.0f, we will end up with a bright red light. If the third number is 1.0f, and the first two are 0.0f, we will have a bright blue light. The last number is an alpha value. Well leave it at 1.0f for now. So in the line below, we are storing the values for a white ambient light at half intensity (0.5f). Because all the numbers are 0.5f, we will end up with a light thats halfway between off (black) and full brightness (white). Red, blue and green mixed at the same value will create a shade from black(0.0f) to white(1.0f). Without an ambient light, spots where there is no diffuse light will appear very dark现在,我们来设置创建光源的数组。我们将使用两种不同的光。第一种光被称为环境光。环境光是一种来自于各个方向的光。所有场景中的对象都处于环境光的照射中。第二种光被称为漫射光。漫射光由特定的光源产生,并在你的场景中的对象表面上产生反射。处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显得要暗一些。这样在我们所创建的木板箱的棱边上就会产生的很不错的阴影效果。 创建光源的过程和颜色的创建过程一样。如果第一个数字是1.0f,接下来的两个数字是0.0f,我们将得到艺术明亮的蓝色光。最后一个数字是阿尔法值。我们将把它设为1.0f。所以在接下来的代码中,我们得到的是半亮(0.5f)的白色环境光。因为所有的数字都是0.5f,我们将得到一束一半黑一半白的光。红,蓝和绿混合在一起将出现从黑到白的阴影。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。GLfloat LightAmbient=0.5f,0.5f,0.5f,1.0f; / 环境光参数In the next line were storing the values for a super bright, full intensity diffuse light. All the values are 1.0f. This means the light is as bright as we can get it. A diffuse light this bright lights up the front of the crate nicely.下一行代码我们将得到最亮的漫射光。所有的参数值都取成最大值1.0f。这意味着这束光和我们能得到的一样亮。它将照在我们木板箱的前面。 GLfloat LightDiffuse=1.0f,1.0f,1.0f,1.0f;/ 漫射光参数Finally we store the position of the light. The first three numbers are the same as glTranslates three numbers. The first number is for moving left and right on the x plane, the second number is for moving up and down on the y plane, and the third number is for moving into and out of the screen on the z plane. Because we want our light hitting directly on the front of the crate, we dont move left or right so the first value is 0.0f (no movement on x), we dont want to move up and down, so the second value is 0.0f as well. For the third value we want to make sure the light is always in front of the crate. So well position the light off the screen, towards the viewer. Lets say the glass on your monitor is at 0.0f on the z plane. Well position the light at 2.0f on the z plane. If you could actually see the light, it would be floating in front of the glass on your monitor. By doing this, the only way the light would be behind the crate is if the crate was also in front of the glass on your monitor. Of course if the crate was no longer behind the glass on your monitor, you would no longer see the crate, so it doesnt matter where the light is. Does that make sense? Theres no real easy way to explain the third parameter. You should know that -2.0f is going to be closer to you than -5.0f. and -100.0f would be WAY into the screen. Once you get to 0.0f, the image is so big, it fills the entire monitor. Once you start going into positive values, the image no longer appears on the screen cause it has gone past the screen. Thats what I mean when I say out of the screen. The object is still there, you just cant see it anymore. Leave the last number at 1.0f. This tells OpenGL the designated coordinates are the position of the light source. More about this in a later tutorial最后我们保存光源的位置。前三个参数和glTranslate中的一样。依次分别是XYZ轴上的位移。由于我们想要光线直接照射在木箱的正面,所以XY轴上的位移都是0.0f。第三个值是Z轴上的位移。为了保证光线总在木箱的前面,所以我们将光源的位置朝着观察者挪出屏幕。我们通常将屏幕也就是显示器的屏幕玻璃所处的位置称作Z轴的0.0f点。所以Z轴上的位移最后定为2.0f。假如你能够看见光源的话,它就浮在显示器的前方。当然,如果木箱不在显示器的屏幕玻璃后面的话,你也无法看见箱子。没有解释三个参数的简单方法。你应该知道,-2.0f比 -5.0f更接近你。-100.0f将成为进入屏幕的方法。一旦你得到了0.0f,图像就大了,它充满了监视设备,一旦你进入,图像不再在屏幕上显示造成它已经穿过屏幕。这就是我所说的穿出屏幕。物体还在,只是你看不见了。最后一个参数取为1.0f。这将告诉OpenGL这里指定的坐标就是光源的位置,以后的教程中我会有更多解释。GLfloat LightPosition=0.0f,0.0f,2.0f,1.0f; / 光源位置The filter variable below is to keep track of which texture to display. The first texture (texture 0) is made using gl_nearest (no smoothing). The second texture (texture 1) uses gl_linear filtering which smooths the image out quite a bit. The third texture (texture 2) uses mipmapped textures, creating a very nice looking texture. The variable filter will equal 0, 1 or 2 depending on the texture we want to use. We start off with the first texture. GLuint texture3 creates storage space for the three different textures. The textures will be stored at texture0, texture1 and texture2.filter 变量跟踪显示时所采用的纹理类型。第一种纹理(texture 0) 使用gl_nearest(不光滑)滤波方式构建。第二种纹理 (texture 1) 使用gl_linear(线性滤波) 方式,离屏幕越近的图像看起来就越光滑。第三种纹理 (texture 2) 使用 mipmapped滤波方式,这将创建一个外观十分优秀的纹理。根据我们的使用类型,filter 变量的值分别等于 0, 1 或 2 。下面我们从第一种纹理开始。 GLuint texture3 为三种不同纹理分配储存空间。它们分别位于在 texture0, texture1 和 texture2中GLuint filter; / 滤波类型GLuint texture3; / 3种纹理的储存空间Now we load in a bitmap, and create three different textures from it. This tutorial uses the glaux library to load in the bitmap, so make sure you have the glaux library included before you try compiling the code. I know Delphi, and Visual C+ both have glaux libraries. Im not sure about other languages. Im only going to explain what the new lines of code do, if you see a line I havent commented on, and youre wondering what it does, check tutorial six. It explains loading, and building texture maps from bitmap images in great detail. Immediately after the above code, and before ReSizeGLScene(), we want to add the following section of code. This is the same code we used in lesson 6 to load in a bitmap file. Nothing has changed. If youre not sure what any of the following lines do, read tutorial six. It explains the code below in detail.现在我们载入一个位图,并用它创建三种不同的纹理。这一课使用glaux文库来载入位图,因此在编译时你应该确认是否包含了glaux库。我知道Delphi和VC+都包含了glaux库,但别的语言我不确定。我只准备解释新增的代码。如果你想知道它是干什么的,请查看教程六。那一课很详细的解释了载入、创建纹理的内容。AUX_RGBImageRec*LoadBMP(char*Filename)/载入 A Bitmap 图像FILE *File=NULL;/文件句柄if (!Filename)/确A 的文件名为Givenreturn NULL;/错误返回 NULLFile=fopen(Filename,r);/ 检查文件是否存在if (File)/ 文件存在吗?fclose(File);/关闭句柄return auxDIBImageLoad(Filename);/ 载入 Bitmap然后返回 A Pointerreturn NULL;/如果载入失败返回 NULLThis is the section of code that loads the bitmap (calling the code above) and converts it into 3 textures. Status is used to keep track of whether or not the texture was loaded and created.这段代码调用前面的代码载入位图,并将其转换成3个纹理。Status 变量跟踪纹理是否已载入并被创建了。int LoadGLTextures() / 载入位图并转换成纹理 int Status=FALSE; / 状态指示器AUX_RGBImageRec *TextureImage1; / 创建纹理的存储空间memset(TextureImage,0,sizeof(void*)*1);/ 将指针设为 NULLNow we load the bitmap and convert it to a ,TextureImage0=LoadBMP(Data/Crate.bmp) will jump to our LoadBMP() code. The file named Crate.bmp in the Data directory will be loaded. If everything goes well, the image data is stored in TextureImage0, Status is set to TRUE, and we start to build our texture现在我们载入位图并转换成纹理。TextureImage0=LoadBMP(Data/Crate.bmp)调用我们的LoadBMP()函数。Data目录下的Crate.bmp将被载入。如果一切正常,图像信息将存放在TextureImage0。Status变量被设为TRUE,我们将开始创建纹理。/ 载入位图,检查有错,或位图不存在的话退出if (TextureImage0=LoadBMP(Data/Crate.bmp)Status=TRUE;/ 状态设为 TRUENow that weve loaded the image data into TextureImage0, well use the data to build 3 textures. The line below tells OpenGL we want to build three textures, and we want the texture to be stored in texture0, texture1 and texture2.现在我们已经将图像信息载入TextureImage0。我们将用它来创建3个纹理。下面的行告诉OpenGL我们要创建三个纹理,我们想让这些纹理存放在texture0, texture1 和 texture2 中。glGenTextures(3, &texture0);/ 创建纹理In tutorial six, we used linear filtered texture maps. They require a hefty amount of processing power, but they look real nice. The first type of texture were going to create in this tutorial uses GL_NEAREST. Basically this type of texture has no filtering at all. It takes very little processing power, and it looks real bad. If youve ever played a game where the textures look all blocky, its probably using this type of texture. The only benefit of this type of texture is that projects made using this type of texture will usually run pretty good on slow computers. Youll notice were using GL_NEAREST for both the MIN and MAG. You can mix GL_NEAREST with GL_LINEAR, and the texture will look a bit better, but were intested in speed, so well use low quality for both. The MIN_FILTER is the filter used when an image is drawn smaller than the original texture size. The MAG_FILTER is used when the image is bigger than the original texture size. 在第六课,我们使用了线性滤波的纹理贴图。这需要机器有相当高的处理能力,但它们看起来很不错。这一课中,我们接着要创建的第一种纹理使用 GL_NEAREST方式。从原理上讲,这种方式没有真正进行滤波。它只占用很小的处理能力,看起来也很差。唯一的好处是这样我们的工程在很快和很慢的机器上都可以正常运行。你会注意到我们在 MIN 和 MAG 时都采用了GL_NEAREST,你可以混合使用 GL_NEAREST 和 GL_LINEAR。纹理看起来效果会好些,但我们更关心速度,所以全采用低质量贴图。MIN_FILTER在图像绘制时小于贴图的原始尺寸时采用。MAG_FILTER在图像绘制时大于贴图的原始尺寸时采用。 / 创建 Nearest 滤波贴图 glBindTexture(GL_TEXTURE_2D, texture0); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage0-sizeX, TextureImage0-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage0-data);The next texture we build is the same type of texture we used in tutorial six. Linear filtered. The only thing that has changed is that we are storing this texture in texture1 instead of texture0 because its our second texture. If we stored it in texture0 like above, it would overwrite the GL_NEAREST texture (the first texture).接下来我们要创建的纹理跟第六节的是同一种类型。唯一改变的是我们将这种纹理存储在texture1而不是在texture0,因为它是我们的第二种纹理。如果我们将它像以前一样存储在texture0中,它将超出GL_NEAREST纹理(第一种纹理)/ 创建线性滤波纹理glBindTexture(GL_TEXTURE_2D, texture1);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage0-sizeX, TextureImage0-sizeY,0,GL_RGB,GL_UNSIGNED_BYTE, TextureImage0-data);Now for a new way to make textures. Mipmapping! You may have noticed that when you make an image very tiny on the screen, alot of the fine details disappear. Patterns that used to look nice start looking real bad. When you tell OpenGL to build a mipmapped texture OpenGL tries to build different sized high quality textures. When you draw a mipmapped texture to the screen OpenGL will select the BEST looking texture from the ones it built (texture with the most detail) and draw it to the screen instead of resizing the original image (which causes detail loss). I had said in tutorial six there was a way around the 64,128,256,etc limit that OpenGL puts on texture width and height. gluBuild2DMipmaps is it. From what Ive found, you can use any bitmap image you want (any width and height) when building mipmapped textures. OpenGL will automatically size it to the proper width and height. Because this is texture number three, were going to store this texture in texture2. So now we have texture0 which has no filtering, texture1 which uses linear filtering, and texture2 which uses mipmapped textures. Were done building the textures for this tutorial.现在有一个创建纹理的新方法。 Mipmapping!你可能会注意到当屏幕上的图像变得很小时,很多细节会消失。刚才还很不错的图案变得很难看。当你告诉OpenGL创建一个 mipmapped的纹理后,OpenGL将尝试创建不同尺寸的高质量纹理。当你向屏幕绘制一个 mipmapped纹理的时候,OpenGL将选择它已经创建的外观最佳的纹理(带有更多细节)来绘制,而不仅仅是缩放原先的图像(这将导致细节丢失)。 我曾经说过有办法可以绕过OpenGL对纹理宽度和高度为64、128、256的限制,等等。办法就是 gluBuild2DMipmaps。据我的发现,你可以使用任意的位图来创建纹理。OpenGL将自动将它缩放到正常的大小。 因为是第三个纹理,我们将它存到texture2。现在我们有没有经过过滤的texture0,用直线过滤的texture1,和用mipmapped纹理的texture2。这样本课中的三个纹理全都创建好了。/ 创建 MipMapped 纹理glBindTexture(GL_TEXTURE_2D, texture2);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);The following line builds the mipmapped texture. Were creating a 2D texture using three colors (red, green, blue). TextureImage0-sizeX is the bitmaps width, TextureImage0-sizeY is the bitmaps height, GL_RGB means were using Red, Green, Blue colors in that order. GL_UNSIGNED_BYTE means the data that makes the texture is made up of bytes, and TextureImage0-data points to the bitmap data that were building the texture from.下面一行生成 mipmapped 纹理。我们使用三种颜色(红,绿,蓝)来生成一个2D纹理。TextureImage0-sizeX 是位图宽度,extureImage0-sizeY 是位图高度,GL_RGB意味着我们依次使用红,绿,蓝三种色彩。GL_UNSIGNED_BYTE 意味着纹理数据的单位是字节。TextureImage0-data指向我们创建纹理所用的位图。gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage0-sizeX, TextureImage0-sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage0-data); Now we free up any ram that we may have used to store the bitmap data. We check to see if the bitmap data was stored in TextureImage0. If it was we check to see if the data has been stored. If data was stored, we erase it. Then we free the image structure making sure any used memory is freed up.现在我们释放用来存放位图数据的内存。我们先查看位图数据是否存放在 TextureImage0 中,如果有,我们删掉它。然后释放位图结构以确保内存被释放。 if (TextureImage0) / 纹理是否存在 if (TextureImage0-data) / 纹理图像是否存在 free(TextureImage0-data);/ 释放纹理图像占用的内存 free(TextureImage0); / 释放图像结构 Finally we return the status. If everything went OK, the variable Status will be TRUE. If anything went wrong, Status will be FALSE. 最后我们返回 status 变量。如果一切顺利,status 变量的值为TRUE。如果出现任何问题,则为FALSE。 return Status; / 返回 Status 变量Now we load the textures, and initialize the OpenGL settings. The first line of InitGL loads the textures using the code above. After the textures have been created, we enable 2D texture mapping with glEnable(GL_TEXTURE_2D). The shade mode is set to smooth shading, The background color is set to black, we enable depth testing, then we enable nice perspective calculations现在我们载入纹理,然后初始化OpenGL设置了。InitGL函数的第一行使用上面的代码载入纹理。创建纹理之后,我们调用glEnable(GL_TEXTURE_2D)启用2D纹理映射。阴影模式设为平滑阴影。背景色设为黑色,我们启用深度测试,然后我们用优化透视计算。int InitGL(GLvoid)/设置 OpenGL 至此if (!LoadGLTextures()/ 跳至纹理载入程序return FALSE;/ 如果纹理未被载入返回FALSEglEnable(GL_TEXTURE_2D);/启用纹理显示glShadeModel(GL_SMOOTH);/启用阴影平滑glClearColor(0.0f, 0.0f, 0.0f, 0.5f);/ 背景色为黑色glClearDepth(1.0f);/调整缓冲区深度glEnable(GL_DEPTH_TEST);/启用深度测试glDepthFunc(GL_L

温馨提示

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

评论

0/150

提交评论