代码是网上找的代码,通过调参、修改、封装实现的。
代码:
/** * 火焰 */ import * as THREE from '../build/three.module.js'; let MyFire3 = function () { let fireVertexShader = ` attribute vec4 orientation; attribute vec3 offset; attribute vec2 scale; attribute float life; attribute random; varying vec2 vUv; varying vRandom; varying vAlpha; float range(float oldValue,float oldMin,1)">float oldMax,1)">float newMin,1)"> newMax) { float oldRange = oldMax - oldMin; float newRange = newMax - newMin; return (((oldValue - oldMin) * newRange) / oldRange) + newMin; } // From Inigo Quilez http://www.iquilezles.org/www/articles/functions/functions.htm float pcurve(float x,1)">float a,1)"> b) { float k = pow(a + b,a + b) / (pow(a,a) * pow(b,b)); return k * pow(x,a) * pow(1.0 - x,b); } void main() { vUv = uv; vRandom = random; vAlpha = pcurve(life,1.0,2.0); vec3 pos = position; pos.xy *= scale * vec2(range(pow(life,1.5),0.0,0.6),range(pow(life,0.6,1.2)); vec4 or = orientation; vec3 vcV = cross(or.xyz,pos); pos = vcV * (2.0 * or.w) + (cross(or.xyz,vcV) * 2.0 + pos); gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0); } `; let fireFragmentShader = ` uniform sampler2D uMap; uniform vec3 uColor1; uniform vec3 uColor2; uniform uTime; varying vec2 vUv; varying vAlpha; varying vRandom; main() { vec2 uv = vUv; float spriteLength = 10.0; uv.x /= spriteLength; float spriteIndex = mod(uTime * 0.1 + vRandom * 2.0,1)">); uv.x += floor(spriteIndex * spriteLength) / spriteLength; vec4 map = texture2D(uMap,uv); gl_FragColor.rgb = mix(uColor2,uColor1,map.r); gl_FragColor.a = vAlpha * map.a; } `; let embersVertexShader = ` attribute size; attribute life; attribute vec3 offset; varying float impulse(float k,1)"> x) { float h = k * x; return h * exp(1.0 - h); } main() { vAlpha = impulse(6.28,life); vec3 pos = position; pos += offset * vec3(life * 0.7 + 0.3,life * 0.9 + 0.1,life * 0.7 + 0.3); vec4 mvPosition = modelViewMatrix * vec4(pos,1)">); gl_PointSize = size * (80.0 / length(mvPosition.xyz)); gl_Position = projectionMatrix * mvPosition; } `; let embersFragmentShader = ` uniform sampler2D uMap; uniform vec3 uColor; varying main() { vec2 uv = vec2(gl_PointCoord.x,1.0 - gl_PointCoord.y); vec4 mask = uColor; gl_FragColor.a = mask.a * vAlpha * 0.8; } `; let hazeVertexShader = ` attribute vec3 base; attribute vec3 offset; attribute vec4 orientation; attribute vec2 scale; attribute life; varying vAlpha; varying vec2 vUv; uv; vAlpha = pcurve(life,1)"> position; pos.xy *= scale * (life * 0.7 + 0.3); vec4 or = pos); pos += base; pos += offset * vec3(life * 0.7 + 0.3,1)">); gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1)">);; } `; let hazeFragmentShader = ` uniform sampler2D uMap; uniform sampler2D uMask; uniform vec2 uResolution; varying main() { vec2 uv = gl_FragCoord.xy / uResolution; vec2 mask = texture2D(uMask,vUv).ra - vec2(0.5); uv -= mask * 0.1; vec4 tex = tex.rgb; gl_FragColor.a = vAlpha * 0.5; } `; random(min,max,precision) { var p = Math.pow(10return Math.round((min + Math.random() * (max - min)) * p) / p; } let _scene; let _renderer; let _camera; let _controls; let _rtt; let _fire; let _width; let _height; this.objs = []; let _self = this; this._isShow = false; let _pos_x; let _pos_y; let _pos_z; this.config = (scene_,renderer_,camera_,controls_) { _width = 1920; _height = 1040; _renderer = renderer_; _scene = scene_; _camera = camera_; _controls = controls_; var _parameters = { minFilter: THREE.LinearFilter,magFilter: THREE.LinearFilter,format: THREE.RGBAFormat,stencilBuffer: }; _rtt = new THREE.WebGLRenderTarget(_width * 0.5,_height * 0.5this.setPosition = name(x,y,z) { _pos_x = x; _pos_y = y; _pos_z = z; } this.showFire = () { initFire(); initEmbers(); initHaze(); true; } this.refresh = () { _self.loop(); _self.loop2(); _self.loop3(); } this.isShow = () { return ._isShow; } this.hide = () { _self.objs.map(obj => { _scene.remove(obj); }); this.show = { _scene.add(obj); }); =====// Fire //========================================// initFire() { var _geometry,_shader,_mesh,_group; var _num = 50; var _x = new THREE.Vector3(1,0); var _y = new THREE.Vector3(0,1,1)">var _z = ); var _tipTarget = new THREE.Vector3(); var _tip = var _diff = THREE.Vector3(); var _quat = THREE.Quaternion(); var _quat2 = THREE.Quaternion(); ( () { initGeometry(); initInstances(); initShader(); initMesh(); })(); initGeometry() { _geometry = THREE.InstancedBufferGeometry(); _geometry.maxInstancedCount = _num; var shape = new THREE.PlaneBufferGeometry(500,500); shape.translate(0,0.4,1)">); var data = shape.attributes; _geometry.addAttribute('position',1)">new THREE.BufferAttribute(new Float32Array(data.position.array),3)); _geometry.addAttribute('uv',1)">new Float32Array(data.uv.array),2)); _geometry.addAttribute('normal',1)">new Float32Array(data.normal.array),1)">)); _geometry.setIndex(new Uint16Array(shape.index.array),1)">)); shape.dispose(); } initInstances() { var orientation = new THREE.InstancedBufferAttribute(new Float32Array(_num * 4),4var randoms = new Float32Array(_num),1)">var scale = new Float32Array(_num * 2),1)">var life = ); for (let i = 0; i < _num; i++) { orientation.setXYZW(i,0,1)">); life.setX(i,i / _num + 1); } _geometry.addAttribute('orientation''life' initShader() { var uniforms = { uMap: { type: 't'null },uColor1: { type: 'c'new THREE.Color(0x961800) }, red uColor2: { type: 'c'new THREE.Color(0x4b5828 yellow uTime: { type: 'f'= THREE.ShaderMaterial({ uniforms: uniforms,vertexShader: fireVertexShader,fragmentShader: fireFragmentShader,blending: THREE.AdditiveBlending,transparent: var textureLoader = THREE.TextureLoader(); textureLoader.load('images/myFire3/flame.png',t => _shader.uniforms.uMap.value = t); } initMesh() { _group = THREE.Group(); _mesh = THREE.Mesh(_geometry,_shader); _mesh.frustumCulled = ; _group.add(_mesh); _scene.add(_group); _self.objs.push(_group); _fire = _group; } _self.loop = () { let e = 100; _shader.uniforms.uTime.value = e * 0.001; var life = _geometry.attributes.life; var orientation = _geometry.attributes.orientation; var scale = _geometry.attributes.scale; var randoms = _geometry.attributes.random; ) { var value = life.array[i]; value += 0.04; if (value > 1) { value -= 1; _quat.setFromAxisAngle(_y,random(0,3.14,1)">)); _quat2.setFromAxisAngle(_x,random(-1,2) * 0.1); _quat.multiply(_quat2); _quat2.setFromAxisAngle(_z,2) * 0.3); _quat.multiply(_quat2); orientation.setXYZW(i,_quat.x,_quat.y,_quat.z,_quat.w); scale.setXY(i,random(0.8,1.2,3),random(0.8,1)">)); randoms.setX(i,1)">)); } life.setX(i,value); } life.needsUpdate = ; orientation.needsUpdate = ; scale.needsUpdate = ; randoms.needsUpdate = ; _group.position.x = _pos_x; Math.sin(e * 0.002) * 1.4; _group.position.y = _pos_y + 150; Math.cos(e * 0.0014) * 0.2; _group.position.z = _pos_z; Math.cos(e * 0.0014) * 0.5; let tipOffset = 0.4; _tipTarget.copy(_group.position); _tipTarget.y += tipOffset; _tip.lerp(_tipTarget,0.1); _diff.copy(_tip); _diff.sub(_group.position); let length = _diff.length(); _group.scale.y = (length / tipOffset - 1) * 0.4 + 1; _group.quaternion.setFromUnitVectors(_y,_diff.normalize()); } } =====// Embers //========================================// initEmbers() { var _num = 8; ( () { initGeometry(); initShader(); initMesh(); })(); THREE.BufferGeometry(); _geometry.addAttribute('position',1)">new Float32Array(_num * 3),1)">)); _geometry.addAttribute('offset',1)">)); _geometry.addAttribute('size',1)">)); _geometry.addAttribute('life',1)">)); ); _geometry.addAttribute('scale'for (var i = 0; i < _num; i++) { _geometry.attributes.life.setX(i,3) + 1); } } new THREE.Color(0xffe61e THREE.TextureLoader(); textureLoader.load('images/myFire3/ember.png',1)"> initMesh() { _points = THREE.Points(_geometry,_shader); _points.frustumCulled = ; _scene.add(_points); _self.objs.push(_points); } _self.loop2 = () { var position = _geometry.attributes.position; var size = _geometry.attributes.size; var offset = _geometry.attributes.offset; life.array[i]; value += 0.02; position.setXYZ(i,_pos_x,_pos_y + 0.1),random(200,600,random(-100,100,1)">) ); size.setX(i,random(20,1)">)); scale.setXY(i,50,50); } life.setX(i,value); } life.needsUpdate = ; position.needsUpdate = ; size.needsUpdate = ; offset.needsUpdate = ; } } =====// Haze //========================================// initHaze() { var _num = 4 () { initGeometry(); initInstances(); initShader(); initMesh(); window.addEventListener('resize',resizeHaze,1)">); resizeHaze(); })(); new THREE.PlaneBufferGeometry(0.1,0.1var base = var offset = var rotation = ); } _geometry.addAttribute('base''orientation''life' initShader() { let dpr = _renderer.getPixelRatio(); 'v2'new THREE.Vector2(_width * dpr,_height * dpr) },vertexShader: hazeVertexShader,fragmentShader: hazeFragmentShader,1)"> THREE.TextureLoader(); textureLoader.load('images/myFire3/haze.png',t => _shader.uniforms.uMask.value = initMesh() { _mesh = ; _scene.add(_mesh); _self.objs.push(_mesh); } resizeHaze() { let dpr = _renderer.getPixelRatio(); _shader.uniforms.uMap.value = _rtt.texture; _shader.uniforms.uResolution.value.set(_width * dpr,1)"> dpr); } _self.loop3 = () { let e = 100; _mesh.visible = ; _renderer.render(_scene,_camera,_rtt); _mesh.visible = var base = _geometry.attributes.base; var rotation = _geometry.attributes.rotation; life.array[i]; value += 0.008; rotation.setX(i,1)">)); base.setXYZ(i,random(-220,220,random(300,0 ); scale.setXY(i,random(0.6,3)); scale.setXY(i,50,1)">); } _quat.copy(_camera.quaternion); _quat2.setFromAxisAngle(_z,rotation.array[i]); _quat.multiply(_quat2); orientation.setXYZW(i,_quat.w); life.setX(i,1)">; base.needsUpdate = ; } } } MyFire3.prototype.constructor = MyFire3; export { MyFire3 }
如何使用(部分代码):
import { MyFire3 } from '../js.my/MyFire3.js'; let myFire3; if (!myFire3) { myFire3 = MyFire3(); myFire3.config(scene,renderer,camera,controls); myFire3.setPosition(417,1134); myFire3.showFire(); } else { if (myFire3.isShow()) { myFire3.hide(); } { myFire3.show(); } } renderLoop() { requestAnimationFrame(renderLoop); myFire3 && myFire3.refresh && myFire3.refresh(); } renderLoop();
说明:myFire3.config的参数中的controls未用到,scene、renderer、camera分别是three.js的Scene、WebGLRenderer和PerspectiveCamera对象
原文地址:https://www.cnblogs.com/s0611163
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。