three实现多种闪电动画效果代码

代码语言:html

所属分类:三维

代码描述:three实现多种闪电动画效果代码,可调节参数实现不同的闪电效果

代码标签: three 多种 闪电 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
	<head>
	
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	
	</head>
	<body>

		<div id="container"></div>
		<div id="info"> webgl - lightning strike</div>

		<!-- Import maps polyfill -->
		<!-- Remove this when import maps will be widely supported -->
		<script async type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/es-module-shims.1.3.6.js"></script>


		<script type="importmap">
			{
				"imports": {
					"three": "//repo.bfw.wiki/bfwtool/build/three.module.js"
				}
			}
		</script>

		<script type="module">

			import * as THREE from 'three';

			import Stats from '//repo.bfw.wiki/bfwtool/examples/jsm/libs/stats.module.js';
			import { GUI } from '//repo.bfw.wiki/bfwtool/examples/jsm/libs/lil-gui.module.min.js';

			import { OrbitControls } from '//repo.bfw.wiki/bfwtool/examples/jsm/controls/OrbitControls.js';
			import { LightningStrike } from '//repo.bfw.wiki/bfwtool/examples/jsm/geometries/LightningStrike.js';
			import { LightningStorm } from '//repo.bfw.wiki/bfwtool/examples/jsm/objects/LightningStorm.js';
			import { EffectComposer } from '//repo.bfw.wiki/bfwtool/examples/jsm/postprocessing/EffectComposer.js';
			import { RenderPass } from '//repo.bfw.wiki/bfwtool/examples/jsm/postprocessing/RenderPass.js';
			import { OutlinePass } from '//repo.bfw.wiki/bfwtool/examples/jsm/postprocessing/OutlinePass.js';

			let container, stats;

			let scene, renderer, composer, gui;

			let currentSceneIndex = 0;

			let currentTime = 0;

			const sceneCreators = [
				createConesScene,
				createPlasmaBallScene,
				createStormScene
			];

			const clock = new THREE.Clock();

			const raycaster = new THREE.Raycaster();
			const mouse = new THREE.Vector2();

			init();
			animate();

			function init() {

				container = document.getElementById( 'container' );

				renderer = new THREE.WebGLRenderer();
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.outputEncoding = THREE.sRGBEncoding;

				container.appendChild( renderer.domElement );

				composer = new EffectComposer( renderer );

				stats = new Stats();
				container.appendChild( stats.dom );

				window.addEventListener( 'resize', onWindowResize );

				createScene();

			}

			function createScene() {

				scene = sceneCreators[ currentSceneIndex ]();

				createGUI();

			}

			function onWindowResize() {

				scene.userData.camera.aspect = window.innerWidth / window.innerHeight;
				scene.userData.camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

				composer.setSize( window.innerWidth, window.innerHeight );

			}

			//

			function createGUI() {

				if ( gui ) {

					gui.destroy();

				}

				gui = new GUI( { width: 315 } );

				const sceneFolder = gui.addFolder( 'Scene' );

				scene.userData.sceneIndex = currentSceneIndex;

				sceneFolder.add( scene.userData, 'sceneIndex', { 'Electric Cones': 0, 'Plasma Ball': 1, 'Storm': 2 } ).name( 'Scene' ).onChange( function ( value ) {

					currentSceneIndex = value;

					createScene();

				} );

				scene.userData.timeRate = 1;
				sceneFolder.add( scene.userData, 'timeRate', scene.userData.canGoBackwardsInTime ? - 1 : 0, 1 ).name( 'Time rate' );

				sceneFolder.open();

				const graphicsFolder = gui.addFolder( 'Graphics' );

				graphicsFolder.add( scene.userData, 'outlineEnabled' ).name( 'Glow enabled' );

				scene.userData.lightningColorRGB = [
					scene.userData.lightningColor.r * 255,
					scene.userData.lightningColor.g * 255,
					scene.userData.lightningColor.b * 255
				];
				graphicsFolder.addColor( scene.userData, 'lightningColorRGB' ).name( 'Color' ).onChange( function ( value ) {

					scene.userData.lightningMaterial.color.setRGB( value[ 0 ], value[ 1 ], value[ 2 ] ).multiplyScalar( 1 / 255 );

				} );
				scene.userData.outlineColorRGB = [
					scene.userData.outlineColor.r * 255,
					scene.userData.outlineColor.g * 255,
					scene.userData.outlineColor.b * 255
				];
				graphicsFolder.addColor( scene.userData, 'outlineColorRGB' ).name( 'Glow color' ).onChange( function ( value ) {

					scene.userData.outlineColor.setRGB( value[ 0 ], value[ 1 ], value[ 2 ] ).multiplyScalar( 1 / 255 );

				} );

				graphicsFolder.open();

				const rayFolder = gui.addFolder( 'Ray parameters' );

				rayFolder.add( scene.userData.rayParams, 'straightness', 0, 1 ).name( 'Straightness' );
				rayFolder.add( scene.userData.rayParams, 'roughness', 0, 1 ).name( 'Roughness' );
				rayFolder.add( scene.userData.rayParams, 'radius0', 0.1, 10 ).name( 'Initial radius' );
				rayFolder.add( scene.userData.rayParams, 'radius1', 0.1, 10 ).name( 'Final radius' );
				rayFolder.add( scene.userData.rayParams, 'radius0Factor', 0, 1 ).name( 'Subray initial radius' );
				rayFolder.add( scene.userData.rayParams, 'radius1Factor', 0, 1 ).name( 'Subray final radius' );
				rayFolder.add( scene.userData.rayParams, 'timeScale', 0, 5 ).name( 'Ray time scale' );
				rayFolder.add( scene.userData.rayParams, 'subrayPeriod', 0.1, 10 ).name( 'Subray period (s)' );
				rayFolder.add( scene.userData.rayParams, 'subrayDutyCycle', 0, 1 ).name( 'Subray duty cycle' );

				if ( scene.userData.recreateRay ) {

					// Parameters which need to recreate the ray after modification

					const raySlowFolder = gui.addFolder( 'Ray parameters (slow)' );

					raySlowFolder.add( scene.userData.rayParams, 'ramification', 0, 15 ).step( 1 ).name( 'Ramification' ).onFinishChange( function () {

						scene.userData.recreateRay();

					} );

					raySlowFolder.add( scene.userData.rayParams, 'maxSubrayRecursion', 0, 5 ).step( 1 ).name( 'Recursion' ).onFinishChange( function () {

						scene.userData.recreateRay();

					} );

					raySlowFolder.add( scene.userData.rayParams, 'recursionProbability', 0, 1 ).name( 'Rec. probability' ).onFinishChange( function () {

						scene.userData.recreateRay();

					} );

					raySlowFolder.open();

				}

				rayFolder.open();

			}

			//

			function animate() {

				requestAnimationFrame( animate );

				render();
				stats.update();

			}

			function render() {

				currentTime += scene.userData.timeRate * clock.getDelta();

				if ( currentTime < 0 ) {

					currentTime = 0;

				}

				scene.userData.render( currentTime );

			}

			function createOutline( scene, objectsArray, visibleColor ) {

				const outlinePass = new OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, scene.userData.camera, objectsArray );
				outlinePass.edgeStrength = 2.5;
				outlinePass.edgeGlow = 0.7;
				outlinePass.edgeThickness = 2.8;
				outlinePass.visibleEdgeColor = visibleColor;
				outlinePass.hiddenEdgeColor.set( 0 );
				composer.addPass( outlinePass );

				scene.userData.outlineEnabled = true;

				return outlinePass;

			}

			//

			function createConesScene() {

				const scene = new THREE.Scene();
				scene.background = new THREE.Color( 0x050505 );

				scene.userData.canGoBackwardsInTime = true;

				scene.userData.camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 200, 100000 );

				// Lights

				scene.userData.lightningColor = new THREE.Color( 0xB0FFFF );
				scene.userData.outlineColor = new THREE.Color( 0x00FFFF );

				const posLight = new THREE.PointLight( 0x00ffff, 1, 5000, 2 );
				scene.add( posLight );

				// Ground

				const ground = new THREE.Mesh( new THREE.PlaneGeometry( 200000, 200000 ), new THREE.MeshPhongMaterial( { color: 0xC0C0C0, shininess: 0 } ) );
				ground.rotation.x = - Math.PI * 0.5;
				scene.add( ground );

				// Cones

				const conesDistance = 1000;
				const coneHeight = 200;
				const coneHeightHalf = coneHeight * 0.5;

				posLight.position.set( 0, ( conesDistance + coneHeight ) * 0.5, 0 );
				posLight.color = scene.userData.outlineColor;

				scene.userData.camera.position.set( 5 * coneHeight, 4 * coneHeight, 18 * coneHeight );

				const coneMesh1 = new THREE.Mesh( new THREE.ConeGeometry( coneHeight, coneHeight, 30, 1, false ), new THREE.MeshPhongMaterial( { color: 0xFFFF00, emissive: 0x1F1F00 } ) );
				coneMesh1.rotation.x = Math.PI;
				coneMesh1.position.y = conesDistance + coneHeight;
				scene.add( coneMesh1 );

				const coneMesh2 = new THREE.Mesh( coneMesh1.geometry.clone(), new THREE.MeshPhongMaterial( { color: 0xFF2020, emissive: 0x1F0202 } ) );
				coneMesh2.position.y = coneHeightHalf;
				scene.add( coneMesh2 );

				// Lightning strike

				scene.userData.lightningMaterial = new THREE.MeshBasicMaterial( { color: scene.userData.lightningColor } );

				scene.userData.rayParams = {

					sourceOffset: new THREE.Vector3(),
					destOffset: new THREE.Vector3(),
					radius0: 4,
					radius1: 4,
					minRadius: 2.5,
					maxIterations: 7,
					isEternal: true,

					timeScale: 0.7,

					propagationTimeFactor: 0.05,
					vanishingTimeFactor: 0.95,
					subrayPeriod: 3.5,
					subrayDutyCycle: 0.6,
					maxSubrayRecursion: 3,
					ramification: 7,
					recursionProbability: 0.6,

					roughness: 0.85,
					straightness: 0.6

				};

				let lightningStrike;
				let lightningStrikeMesh;
				const outlineMeshArray = [];

				scene.userData.recreateRay = function () {

					if ( lightningStrikeMesh ) {

						scene.remove( lightningStrikeMesh );

					}

					lightningStrike = new LightningStrike( scene.userData.rayParams );
					lightningStrikeMesh = new THREE.Mesh( lightningStrike, scene.userData.lightningMaterial );

					outlineMeshArray.length = 0;
					outlineMeshArray.push( lightningStrikeMesh );

					scene.add( lightningStrikeMesh );

				};

				scene.userData.recreateRay();

				// Compose rendering

				composer.passes = [];
				composer.addPass( new RenderPass( scene, scene.userData.camera ) );
				createOutline( scene, outlineMeshArray, scene.userData.outlineColor );

				// Controls

				const controls = new OrbitControls( scene.userData.camera, renderer.domElement );
				controls.target.y = ( conesDistance + coneHeight ) * 0.5;
				controls.enableDamping = true;
				controls.dampingFactor = 0.05;

				scene.userData.render = function ( time ) {

					// Move cones and Update ray position
					coneMesh1.position.set( Math.sin( 0.5 * time ) * conesDistance * 0.6, conesDistance + coneHeight, Math.cos( 0.5 * time ) * conesDistance * 0.6 );
					coneMesh2.position.set( Math.sin( 0.9 * time ) * conesDistance, coneHeightHalf, 0 );
					lightningStrike.rayParameters.sourceOffset.copy( coneMesh1.position );
					lightningStrike.rayParameters.sourceOffset.y -= coneHeightHalf;
					lightningStrike.rayParameters.destOffset.copy( coneMesh2.position );
					lightningStrike.rayParameters.destOffset.y += coneHeightHalf;

					lightningStrike.update( time );

					controls.update();

					// Update point li.........完整代码请登录后点击上方下载按钮下载查看

网友评论0