《《面向对象的程序设计》课程设计作业.docx》由会员分享,可在线阅读,更多相关《《面向对象的程序设计》课程设计作业.docx(16页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、郑州大学环境与水利学院面向对象的程序设计课程设计计 算 说 明 书专 业: 地理信息系统 学生姓名: 学生学号: 指导教师: 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 t
2、each 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 f
3、rom 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场景中添加简单的光照。这一课包含了很多内容,所以如果你之前的课程仍存在问题,就先回头复习一下。学习后面的代码
4、之前,很好的理解基础知识十分重要。 我们准备在第一课的代码上稍作修改。跟以前一样,只要有任何大的改动,我都会写出整段被改动的代码。我们将以添加几个新的变量作为开始。#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 Conte
5、xtHWND 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 ligh
6、t 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。我们
7、创造了 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
8、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 x
9、speed; / 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 o
10、bjects 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
11、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.
12、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)
13、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现在,我们来设置创建光源的数组。我们将使用两种不同的光。第一种光被称为环境光。环境光是一种来自于各个方向的光。所有场景中的对象都处于环境光的照射中。第二种光被称为漫射光。漫射光由
14、特定的光源产生,并在你的场景中的对象表面上产生反射。处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显得要暗一些。这样在我们所创建的木板箱的棱边上就会产生的很不错的阴影效果。 创建光源的过程和颜色的创建过程一样。如果第一个数字是1.0f,接下来的两个数字是0.0f,我们将得到艺术明亮的蓝色光。最后一个数字是阿尔法值。我们将把它设为1.0f。所以在接下来的代码中,我们得到的是半亮(0.5f)的白色环境光。因为所有的数字都是0.5f,我们将得到一束一半黑一半白的光。红,蓝和绿混合在一起将出现从黑到白的阴影。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。GLfloat L
15、ightAmbient=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.下一行代码我们将得到最亮的漫射光。所有的参数值都
16、取成最大值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 a
17、nd 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
18、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
19、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 cr
20、ate, 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 moni
21、tor. 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 coordi
22、nates 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。假如你能够看见光源的话,它就浮在显示器的前方。当然,如果木箱不在显示器的屏幕玻璃后
23、面的话,你也无法看见箱子。没有解释三个参数的简单方法。你应该知道,-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 te
24、xture 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 w
25、ill 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(不光滑)滤波方式构建。第二种
26、纹理 (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 c
27、reate 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
28、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
29、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+都包含了gl
30、aux库,但别的语言我不确定。我只准备解释新增的代码。如果你想知道它是干什么的,请查看教程六。那一课很详细的解释了载入、创建纹理的内容。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);/ 载入 Bi
31、tmap然后返回 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 LoadGLTextu
32、res() / 载入位图并转换成纹理 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
33、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,我们将开始创建纹理。/ 载入位图,检查有错,或位
34、图不存在的话退出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.
35、现在我们已经将图像信息载入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 g
36、oing 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 typ
37、e 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 qualit
38、y 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方式。从原理上讲,这种方式没有真正进行滤波。它只占用很小的处理能力,看
39、起来也很差。唯一的好处是这样我们的工程在很快和很慢的机器上都可以正常运行。你会注意到我们在 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_FILT
40、ER,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
41、. 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,因为它是
42、我们的第二种纹理。如果我们将它像以前一样存储在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-
43、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 m
44、ipmapped 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 caus
45、es 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 automatic
46、ally 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将选择它已经创建的外观最