这是一款基于HTML5的3D水波动画特效,它的效果非常逼真,我们可以按“G”键来让水池中的石头上下浮动,按“L”键添加灯光效果,设计相当完美。同时说明一下,这款3D水波动画是基于WebGL渲染技术的,大家可以了解一下WebGL。
在线预览 源码下载
HTML代码
XML/HTML Code复制内容到剪贴板 <imgid="tiles"src="tiles.jpg"> <imgid="xneg"src="xneg.jpg"> <imgid="xpos"src="xpos.jpg"> <imgid="ypos"src="ypos.jpg"> <imgid="zneg"src="zneg.jpg"> <imgid="zpos"src="zpos.jpg">
JavaScript代码
JavaScript Code复制内容到剪贴板 functionWater(){ varvertexShader=' varyingvec2coord; voidmain(){ coord=gl_Vertex.xy*0.5+0.5; gl_Position=vec4(gl_Vertex.xyz,1.0); } '; this.plane=GL.Mesh.plane(); if(!GL.Texture.canUseFloatingPointTextures()){ thrownewError('ThisdemorequirestheOES_texture_floatextension'); } varfilter=GL.Texture.canUseFloatingPointLinearFiltering()?gl.LINEAR:gl.NEAREST; this.textureA=newGL.Texture(256,256,{type:gl.FLOAT,filter:filter}); this.textureB=newGL.Texture(256,256,{type:gl.FLOAT,filter:filter}); this.dropShader=newGL.Shader(vertexShader,' constfloatPI=3.141592653589793; uniformsampler2Dtexture; uniformvec2center; uniformfloatradius; uniformfloatstrength; varyingvec2coord; voidmain(){ /*getvertexinfo*/ vec4info=texture2D(texture,coord); /*addthedroptotheheight*/ floatdrop=max(0.0,1.0-length(center*0.5+0.5-coord)/radius); drop=0.5-cos(drop*PI)*0.5; info.r+=drop*strength; gl_FragColor=info; } '); this.updateShader=newGL.Shader(vertexShader,' uniformsampler2Dtexture; uniformvec2delta; varyingvec2coord; voidmain(){ /*getvertexinfo*/ vec4info=texture2D(texture,coord); /*calculateaverageneighborheight*/ vec2dx=vec2(delta.x,0.0); vec2dy=vec2(0.0,delta.y); floataverage=( texture2D(texture,coord-dx).r+ texture2D(texture,coord-dy).r+ texture2D(texture,coord+dx).r+ texture2D(texture,coord+dy).r )*0.25; /*changethevelocitytomovetowardtheaverage*/ info.g+=(average-info.r)*2.0; /*attenuatethevelocityalittlesowavesdonotlastforever*/ info.g*=0.995; /*movethevertexalongthevelocity*/ info.r+=info.g; gl_FragColor=info; } '); this.normalShader=newGL.Shader(vertexShader,' uniformsampler2Dtexture; uniformvec2delta; varyingvec2coord; voidmain(){ /*getvertexinfo*/ vec4info=texture2D(texture,coord); /*updatethenormal*/ vec3dx=vec3(delta.x,texture2D(texture,vec2(coord.x+delta.x,coord.y)).r-info.r,0.0); vec3dy=vec3(0.0,texture2D(texture,vec2(coord.x,coord.y+delta.y)).r-info.r,delta.y); info.ba=normalize(cross(dy,dx)).xz; gl_FragColor=info; } '); this.sphereShader=newGL.Shader(vertexShader,' uniformsampler2Dtexture; uniformvec3oldCenter; uniformvec3newCenter; uniformfloatradius; varyingvec2coord; floatvolumeInSphere(vec3center){ vec3toCenter=vec3(coord.x*2.0-1.0,0.0,coord.y*2.0-1.0)-center; floatt=length(toCenter)/radius; floatdy=exp(-pow(t*1.5,6.0)); floatymin=min(0.0,center.y-dy); floatymax=min(max(0.0,center.y+dy),ymin+2.0*dy); return(ymax-ymin)*0.1; } voidmain(){ /*getvertexinfo*/ vec4info=texture2D(texture,coord); /*addtheoldvolume*/ info.r+=volumeInSphere(oldCenter); /*subtractthenewvolume*/ info.r-=volumeInSphere(newCenter); gl_FragColor=info; } '); } Water.prototype.addDrop=function(x,y,radius,strength){ varthis_=this; this.textureB.drawTo(function(){ this_.textureA.bind(); this_.dropShader.uniforms({ center:[x,y], radius:radius, strength:strength }).draw(this_.plane); }); this.textureB.swapWith(this.textureA); }; Water.prototype.moveSphere=function(oldCenter,newCenter,radius){ varthis_=this; this.textureB.drawTo(function(){ this_.textureA.bind(); this_.sphereShader.uniforms({ oldCenter:oldCenter, newCenter:newCenter, radius:radius }).draw(this_.plane); }); this.textureB.swapWith(this.textureA); }; Water.prototype.stepSimulation=function(){ varthis_=this; this.textureB.drawTo(function(){ this_.textureA.bind(); this_.updateShader.uniforms({ delta:[1/this_.textureA.width,1/this_.textureA.height] }).draw(this_.plane); }); this.textureB.swapWith(this.textureA); }; Water.prototype.updateNormals=function(){ varthis_=this; this.textureB.drawTo(function(){ this_.textureA.bind(); this_.normalShader.uniforms({ delta:[1/this_.textureA.width,1/this_.textureA.height] }).draw(this_.plane); }); this.textureB.swapWith(this.textureA); };
以上就是本文的全部内容,希望对大家的学习有所帮助。