ImageVerifierCode 换一换
格式:DOCX , 页数:36 ,大小:125.29KB ,
资源ID:10187442      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10187442.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(源码来自Opegl高级编程.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

源码来自Opegl高级编程.docx

1、源码来自Opegl高级编程源码来自Opegl高级编程第7章首先我们看他的初始化函数ripple_init(int w,int h)这里传入了个窗口的大小(高和宽),glEnable(GL_TEXTURE_2D);这个函数打开2D纹理模式glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);设置贴图模式OpenGL提供了3种不同的贴图模式:GL_MODULATE,GL_DECAL和GL_BLEND。默认情况下,贴图模式是GL_MODULATE,在这种模式下,OpenGL会根据当前的光照系统调整物体的色彩和明暗。第二种模式是GL_DECA

2、L,在这种模式下所有的光照效果都是无效的,OpenGL将仅依据纹理贴图来绘制物体的表面。最后是GL_BLEND,这种模式允许我们使用混合纹理。在这种模式下,我们可以把当前纹理同一个颜色混合而得到一个新的纹理。我们可以调用glTexEnvi函数来设置当前贴图模式:纹理过滤函数glTexParameteri() 图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素.GL_TEXTURE_2D: 操作2D纹理. GL_TEXTURE_WRAP_S: S方向上的贴图模式.

3、GL_CLAMP: 将纹理坐标限制在0.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1-sizeX, image1-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1-data)指定纹理数据,也就是图像接下来for (i = 0; i RIPPLE_COUNT; i+) ti = ripple_max + RIPPLE_LENGTH;/这里初始化水波的步长,也就是水波的扩散速度 cxi = 0;/这里初始化第N个水波X坐标 cyi = 0;/这里

4、初始化第N个水波Y坐标 maxi = 0;/这里初始化水波最大个数 接下来就是初始化顶点数据 for (i = 0; i GRID_SIZE_X; i+) for (j = 0; j GRID_SIZE_Y; j+) ripple_vertexij.x0 = i/(GRID_SIZE_X - 1.0)*w;/当前绘图的顶点数据 ripple_vertexij.x1 = j/(GRID_SIZE_Y - 1.0)*h; ripple_vertexij.dt0 = i/(GRID_SIZE_X - 1.0);/默认绘制的纹理数据 ripple_vertexij.dt1 = j/(GRID_SIZE

5、_Y - 1.0); 上面初始化完之后就可以调用ripple_redraw()/进行绘图功能了 int i, j; glClear(GL_COLOR_BUFFER_BIT);/这个函数我就不多说了,一看就知道是干什么的 /glBindTexture(GL_TEXTURE_2D, texture0);checkGlError(glBindTexture); glEnableClientState(GL_VERTEX_ARRAY); checkGlError(glEnableClientState is for GL_VERTEX_ARRAY);/打开顶点数组功能,使之支持顶点数组的绘制 glEn

6、ableClientState(GL_TEXTURE_COORD_ARRAY); checkGlError(glEnableClientState is for GL_TEXTURE_COORD_ARRAY);/打开纹理数组功能,使之支持纹理功能的绘制 glTexCoordPointer(2,GL_FLOAT,0,Textcoord);/纹理数组 glVertexPointer(2,GL_FLOAT,0,VertexPointer);/顶点数组 glDrawArrays(GL_TRIANGLE_STRIP,0,(GRID_SIZE_X-1)*(GRID_SIZE_Y-1)*4);/,跟据顶点数

7、组和纹理数组, 开始执行上面的纹理数据 glDisableClientState(GL_VERTEX_ARRAY); checkGlError(glDisableClientState);/恢愎顶点数组功能 glDisableClientState(GL_TEXTURE_COORD_ARRAY); checkGlError(glDisableClientState);纹理贴图和顶点之间的影射,我下面给出例子,下面对纹理的基础详细地说下毕竟这是程序的核心: 纹理贴图,从本质上讲,是一个位图图像。在程序中,一个纹理图像就是一个一维或二维数组,存储每一个像素的颜色值(包括R、G、B、A分值,分别存储

8、一个像素的红、绿、蓝、透明度分值)。而运用一个纹理贴图,就是把纹理图像根据纹理坐标对应到图元上。 比如,现在有一个三角形,顶点坐标分别是V1、V2、V3,以及一幅纹理图像,现在,我们可以在绘制三角形之前,为顶点V1、V2、V3指定纹理坐标,使每一个顶点的坐标和它的纹理坐标一一对应一旦我们建立起这种对应关系,就可以开启纹理贴图功能,让OpenGL根据顶点的贴图坐标渲染出指定的三角形这就是纹理贴图的原理。至此我们明白了opengl的纹理基础,稍做变换就能纹出我们需要的图形出来,下面我们讲解水波原理原理来自上面的网站,有兴趣的同学们可以去看看我英文不好,暂时对这以下的话做我理解的翻译吧,如有不妥之处

9、请指正(欢迎给我送花和扔鸡蛋_):Well, firstly, youll need 2 arrays of words (integers). Yes, thats right, words, not bytes. These arrays will hold the state of the water. One holds the current state, the other holds the state from the previous frame. It is important that you have 2 arrays, since you need to know h

10、ow the water has changed since the last frame, and the frame before that. 首先我们需要一个2个整型数组,使用这些数组保存前一帧的阵列和当前的状态,现在你有两个数组,一个用改变的帧,一个用于你之前的帧Data from the previous frame (Buffer2) and the frame before that (Buffer1) are used together, and the results written into Buffer1.Buffer1 contains the current stat

11、e of the water.前两个数据帧Buff1帧和buffer2帧进行&操作的结果影响到Buffer1当前内容水的状态damping = some non-integer between 0 and 1Damping=01之间的小数0阻值最大,1是没有阻力 begin loop for every non-edge element: loop Buffer2(x, y) = (Buffer1(x-1,y) Buffer1(x+1,y) Buffer1(x,y+1) Buffer1(x,y-1) / 2 - Buffer2(x,y) Buffer2(x,y) = Buffer2(x,y)

12、* damping end loop Display Buffer2 Swap the buffers end loopTo explain how and why this works, imagine a wave traveling across a 1-Dimensional surface (wave 0). This wave is traveling to the left. The small vertical arrows indicate the rate at which the water level changes with time. The fainter wav

13、es show the waves positions on previous frames. So how do we achieve the correct changes in height for each part of the wave (vertical arrows)? You may notice that the height of the wave two frames older (wave 2), is proportional to the size of the arrows. So as long as the previous two frames are r

14、emembered, it is easy to work out the change in height of every part of the wave.So, take a look at the code again. When the loop starts, Buffer1 contains the state of the water from the previous frame (wave 1), and Buffer2 has the state before that (wave 2). Buffer2 therefore has information about

15、the vertical velocity of the wave.为了说明这工作方式,想象一下波的移动过程,小的垂直箭头指示水位的变化随时间速度而变化,用前一帧的波浪数据显示波浪,因此我们得如何实现改变箭头正确的垂直高度从而改变每一部份波?您可能注意到前二帧波的高度(wave2)和箭头是成正比的,因此只要记住前两帧就能得出了改变波高度的部份因此我们需要看代码,当循环开始,buffer1包含第一帧水的状态数据与之前的bueffer2状态,因此得出关于buffer2的垂直波的速度,Velocity(x, y) = -Buffer2(x, y)It is also important for th

16、e waves to spread out, so the buffers are smoothed every frame. 每帧波扩散传播的Smoothed公式 Smoothed(x,y) = (Buffer1(x-1, y) + Buffer1(x+1, y) + Buffer1(x, y-1) + Buffer1(x, y+1) / 4Now, to combine the two to calculate the new height of the water. The multiplication by two reduces the effect of the velocity.

17、现在结合计算新的水的高度,两个Smoothed(x,y)+速度NewHeight(x,y) = Smoothed(x,y)*2 + Velocity(x,y)Finally, the ripples must lose energy, so they are damped:最后,涟漪必须失去能量,所以他们乘以一个阻值:NewHeight(x,y) = NewHeight(x,y) * dampingNote: This can be optimised to:注意:可以优化成这样:NewHeight(x,y) = NewHeight(x,y) - (NewHeight(x,y)/n)where

18、 n is some power of 2.其中n有2个能量。So, when you put all that together, you end up with some reasonably fast code. Heres the important inner loop written in C.所以,当你把所有这些结合在一起,你就会有一个相当于如下的代码。 以下是C写的重要的内部循环中 void ProcessWater(short *source, short *dest) int i; for (i=320; i1) ) -desti; desti -= (desti 5);

19、Rendering the Water So, having coded this all up, how do you go about rendering it?Well, the buffers each contaian height map representing the height of the water at each pixel. As you may have guessed, there are many ways you can go about rendering a height field, but, in this case, an easy and eff

20、ective method is to do simple shading and refraction. You will need a texture to go behind the water, so you can see the refraction.渲染水:有了所有这些代码,然后你怎么渲染呢?每一个缓冲区的高度影射到水的像素高度,你也可能想到有许多其他的方法去得到一个高度,但在这情况下,最简单有效的方法就是做阴影和折射,你需要纹理水之后,才能看到折射for every pixel (x,y) in the buffer Xoffset = buffer(x-1, y) - buf

21、fer(x+1, y) Yoffset = buffer(x, y-1) - buffer(x, y+1) Shading = Xoffset t = texture(x+Xoffset, y+Yoffset) p = t + Shading plot pixel at (x,y) with colour p end loopNotes: This method is by no means a highly accurate simulation of rippling water (though it is not too far off). Ripples can pass throug

22、h each other quite happily, and will reflect off the walls. One thing you may notice, however, is that the ripples are not quite circular.这部份我就不翻译了。致此我们对水波的的运动轨迹都有了一个大楖的轮廓,为证实我们的想法,我们使用如下描述,这是摘自opengl高级编程的一段话The mesh geometry can be textured using simple procedural texture images, pro-ducing a good

23、simulation of water surfaces. Synthetic perturbations to the texturecoordinates, as outlined in Section 18.3.7, can also be used to help animate the watersurface.If there is an adequate performance margin, the rendering technique can be furtherembellished. Multipass or multitexture rendering techniq

24、ues can be used to layer addi-tional effects such as surf. The reective properties of the water surface can also be moreaccurately simulated. Environmentmapping can be used to simulate basic reactions fromthe surface, such as sun smear. This specular reaction can be made more physically accurate usi

25、ng environment mapping that incorporates the Fresnel reection model describedin Section 15.9. The bump-mapping technique described in Section 15.10 can be used tocreate the illusion of ripples without having to model them in the mesh geometry. Thebump maps can be updated dynamically to animate them.

26、Animating water surface effects also extends to underwater scenes. Optical effectssuch as caustics can be approximated using OpenGL, as described by Nishita andNakamae (Nishita, 1994), but interactive frame rates are not likely to be achieved. Amoreefcient, if less accurate, technique to model such

27、effects uses a caustic texture to modu-late the intensity of any geometry that lies below the surface. Other below-surface effectscan also be simulated. Movements of the water (surge) can be simulated by perturbingthe vertex coordinates of submerged objects, again using sinusoids. Blueish-green fog

28、canbe used to simulate light attenuation in water.翻译上面的:网格几何图像可以使用简单程序去纹理,能够产生了良好的水面模拟,扰动纹理的合成坐标能够画出如18.3.7描述的那样,如果有足够的性能保证,渲染技术能进一步优化,多重纹理技术可以用层来叠加,例如波浪的额外效果,这样活动水的表面属性会更加准确地模拟, 环境映射可以被用来模拟基本的光源反应,例如太阳照射的表面. 这镜面反应可以更准确地体现物理环境的映射, 采用Fresnel反应模型描述在15.9节中,在15.10章节指出凹凸映射技术,可以创建一个涟漪模型,不必在网格中使用. 凹凸的影射可动态

29、更新显示它们。动画的水面效果也延伸到水下的场面, 光学效应如焦散可以近似使用OpenGL如Nishita与Nakamae (Nishita, 1994)的描述, 但互动帧速率并不是很完美。如果不准确,可使用技术示范中影响纹理中调试任何几何表面强度(这句不好翻译还是看原文吧)。其他水底物体效果也可以模拟。水(风动)再次使用正弦模拟顶点水下运动的对象坐标扰动, 蓝色到绿色的雾可以用于模拟光在水中的衰减。看了上面的知识我们就有了一个大檓的基础,那么我们就算不用opengl的例子我们也同样能生成水波的程序。那么先让我们来回顾一下在高中的物理课上我们所学的关于水波的知识。水波有如下几个特性: 扩散:当你

30、投一块石头到水中,你会看到一个以石头入水点为圆心所形成的一圈圈的水波,这里,你可能会被这个现象所误导,以为水波上的每一点都是以石头入水点为中心向外扩散的,这是错误的。实际上,水波上的任何一点在任何时候都是以自己为圆心向四周扩散的,之所以会形成一个环状的水波,是因为水波的内部因为扩散的对称而相互抵消了。衰减:因为水是有阻尼的,否则,当你在水池中投入石头,水波就会永不停止的震荡下去。水的折射:因为水波上不同地点的倾斜角度不同,所以,因为水的折射,我们从观察点垂直往下看到的水底并不是在观察点的正下方,而有一定的偏移。如果不考虑水面上部的光线反射,这就是我们能感觉到水波形状的原因。反射:水波遇到障碍物

31、会反射。衍射:这个可以通过扭曲的纹理来模拟实现,那么就能看到水波的衍射现象了。好了,有了这几个特性,再运用数学和几何知识,我们就可以模拟出真实的水波了。但是,如果你曾用3DMax做过水波的动画,你就会知道要渲染出一幅真实形状的水波画面少说也得好几十秒,而我们现在需要的是实时的渲染,每秒种至少也得渲染20帧才能使得水波得以平滑的显示。考虑到手机运算的速度,我们不可能按照正弦函数或精确的公式来构造水波,不能用乘除法,更不能用sin、cos,只能用一种取近似值的快速算法,尽管这种算法存在一定误差,但是为了满足实时动画的要求,我们不得不这样做。首先我们要建立两个与水池图象一样大小的数组buffer1PoolWidth*PoolHeight和buffer2PoolWidth*PoolHeight(PoolWidth=水池图象的象素宽度、PoolHeight=水池

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1