threejs fire 火焰与烟雾效果

在threejs中有一个为我们提供了可以实现火焰和烟雾效果的包,我们可以直接引用这个包,通过设置某些参数实现需要的效果。
threejs fire 火焰与烟雾效果_第1张图片
第一步引入fire包,可在工程文件夹下的example文件夹中找到

<script type="text/javascript" src="js/objects/Fire.js" ></script>

第二步,新建任意一个geometry对象作为fire的载体
构造器Fire(geometry,option)

				//var plane=new THREE.PlaneBufferGeometry(20,20,1);
				var cube=new THREE.BoxBufferGeometry(30,30,30);
				fire=new THREE.Fire(cube,{
					textureWidth:512,
					textureHeight:512,
					debug:false
				});
				fire.position.z=-2;
				scene.add(fire);

最后,添加资源就有了效果

fire.addSource(0.5,0.1,0.1,1.0,0.0,1.0);

threejs fire 火焰与烟雾效果_第2张图片
也可以使用canvas贴图实现文字火焰效果,画好了canvas,注意需要声明更新材质

					Text:function(){//文字火焰效果
						var text="Three JS";
						var color='#ff0040';
						var canvas=document.createElement("canvas");
						canvas.width=1024;
						canvas.height=1024;
						var ctx=canvas.getContext('2d');
						ctx.strokeStyle="black";
						ctx.strokeRect(0,0,canvas.width,canvas.height);
						ctx.textAlign='center';
						ctx.textBaseline='middle';	
						ctx.font='180pt Arial';
						ctx.lineWidth=5;
						ctx.strokeStyle=color;
						ctx.strokeText(text,canvas.width/2,canvas.height*0.75);
						var texture=new THREE.Texture(canvas);
						texture.needsUpdate=true;
						fire.setSourceMap(texture);
					}

常用方法:

  1. clearSources()
    清除资源
  2. addSource(u, v, radius, density, windX, windY);
    添加资源
  3. setSourceMap(texture)
    设置贴图

可选属性参数:

				var params={
					//基本火焰参数设置
					color1:'#ffffff',//内焰
					color2:'#ffa000',//外焰
					color3:'#000000',//烟雾
					colorBias:0.8,//颜色偏差
					burnRate:0.35,//燃烧率
					diffuse:1.33,//扩散
					viscosity:0.25,//粘度
					expansion:-0.25,//膨胀
					swirl:50.0,//旋转
					drag:0.35,//拖拽
					airSpeed:12.0,//空气速度
					windX:0.0,//风向X
					windY:0.75,//风向Y
					speed:500.0,//火焰速度
					massConservation:false,//质量守恒
					}

源码示例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<title>火焰和烟雾效果</title>
		<script type="text/javascript" src="js/WebGL.js" ></script>
		<script type="text/javascript" src="js/three.js" ></script>
		<script type="text/javascript" src="js/controls/OrbitControls.js" ></script>
		<script type="text/javascript" src="js/libs/stats.min.js" ></script>
		<script type="text/javascript" src="js/libs/dat.gui.min.js" ></script>
		<script type="text/javascript" src="js/objects/Fire.js" ></script>
		<style>
			body{
				padding: 0;
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<script>
			if(WEBGL.isWebGLAvailable()===false)document.body.appendChild(WEBGL.getWebGLErrorMessage());
			
			var scene,renderer,camera,controls,stats;
			function init(){
				scene=new THREE.Scene();
				scene.background=new THREE.Color(0x000000);
				
				renderer=new THREE.WebGLRenderer({
					antialias:true,
					alpha:true
				});
				renderer.setSize(window.innerWidth,window.innerHeight);
				renderer.setPixelRatio(window.devicePixelRatio);
				document.body.appendChild(renderer.domElement);
				
				camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
				camera.position.set(0,20,50);
				
				controls=new THREE.OrbitControls(camera,renderer.domElement);
				controls.enableDamping=true;
				controls.minDistance=1;
				controls.maxDistance=500;
				
				stats=new Stats();
				document.body.appendChild(stats.domElement);
				
				scene.add(new THREE.AmbientLight(0XCCCCCC,0.4));
				
				var pointLight=new THREE.PointLight(0xffffff,0.8);
				scene.add(pointLight);
			}
			
			var axes;
			var fire;
			function initModel(){
				axes=new THREE.AxesHelper(30);
				scene.add(axes);
				axes.visible=false;
				
				//var plane=new THREE.PlaneBufferGeometry(20,20,1);
				var cube=new THREE.BoxBufferGeometry(30,30,30);
				fire=new THREE.Fire(cube,{
					textureWidth:512,
					textureHeight:512,
					debug:false
				});
				fire.position.z=-2;
				scene.add(fire);
			}
			
			var mouse=new THREE.Vector2();
			var raycaster=new THREE.Raycaster();
			function rayEvent(event){
				if(event.touches){
					var touchE=event.touches[0];
					mouse.x=(touchE.pageX/window.innerWidth)*2-1;
					mouse.y=-(touchE.pageY/window.innerHeight)*2+1;
				}else{
					mouse.x=(event.clientX/window.innerWidth)*2-1;
					mouse.y=-(event.clientY/window.innerHeight)*2+1;
				}
				
				raycaster.setFromCamera(mouse,camera);
				
				var intersects=raycaster.intersectObjects(scene.children,true);
				if(intersects.length>0){
					intersects[0].object.material.color.set(0xff0000);
				}else{
					console.log("未检测到物体!");
				}
			}
			
			var settings;
			function initGui(){
/*				settings={
					axesVisible:false
				}*/
				
				var params={
					//基本火焰参数设置
					color1:'#ffffff',//内焰
					color2:'#ffa000',//外焰
					color3:'#000000',//烟雾
					colorBias:0.8,//颜色偏差
					burnRate:0.35,//燃烧率
					diffuse:1.33,//扩散
					viscosity:0.25,//粘度
					expansion:-0.25,//膨胀
					swirl:50.0,//旋转
					drag:0.35,//拖拽
					airSpeed:12.0,//空气速度
					windX:0.0,//风向X
					windY:0.75,//风向Y
					speed:500.0,//火焰速度
					massConservation:false,//质量守恒
					
					//基本效果
					Single:function(){//单焰效果
						fire.clearSources();
						fire.addSource(0.5,0.1,0.1,1.0,0.0,1.0);
					},
					Multiple:function(){//多焰效果
						fire.clearSources();
						fire.addSource(0.1,0.1,0.1,0.5,0.0,1.0);
						fire.addSource(0.4,0.1,0.1,0.5,0.0,1.0);
						fire.addSource(0.7,0.1,0.1,0.5,0.0,1.0);
					},
					Text:function(){//文字火焰效果
						var text="Three JS";
						var color='#ff0040';
						var canvas=document.createElement("canvas");
						canvas.width=1024;
						canvas.height=1024;
						var ctx=canvas.getContext('2d');
						ctx.strokeStyle="black";
						ctx.strokeRect(0,0,canvas.width,canvas.height);
						ctx.textAlign='center';
						ctx.textBaseline='middle';	
						ctx.font='180pt Arial';
						ctx.lineWidth=5;
						ctx.strokeStyle=color;
						ctx.strokeText(text,canvas.width/2,canvas.height*0.75);
						var texture=new THREE.Texture(canvas);
						texture.needsUpdate=true;
						fire.setSourceMap(texture);
					},
					
					//参数效果
					Candle:function(){//蜡烛
						var paraArr=[0xffffff,0xffa000,0x000000,0.0,0.5,0.3,1.6,1.33,1.33,0.0,0.0,0.0,8.0,500.0,false];
						updateAll(paraArr);
					},
					Torch:function(){//火炬
						var paraArr=[0xffdcaa,0xffa000,0x000000,0.0,0.75,0.9,1.0,1.33,0.25,0.0,50.0,0.35,10.0,500.0,false];
						updateAll(paraArr);
					},
					Campfire:function(){//篝火
						var paraArr=[0xffffff,0xffa000,0x000000,0.0,0.75,0.8,0.3,1.33,0.25,-0.25,50.0,0.35,12.0,500.0,false];
						updateAll(paraArr);
					},
					Fireball:function(){//火球
						var paraArr=[0xffffff,0xffa000,0x000000,0.0,0.75,0.8,1.2,3.0,0.0,0.0,6.0,0.0,20.0,500.0,false];
						updateAll(paraArr);
					},
					Iceball:function(){//冰球
						var paraArr=[0x00bdf7,0x1b3fb6,0x001869,0.0,-0.25,0.25,2.6,5.0,0.5,0.75,30.0,0.0,40.0,500.0,false];
						updateAll(paraArr);
					},
					Smoke:function(){//浓烟
						var paraArr=[0xd2d2d2,0xd7d7d7,0x000000,-0.05,0.15,0.95,0.0,1.5,0.25,0.2,3.75,0.4,18.0,500.0,false];
						updateAll(paraArr);
					},
					Cigar:function(){//香烟的烟
						var paraArr=[0xc5c5c5,0x787878,0x000000,0.0,0.3,0.55,0.0,1.3,0.05,-0.05,3.7,0.6,6.0,500.0,false];
						updateAll(paraArr);
					}
				}
				
				function updateAll(arr){
					fire.color1.set(arr[0]);
					fire.color2.set(arr[1]);
					fire.color3.set(arr[2]);
					fire.windVector.x=arr[3];
					fire.windVector.y=arr[4];
					fire.colorBias=arr[5];
					fire.burnRate=arr[6];
					fire.diffuse=arr[7];
					fire.viscosity=arr[8];
					fire.expansion=arr[9];
					fire.swirl=arr[10];
					fire.drag=arr[11];
					fire.airSpeed=arr[12];
					fire.speed=arr[13];
					fire.massConservation=arr[14];
					
					var i=0;
					for(var index in gui.__controllers){
						gui.__controllers[index].setValue(arr[i]);
						i++;
					}
				}
				
				var gui=new dat.GUI();
/*				gui.add(settings,"axesVisible").onChange(function(e){
					axes.visible=e;
				});*/
				
				var g1=gui.addFolder("基本效果");
				g1.add(params,"Single").name("单焰效果");
				g1.add(params,"Multiple").name('多焰效果');
				g1.add(params,"Text").name("文本火焰");
				g1.open();
				
				var g2=gui.addFolder("参数效果");
				g2.add(params,'Candle').name("蜡烛火焰");
				g2.add(params,'Torch').name("火炬火焰");
				g2.add(params,'Campfire').name("篝火火焰");
				g2.add(params,'Fireball').name("火球火焰");
				g2.add(params,'Iceball').name("冰球火焰");
				g2.add(params,'Smoke').name("浓烟");
				g2.add(params,'Cigar').name("香烟的烟");
				g2.open();
				
				gui.addColor(params,"color1").onChange(function(e){
					fire.color1.set(e);
				});
				gui.addColor(params,"color2").onChange(function(e){
					fire.color2.set(e);
				});
				gui.addColor(params,"color3").onChange(function(e){
					fire.color3.set(e);
				});
				gui.add(params,"windX",-5,5).step(0.1).onChange(function(e){
					fire.windVector.x=e;
				});
				gui.add(params,"windY",-5,5).step(0.1).onChange(function(e){
					fire.windVector.y=e;
				});
				gui.add(params,"colorBias",0.0,1.0).onChange(function(e){
					fire.colorBias=e;
				});
				gui.add(params,"burnRate",0.0,10.0).onChange(function(e){
					fire.burnRate=e;
				});
				gui.add(params,"diffuse",0.0,5.0).step(0.1).onChange(function(e){
					fire.diffuse=e;
				});
				gui.add(params,"viscosity",0.0,5.0).step(0.1).onChange(function(e){
					fire.viscosity=e;
				});
				gui.add(params,"expansion",-1.0,1.0).step(0.01).onChange(function(e){
					fire.expansion=e;
				});
				gui.add(params,"swirl",0.0,50.0).onChange(function(e){
					fire.swirl=e;
				});
				gui.add(params,"drag",0.0,1.0).step(0.01).onChange(function(e){
					fire.drag=e;
				});
				gui.add(params,"airSpeed",0.0,50.0).onChange(function(e){
					fire.airSpeed=e;
				});
				gui.add(params,"speed",0,1000).onChange(function(e){
					fire.speed=e;
				});
				gui.add(params,"massConservation").onChange(function(e){
					fire.massConservation=e;
				});
				
				params.Single();
			}
			
			function onWindowResize(){
				camera.aspect=window.innerWidth/window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth,window.innerHeight);
			}
			
			function render(){
				renderer.render(scene,camera);
			}
			
			function animate(){
				render();
				stats.update();
				controls.update();
				window.onresize=onWindowResize();
				requestAnimationFrame(animate);
			}
			
			(function threeStart(){
				init();
				initModel();
				initGui();
				animate();
				//window.addEventListener("click",rayEvent,false);
				//window.addEventListener("touchstart",rayEvent,false);
			}());
		</script>
	</body>
</html>

你可能感兴趣的:(threejs fire 火焰与烟雾效果)