threejs fire 火焰与烟雾效果

在threejs中有一个为我们提供了可以实现火焰和烟雾效果的包,我们可以直接引用这个包,通过设置某些参数实现需要的效果。
在这里插入图片描述
第一步引入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);

在这里插入图片描述
也可以使用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>
  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
three.js是一种用于在网页上创建3D图形的JavaScript库。它为开发人员提供了丰富的工具和功能,使他们能够创建逼真的3D场景和效果。而火焰烟雾three.js中常见的特效之一。 在three.js中,我们可以使用ShaderMaterial来创建火焰烟雾效果。ShaderMaterial是一种自定义材质,可以根据需求编写着色器代码来控制物体的外观和动画。 对于火焰效果,我们可以使用顶点和片元着色器来模拟火焰的动态效果。通过在顶点着色器中根据时间和噪声生成火焰的形状,并在片元着色器中根据距离摄像机的远近和透明度来控制火焰的渲染效果,可以创建出逼真的火焰效果。 而对于烟雾效果,我们可以使用类似的方法。通过在顶点着色器和片元着色器中对顶点位置和颜色进行变换和计算,以及使用一些纹理贴图来模拟烟雾的形状和颜色,可以实现逼真的烟雾效果。 不仅如此,three.js还提供了一些内置的功能和库来帮助我们创建更加复杂的火焰烟雾效果。例如,我们可以使用THREE.Fire类来创建火焰,并通过调整其参数来控制火焰的大小、颜色和动画效果。同样地,我们可以使用THREE.Smoke类来创建烟雾,并通过调整其参数来控制烟雾的密度、展示范围和透明度等。 总之,通过使用three.js的功能和工具,我们可以轻松地创建出逼真的火焰烟雾效果,为网页中的3D场景增添动态和真实感。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值