欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

多视角3D逼真HTML5水波动画 _html5教程技巧

程序员文章站 2022-03-11 09:49:01
...
这是一款基于HTML5的3D水波动画特效,它的效果非常逼真,我们可以按“G”键来让水池中的石头上下浮动,按“L”键添加灯光效果,设计相当完美。同时说明一下,这款3D水波动画是基于WebGL渲染技术的,大家可以了解一下WebGL。

多视角3D逼真HTML5水波动画 _html5教程技巧

在线预览 源码下载

HTML代码

XML/HTML Code复制内容到剪贴板
  1. img id="tiles" src="tiles.jpg">
  2. img id="xneg" src="xneg.jpg">
  3. img id="xpos" src="xpos.jpg">
  4. img id="ypos" src="ypos.jpg">
  5. img id="zneg" src="zneg.jpg">
  6. img id="zpos" src="zpos.jpg">

JavaScript代码

JavaScript Code复制内容到剪贴板
  1. function Water() {
  2. var vertexShader = '\
  3. varying vec2 coord;\
  4. void main() {\
  5. coord = gl_Vertex.xy * 0.5 + 0.5;\
  6. gl_Position = vec4(gl_Vertex.xyz, 1.0);\
  7. }\
  8. ';
  9. this.plane = GL.Mesh.plane();
  10. if (!GL.Texture.canUseFloatingPointTextures()) {
  11. throw new Error('This demo requires the OES_texture_float extension');
  12. }
  13. var filter = GL.Texture.canUseFloatingPointLinearFiltering() ? gl.LINEAR : gl.NEAREST;
  14. this.textureA = new GL.Texture(256, 256, { type: gl.FLOAT, filter: filter });
  15. this.textureB = new GL.Texture(256, 256, { type: gl.FLOAT, filter: filter });
  16. this.dropShader = new GL.Shader(vertexShader, '\
  17. const float PI = 3.141592653589793;\
  18. uniform sampler2D texture;\
  19. uniform vec2 center;\
  20. uniform float radius;\
  21. uniform float strength;\
  22. varying vec2 coord;\
  23. void main() {\
  24. /* get vertex info */\
  25. vec4 info = texture2D(texture, coord);\
  26. \
  27. /* add the drop to the height */\
  28. float drop = max(0.0, 1.0 - length(center * 0.5 + 0.5 - coord) / radius);\
  29. drop = 0.5 - cos(drop * PI) * 0.5;\
  30. info.r += drop * strength;\
  31. \
  32. gl_FragColor = info;\
  33. }\
  34. ');
  35. this.updateShader = new GL.Shader(vertexShader, '\
  36. uniform sampler2D texture;\
  37. uniform vec2 delta;\
  38. varying vec2 coord;\
  39. void main() {\
  40. /* get vertex info */\
  41. vec4 info = texture2D(texture, coord);\
  42. \
  43. /* calculate average neighbor height */\
  44. vec2 dx = vec2(delta.x, 0.0);\
  45. vec2 dy = vec2(0.0, delta.y);\
  46. float average = (\
  47. texture2D(texture, coord - dx).r +\
  48. texture2D(texture, coord - dy).r +\
  49. texture2D(texture, coord + dx).r +\
  50. texture2D(texture, coord + dy).r\
  51. ) * 0.25;\
  52. \
  53. /* change the velocity to move toward the average */\
  54. info.g += (average - info.r) * 2.0;\
  55. \
  56. /* attenuate the velocity a little so waves do not last forever */\
  57. info.g *= 0.995;\
  58. \
  59. /* move the vertex along the velocity */\
  60. info.r += info.g;\
  61. \
  62. gl_FragColor = info;\
  63. }\
  64. ');
  65. this.normalShader = new GL.Shader(vertexShader, '\
  66. uniform sampler2D texture;\
  67. uniform vec2 delta;\
  68. varying vec2 coord;\
  69. void main() {\
  70. /* get vertex info */\
  71. vec4 info = texture2D(texture, coord);\
  72. \
  73. /* update the normal */\
  74. vec3 dx = vec3(delta.x, texture2D(texture, vec2(coord.x + delta.x, coord.y)).r - info.r, 0.0);\
  75. vec3 dy = vec3(0.0, texture2D(texture, vec2(coord.x, coord.y + delta.y)).r - info.r, delta.y);\
  76. info.ba = normalize(cross(dy, dx)).xz;\
  77. \
  78. gl_FragColor = info;\
  79. }\
  80. ');
  81. this.sphereShader = new GL.Shader(vertexShader, '\
  82. uniform sampler2D texture;\
  83. uniform vec3 oldCenter;\
  84. uniform vec3 newCenter;\
  85. uniform float radius;\
  86. varying vec2 coord;\
  87. \
  88. float volumeInSphere(vec3 center) {\
  89. vec3 toCenter = vec3(coord.x * 2.0 - 1.0, 0.0, coord.y * 2.0 - 1.0) - center;\
  90. float t = length(toCenter) / radius;\
  91. float dy = exp(-pow(t * 1.5, 6.0));\
  92. float ymin = min(0.0, center.y - dy);\
  93. float ymax = min(max(0.0, center.y + dy), ymin + 2.0 * dy);\
  94. return (ymax - ymin) * 0.1;\
  95. }\
  96. \
  97. void main() {\
  98. /* get vertex info */\
  99. vec4 info = texture2D(texture, coord);\
  100. \
  101. /* add the old volume */\
  102. info.r += volumeInSphere(oldCenter);\
  103. \
  104. /* subtract the new volume */\
  105. info.r -= volumeInSphere(newCenter);\
  106. \
  107. gl_FragColor = info;\
  108. }\
  109. ');
  110. }
  111. Water.prototype.addDrop = function(x, y, radius, strength) {
  112. var this_ = this;
  113. this.textureB.drawTo(function() {
  114. this_.textureA.bind();
  115. this_.dropShader.uniforms({
  116. center: [x, y],
  117. radius: radius,
  118. strength: strength
  119. }).draw(this_.plane);
  120. });
  121. this.textureB.swapWith(this.textureA);
  122. };
  123. Water.prototype.moveSphere = function(oldCenter, newCenter, radius) {
  124. var this_ = this;
  125. this.textureB.drawTo(function() {
  126. this_.textureA.bind();
  127. this_.sphereShader.uniforms({
  128. oldCenter: oldCenter,
  129. newCenter: newCenter,
  130. radius: radius
  131. }).draw(this_.plane);
  132. });
  133. this.textureB.swapWith(this.textureA);
  134. };
  135. Water.prototype.stepSimulation = function() {
  136. var this_ = this;
  137. this.textureB.drawTo(function() {
  138. this_.textureA.bind();
  139. this_.updateShader.uniforms({
  140. delta: [1 / this_.textureA.width, 1 / this_.textureA.height]
  141. }).draw(this_.plane);
  142. });
  143. this.textureB.swapWith(this.textureA);
  144. };
  145. Water.prototype.updateNormals = function() {
  146. var this_ = this;
  147. this.textureB.drawTo(function() {
  148. this_.textureA.bind();
  149. this_.normalShader.uniforms({
  150. delta: [1 / this_.textureA.width, 1 / this_.textureA.height]
  151. }).draw(this_.plane);
  152. });
  153. this.textureB.swapWith(this.textureA);
  154. };

以上就是本文的全部内容,希望对大家的学习有所帮助。