three实现多种闪电动画效果代码
代码语言:html
所属分类:三维
代码描述: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