当前位置:网站首页>Threejs realizes rain, snow, overcast, sunny, flame

Threejs realizes rain, snow, overcast, sunny, flame

2022-07-05 04:00:00 Zuo Ben

1, Introduce

This example uses r95 edition Three.js library . Use Threejs Particle effect realizes rain , snow , overcast , a sunny day , flame .
The renderings are as follows : 

 2, Main description

overcast , Sunny way , Mainly to replace the background image of the scene .

It's raining 、 snow 、 Flame is mainly realized by particles , There are two ways to create particles :

1, Use THREE.Points Create a collection of particles , Use THREE.PointsMaterial To style particles .

2, Use Three.Sprite() Constructors create particles manually . The only parameter we pass in is material , It can only be THREE.SpriteMaterial or THREE.SpriteCanvasMaterial.

Sprite Suitable for creating a small number of particles , If you want to create a large number of particles, you should use Points.

I'm going to use Points Realize rain and snow , The main codes are as follows :

function createPointRainy() {
	var img = rainy_sw == 1 ? "raindrop-4.png" : rainy_sw == 2 ? "snowflake3.png" : "";
	var name = rainy_sw == 1 ? "particles_rainy" : rainy_sw == 2 ? "particles_snowy" : "";
	var texture = new THREE.TextureLoader().load("assets/textures/particles/" + img);
	var geom = new THREE.Geometry();

	var material = new THREE.PointsMaterial({
		size: 1.5,
		transparent: true, //  Whether to set transparency 
		opacity: 1, //  transparent 
		map: texture, //  Particle material 
		blending: THREE.AdditiveBlending,
		sizeAttenuation: true, //  Is it the same size 
		color: 0xffffff
	});

	var range = 120;
	for (var i = 0; i < 1500; i++) {
		var particle = new THREE.Vector3(
			Math.random() * range - range / 2,
			Math.random() * range * 1.5,
			1 + (i / 10 - 80)
		)
		if (rainy_sw == 2) {
			//  Define how fast raindrops fall , The range of longitudinal motion speed is 0.1~0.3
			particle.velocityY = (0.1 + Math.random() / 5) - 0.1;
			//  Define particles ( Raindrop ) How to move horizontally , The range of lateral motion speed is -0.16~+0.16
			particle.velocityX = ((Math.random() - 0.5) / 3) - 0.05;
		} else {
			particle.velocityY = 0.15 + Math.random() / 5;
			particle.velocityX = (Math.random() - 0.5) / 3;
		}
		geom.vertices.push(particle);
	}

	cloud = new THREE.Points(geom, material);
	cloud.sortParticles = true;
	cloud.name = name;
	scene.add(cloud);
}

Use Sprite Achieve flame effect , The main codes are as follows :

function initFlame() {
	var texture = new THREE.TextureLoader().load("assets/textures/particles/flamex.png");
	//sprite texture of material 
	var material = new THREE.SpriteMaterial({
		// With canvas As texture 
		map: texture,
		// Mixing degree   Add and mix 
		blending: THREE.AdditiveBlending
	});

	// loop 1000   Add particles 
	for (var i = 0; i < 2000; i++) {
		var particle = new THREE.Sprite(material);
		initParticle(particle, i);
		krq.add(particle);
		krq.name = "particles_flame";
	}
	scene.add(krq);
}

 3, Source code

<!DOCTYPE html>
<html>
	<head>
		<title>Threejs Realize rain , snow , overcast , a sunny day , flame </title>
		<script type="text/javascript" src="libs/three.js"></script>
		<script type="text/javascript" src="libs/OrbitControls.js"></script>
		<script type="text/javascript" src="libs/OBJLoader.js"></script>
		<script type="text/javascript" src="libs/other/Tween.min.js"></script>
		<script type="text/javascript" src="libs/dat.gui.js"></script>
		<style>
			body {
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<div id="dom"></div>
		<script type="text/javascript">
			var camera;
			var renderer;
			var cloud;
			var rainy_sw = 3; // 1 rain 2 snow 3 Fine 4 Yin 
			var flame_sw = true;
			// Initialize an empty container , Loading particles 
			var krq = new THREE.Object3D();
			var textureLoader = new THREE.TextureLoader();

			function init() {
				//  Create a scene , It will contain all our elements , Like an object , Cameras and lights .
				var scene = new THREE.Scene();

				var urls = [
					'assets/textures/cubemap/flowers/posx.jpg',
					'assets/textures/cubemap/flowers/negx.jpg',
					'assets/textures/cubemap/flowers/posy.jpg',
					'assets/textures/cubemap/flowers/negy.jpg',
					'assets/textures/cubemap/flowers/posz.jpg',
					'assets/textures/cubemap/flowers/negz.jpg'
				];
				var urls1 = [
					'assets/textures/cubemap/flowers/posx1.jpg',
					'assets/textures/cubemap/flowers/negx1.jpg',
					'assets/textures/cubemap/flowers/posy1.jpg',
					'assets/textures/cubemap/flowers/negy1.jpg',
					'assets/textures/cubemap/flowers/posz1.jpg',
					'assets/textures/cubemap/flowers/negz1.jpg'
				];

				var cubeLoader = new THREE.CubeTextureLoader();
				scene.background = cubeLoader.load(urls);

				//  Create a camera , It defines where we are looking 
				camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
				//  Aim the camera at the center of the scene 
				camera.position.x = 10;
				camera.position.y = 50;
				camera.position.z = 90;
				camera.lookAt(scene.position);
				var orbit = new THREE.OrbitControls(camera);

				//  Create a renderer and set the size ,WebGLRenderer The computer graphics card will be used to render the scene 
				renderer = new THREE.WebGLRenderer({
					antialias: true,
					logarithmicDepthBuffer: true,
				});
				renderer.setClearColor(new THREE.Color(0x121A39));
				renderer.setSize(window.innerWidth, window.innerHeight);
				var alight = new THREE.AmbientLight("#ffffff", 1);
				alight.name = "aLight";
				scene.add(alight);

				//  Display the coordinate axis on the screen 
				var axes = new THREE.AxesHelper(100);
				// scene.add(axes);

				//  Add planes to the scene 
				createPlaneGeometryBasicMaterial();

				//  Add the output of the renderer to HTML Elements 
				document.getElementById("dom").appendChild(renderer.domElement);

				//  Use GUI Debug library 
				var controls = new function() {
					this.rainy = function() {
						scene.remove(scene.getObjectByName("particles_snowy"));
						if (rainy_sw != 1) {
							rainy_sw = 1;
							scene.background = cubeLoader.load(urls1);
							scene.getObjectByName("aLight").intensity = 0.6;
							createPointRainy();
						}
					}

					this.snowy = function() {
						scene.remove(scene.getObjectByName("particles_rainy"));
						if (rainy_sw != 2) {
							rainy_sw = 2;
							scene.background = cubeLoader.load(urls1);
							scene.getObjectByName("aLight").intensity = 2;
							createPointRainy();
						}
					}

					this.sunny = function() {
						if (rainy_sw != 3) {
							scene.remove(scene.getObjectByName("particles_rainy"));
							scene.remove(scene.getObjectByName("particles_snowy"));
							scene.background = cubeLoader.load(urls);
							scene.getObjectByName("aLight").intensity = 1.2;
							rainy_sw = 3;
						}

					}

					this.cloudy = function() {
						if (rainy_sw != 4) {
							scene.remove(scene.getObjectByName("particles_rainy"));
							scene.remove(scene.getObjectByName("particles_snowy"));
							scene.background = cubeLoader.load(urls1);
							scene.getObjectByName("aLight").intensity = 1;
							rainy_sw = 4;
						}
					}

					this.flame = function() {
						if (flame_sw) {
							initFlame();
							flame_sw = !flame_sw;
						}
					}
				}

				var gui = new dat.GUI();

				gui.add(controls, 'rainy'); //  rain 
				gui.add(controls, 'snowy'); //  snow 
				gui.add(controls, 'sunny'); //  Fine 
				gui.add(controls, 'cloudy'); //  Yin 
				gui.add(controls, 'flame'); //  flame 

				//  Start animation 
				renderScene();

				function createPointRainy() {
					var img = rainy_sw == 1 ? "raindrop-4.png" : rainy_sw == 2 ? "snowflake3.png" : "";
					var name = rainy_sw == 1 ? "particles_rainy" : rainy_sw == 2 ? "particles_snowy" : "";
					var texture = new THREE.TextureLoader().load("assets/textures/particles/" + img);
					var geom = new THREE.Geometry();

					var material = new THREE.PointsMaterial({
						size: 1.5,
						transparent: true, //  Whether to set transparency 
						opacity: 1, //  transparent 
						map: texture, //  Particle material 
						blending: THREE.AdditiveBlending,
						sizeAttenuation: true, //  Is it the same size 
						color: 0xffffff
					});

					var range = 120;
					for (var i = 0; i < 1500; i++) {
						var particle = new THREE.Vector3(
							Math.random() * range - range / 2,
							Math.random() * range * 1.5,
							1 + (i / 10 - 80)
						)
						if (rainy_sw == 2) {
							//  Define how fast raindrops fall , The range of longitudinal motion speed is 0.1~0.3
							particle.velocityY = (0.1 + Math.random() / 5) - 0.1;
							//  Define particles ( Raindrop ) How to move horizontally , The range of lateral motion speed is -0.16~+0.16
							particle.velocityX = ((Math.random() - 0.5) / 3) - 0.05;
						} else {
							particle.velocityY = 0.15 + Math.random() / 5;
							particle.velocityX = (Math.random() - 0.5) / 3;
						}
						geom.vertices.push(particle);
					}

					cloud = new THREE.Points(geom, material);
					cloud.sortParticles = true;
					cloud.name = name;
					scene.add(cloud);
				}

				function initFlame() {
					var texture = new THREE.TextureLoader().load("assets/textures/particles/flamex.png");
					//sprite texture of material 
					var material = new THREE.SpriteMaterial({
						// With canvas As texture 
						map: texture,
						// Mixing degree   Add and mix 
						blending: THREE.AdditiveBlending
					});

					// loop 1000   Add particles 
					for (var i = 0; i < 2000; i++) {
						var particle = new THREE.Sprite(material);
						initParticle(particle, i);
						krq.add(particle);
						krq.name = "particles_flame";
					}
					scene.add(krq);
				}

				/**
				 *  The particle   Delay divergence 
				 * @param particle
				 * @param delay
				 */
				function initParticle(particle, delay) {
					particle.position.set(5, Math.random() + 5, 0);
					particle.scale.x = particle.scale.y = Math.random() * 3;
					// Here is a series of animations 
					var xx = Math.random() * 10 - 5;
					var yy = Math.cos((Math.PI / 100) * xx) * 20;
					// Displacement 
					new TWEEN.Tween(particle.position)
						.delay(delay)
						.to({
							x: xx,
							y: yy,
							z: Math.random() * 10 - 5
						}, 2000)
						.onComplete(function() {
							initParticle(particle, delay);
						})
						.start();
					//  size 
					new TWEEN.Tween(particle.scale)
						.delay(delay)
						.to({
							x: 0.01,
							y: 0.01
						}, 1000)
						.start();
				}

				/**
				 *  Create the ground and add materials 
				 * wrapS Attributes define the texture along x Axial behavior , and warpT Attributes define the texture along y Axial behavior .
				 * Three.js The following two options are provided for these attributes :
				 * ·THREE.RepeatWrapping Allow the texture to repeat itself .
				 * ·THREE.ClampToEdgeWrapping Is the default value of the attribute .
				 *  The property value is THREE.ClampToEdgeWrapping when , Then the whole texture will not repeat , Only the pixels at the edge of the texture will be repeated to fill the remaining space .
				 */
				function createPlaneGeometryBasicMaterial() {
					var cubeMaterial = new THREE.MeshStandardMaterial({
						map: textureLoader.load("assets/textures/stone/cd.jpg"),
						side: THREE.DoubleSide,
					});
					cubeMaterial.map.wrapS = THREE.RepeatWrapping;
					cubeMaterial.map.wrapT = THREE.RepeatWrapping;
					cubeMaterial.map.repeat.set(3, 3)
					//  Create the ground plane and set the size 
					var planeGeometry = new THREE.PlaneGeometry(100, 100);
					var plane = new THREE.Mesh(planeGeometry, cubeMaterial);

					//  Set the plane position and rotate 
					plane.rotation.x = -0.5 * Math.PI;
					plane.position.x = 0;
					plane.position.z = -5;
					plane.position.y = -5;
					scene.add(plane);
				}

				function renderScene() {
					orbit.update(); //  Drag the 
					TWEEN.update();

					if (cloud) {
						var vertices = cloud.geometry.vertices;
						vertices.forEach(function(v) {
							v.y = v.y - (v.velocityY);
							v.x = v.x - (v.velocityX);

							if (v.y <= 0) v.y = 60;
							if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1;
						});
						cloud.geometry.verticesNeedUpdate = true;
					}

					//  Use requestAnimationFrame Function to render 
					requestAnimationFrame(renderScene);
					renderer.render(scene, camera);
				}

				//  Rendered scenes 
				renderer.render(scene, camera);
			}
			window.onload = init;

			//  Modify the scene as the form changes 
			function onResize() {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth, window.innerHeight);
			}
			//  Listen for form resizing events 
			window.addEventListener('resize', onResize, false);
		</script>
	</body>
</html>

If you need a complete code, please leave a message or contact me

原网站

版权声明
本文为[Zuo Ben]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202140717141049.html