three模拟液体流动动画效果代码
代码语言:html
所属分类:动画
代码描述:three模拟液体流动动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body {margin:0px; padding:0px; overflow: hidden} </style> </head> <body > <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.156.js"></script> <script > let fluid,paint,count = 0,canvas; function init() { const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); canvas = renderer.domElement; document.body.appendChild(canvas); // Calculate half fov radians for camera setup const fov = 65; const hFovRadian = fov / 2 / 180 * Math.PI; const cz = window.innerHeight / 2 / Math.tan(hFovRadian); // Setup camera const camera = new THREE.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, 0.1, cz * 4); camera.position.z = cz; // Create context object to hold renderer, camera and dimensions const context = { renderer, camera, width: window.innerWidth, height: window.innerHeight }; // Initialize fluid and paint simulations fluid = new Fluid(context); paint = new Paint(context); } async function animate() { if (count % 640 == 0) { fluid.init(); paint.init(); } count++; fluid.update(); fluid.draw(); paint.update(fluid.getVelocity()); paint.draw(); requestAnimationFrame(animate); } //---------------------------------------- class Fluid { constructor(context) { this.context = context; this.speed = 4; this.forceInitMaterial = this.createShaderMaterial(forceInitFrag); this.divergenceMaterial = this.createShaderMaterial(divergenceFrag); this.advectionMaterial = this.createShaderMaterial(advectionFrag); this.pressureMaterial = this.createShaderMaterial(pressureFrag); this.updateMaterial = this.createShaderMaterial(forceUpdateFrag); this.renderMaterial = this.createShaderMaterial(forceRenderFrag); this.velocity = [this.createRenderTarget(), this.createRenderTarget()]; this.pressure = [this.createRenderTarget(), this.createRenderTarget()]; this.divergence = this.createRenderTarget(); this.advection = this.createRenderTarget(); this.blank = this.createRenderTarget(); // Main Scene this.mainScene = new THREE.Scene(); this.mainMesh = this.createMesh(0, 0, this.context.width, this.context.height); this.mainScene.add(this.mainMesh); this.init(); } init() { this.velocityIndex = 0; this.context.renderer.setRenderTarget(this.velocity[0]); this.mainMesh.material = this.forceInitMaterial; this.forceInitMaterial.uniforms.seed = { value: Math.random() * 100.0 }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } createShaderMaterial(frag) { return new THREE.ShaderMaterial({ vertexShader: vert, fragmentShader: frag, uniforms: { tex: { value: null }, res: { value: [this.context.width, this.context.height] }, speed: { value: this.speed } } }); } createRenderTarget() { return new THREE.WebGLRenderTarget(this.context.width, this.context.height, { format: THREE.RGBAFormat, type: THREE.FloatType }); } createMesh(cx, cy, w, h) { const geometry = new THREE.PlaneGeometry(w, h); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh = new THREE.Mesh(geometry, material); mesh.position.x = cx; mesh.position.y = cy; return mesh; } update() { this.updateAdvection(); this.updateDivergence(); this.updatepPressure(); this.updateVelocity(); } updateAdvection() { this.context.renderer.setRenderTarget(this.advection); this.mainMesh.material = this.advectionMaterial; this.advectionMaterial.uniforms.tex = { value: this.velocity[this.velocityIndex].texture }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } updateDivergence() { this.context.renderer.setRenderTarget(this.divergence); this.mainMesh.material = this.divergenceMaterial; this.divergenceMaterial.uniforms.tex = { value: this.advection.texture }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } updatepPressure() { this.context.renderer.setRenderTarget(this.pressure[0]); this.context.renderer.clear(); this.context.renderer.setRenderTarget(null); for (let i = 0; i < 4; i++) { let i0 = i % 2; let i1 = (i + 1) % 2; const prevPressure = this.pressure[i0]; const nextPressure = this.pressure[i1]; this.context.renderer.setRenderTarget(nextPressure); this.mainMesh.material = this.pressureMaterial; this.pressureMaterial.uniforms.tex = { value: prevPressure.texture }; this.pressureMaterial.uniforms.divergence = { value: this.divergence.texture }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } } updateVelocity() { const i1 = (this.velocityIndex + 1) % 2; const nextVelocity = this.velocity[i1]; this.velocityIndex = i1; this.context.renderer.setRenderTarget(nextVelocity); this.mainMesh.material = this.updateMaterial; this.updateMaterial.uniforms.pressure = { value: this.pressure[1].texture }; this.updateMaterial.uniforms.advection = { value: this.advection.texture }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } draw() { this.mainMesh.material = this.renderMaterial; this.renderMaterial.uniforms.tex = { value: this.getVelocity().texture }; this.context.renderer.render(this.mainScene, this.context.camera); } getVelocity() { return this.velocity[this.velocityIndex]; }} class Paint { constructor(context) { this.context = context; this.speed = 4; this.initMaterial = this.createShaderMaterial(paintInitFrag); this.updateMaterial = this.createShaderMaterial(paintUpdateFrag); this.renderMaterial = this.createShaderMaterial(paintRenderFrag); this.paint = [this.createRenderTarget(), this.createRenderTarget()]; // Main Scene this.mainScene = new THREE.Scene(); this.mainMesh = this.createMesh(0, 0, this.context.width, this.context.height); this.mainScene.add(this.mainMesh); this.init(); } init() { this.paintIndex = 0; this.context.renderer.setRenderTarget(this.paint[0]); this.mainMesh.material = this.initMaterial; this.initMaterial.uniforms.seed = { value: Math.random() * 100.0 }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } createShaderMaterial(frag) { return new THREE.ShaderMaterial({ vertexShader: vert, fragmentShader: frag, uniforms: { tex: { value: null }, res: { value: [this.context.width, this.context.height] }, speed: { value: this.speed } } }); } createRenderTarget() { return new THREE.WebGLRenderTarget(this.context.width, this.context.height, { format: THREE.RGBAFormat, type: THREE.FloatType }); } createMesh(cx, cy, w, h) { const geometry = new THREE.PlaneGeometry(w, h); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh = new THREE.Mesh(geometry, material); mesh.position.x = cx; mesh.position.y = cy; return mesh; } update(velocity) { const i0 = this.paintIndex % 2; const i1 = (this.paintIndex + 1) % 2; const prevPaint = this.paint[i0]; const nextPaint = this.paint[i1]; this.paintIndex = i1; this.context.renderer.setRenderTarget(nextPaint); this.mainMesh.material = this.updateMaterial; this.updateMaterial.uniforms.tex = { value: prevPaint.texture }; this.updateMaterial.uniforms.velocity = { value: velocity.texture }; this.context.renderer.render(this.mainScene, this.context.camera); this.context.renderer.setRenderTarget(null); } draw() { this.mainMesh.material = this.renderMaterial; this.renderMaterial.uniforms.tex = { value: this.getPaint().texture }; this.context.renderer.render(this.mainScene, this.context.camera); } getPaint() { return this.paint[this.paintIndex]; }} // SHADERS const noise = ` /* Simplex Noise code is from: (Shader Library) Simplex Noise in GLSL http://www.geeks3d.com/20110317/shader-library-simplex-noise-glsl-opengl/ */ #define NORMALIZE_GRADIENTS #undef USE_CIRCLE #define COLLAPSE_SORTNET float permute(float x0,vec3 p) { float x1 = mod(x0 * p.y, p.x); return floor( mod( (x1 + p.z) *x0, p.x )); } vec2 permute(vec2 x0,vec3 p) { vec2 x1 = mod(x0 * p.y, p.x); return floor( mod( (x1 + p.z) *x0, p.x )); } vec3 permute(vec3 x0,vec3 p) { vec3 x1 = mod(x0 * p.y, p.x); return floor( mod( (x1 + p.z) *x0, p.x )); } vec4 permute(vec4 x0,vec3 p) { vec4 x1 = mod(x0 * p.y, p.x); return floor( mod( (x1 + p.z) *x0, p.x )); } //uniform vec4 pParam; // Example constant with a 289 element permutation const vec4 pParam = vec4( 17.0*17.0, 34.0, 1.0, 7.0); float taylorInvSqrt(float r) { return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r ); } float simplexNoise2(vec2 v) { const vec2 C = vec2(0.211324865405187134, // (3.0-sqrt(3.0))/6.; 0.366025403784438597); // 0.5*(sqrt(3.0)-1.); const vec3 D = vec3( 0., 0.5, 2.0) * 3.14159265358979312; // First corner vec2 i = floor(v + dot(v, C.yy) ); vec2 x0 = v - i + dot(i, C.xx); // Other corners vec2 i1 = (x0.x > x0.y) ? vec2(1.,0.) : vec2(0.,1.) ; // x0 = x0 - 0. + 0. * C vec2 x1 = x0 - i1 + 1. * C.xx ; vec2 x2 = x0 - 1. + 2. * C.xx ; // Permutations i = mod(i, pParam.x); vec3 p = permute( permute( i.y + vec3(0., i1.y, 1. ), pParam.xyz) + i.x + vec3(0., i1.x, 1. ), pParam.xyz); #ifndef USE_CIRCLE // ( N points uniformly over a line, mapped onto a diamond.) vec3 x = fract(p / pParam.w) ; vec3 h = 0.5 - abs(x) ; vec3 sx = vec3(lessThan(x,D.xxx)) *2. -1.; vec3 sh = vec3(lessThan(h,D.xxx)); vec3 a0 = x + sx*sh; vec2 p0 = vec2(a0.x,h.x); vec2 p1 = vec2(a0.y,h.y); vec2 p2 = vec2(a0.z,h.z); #ifdef NORMALISE_GRADIENTS p0 *= taylorInvSqrt(dot(p0,p0)); p1 *= taylorInvSqrt(dot(p1,p1)); p2 *= taylorInvSqrt(dot(p2,p2)); #endif vec3 g = 2.0 * vec3( dot(p0, x0), dot(p1, x1), dot(p2, x2) ); #else // N points around a unit circle. vec3 phi = D.z * mod(p,pParam.w) /pParam.w ; vec4 a0 = sin(phi.xxyy+D.xyxy); vec2 a1 = sin(phi.zz +D.xy); vec3 g = vec3( dot(a0.xy, x0), dot(a0.zw, x1), dot(a1.xy, x2) ); #endif // mix vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.); m = m*m ; return 1.66666* 70.*dot(m*m, g); } float simplexNoise3(vec3 v) { .........完整代码请登录后点击上方下载按钮下载查看
网友评论0