简介
1 .实现效果,粒子的某些属性,大小,颜色,可以在生命周期改变,其他参数,发射速率,起始大小或寿命。都可以在粒子系统的持续时间内更改
2 .
例子1 粒子随着升起变大,就像泡沫一样
<!DOCTYPE html>
<!-- 添加小人,使用序列图 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>Babylon - Getting Started</title>
<!-- Link to the last version of BabylonJS -->
<script src="https://preview.babylonjs.com/babylon.js"></script>
<!-- Link to the last version of BabylonJS loaders to enable loading filetypes such as .gltf -->
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<!-- Link to pep.js to ensure pointer events work consistently in all browsers -->
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
</body>
</html>
As you can see, we inserted in the <body> a <canvas> element. This <canvas> element will be the place where we'll display the result of our 3D rendering. Insert some style in the <head>:
<style>
html, body {
overflow: hidden;
width : 100%;
height : 100%;
margin : 0;
padding : 0;
}
#renderCanvas {
width : 100%;
height : 100%;
touch-action: none;
}
</style>
Now some javascript code to run our project. To begin with, insert at the end of your <body>:
<script>
const canvas = document.getElementById("renderCanvas");
var engine = null;
// 这里还不能用let,不然就爆炸,获取不到engine
var scene = null;
var sceneToRender = null;
const createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false}); };
let loadMeshes=async function(scene){
let spellL=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellL.meshes[0],true)
// spellL.scaling.scaleInPlace(0)
// 为什么这样就不行
let spellR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellR.meshes[0],true)
spellR.meshes[0].scaling.z=1
// spellR.scaling.scaleInPlace(0)
// 调整两个的动画速度
spellL.animationGroups[0].speedRatio=1
spellR.animationGroups[1].speedRatio=-1
let orbR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/pinkEnergyBall.glb')
let orbG=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/greenEnergyBall.glb')
let orbY=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/yellowEnergyBall.glb')
let hand=await BABYLON.SceneLoader.LoadAssetContainerAsync('https://playground.babylonjs.com/scenes/skull.babylon')
hand.meshes[0].optimizeIndices(function(){
// 先序列化一些网格,去掉一些重复的点
// 在网格具有重复顶点的情况下,优化网格的索引。该函数只会重新排序索引,不会删除未使用的顶点以避免子图出现问题。这应该和简化一起使用,以避免三角形消失。
hand.meshes[0].simplify(
[{distance:50, quality:0.1}, {distance:300, quality:0.5}, {distance:400, quality:0.3}, {distance:500, quality:0.1}],
// 精细切割简化的细则:quality:质量,0-1之间的数字,定义抽取的百分比,distance:与要添加此LOD网格的对象距离optimizeMesh:是否要优化这个网格
false,
// 并行处理:代码正常是异步处理的,这个标志甚至每个级别的处理顺序,如果设置为true,所有将一起运行,设置为false,将一个接一个的处理设置
BABYLON.SimplificationType.QUADRATIC,
// 类型:简化的类型,目前只有一种
function(){
console.log('LOD完毕')
//
}
//成功的回调
)
})
let res={
animationGroupL:spellL.animationGroups[0],
animationGroupR:spellR.animationGroups[0],
spellL:spellL.meshes[0],
spellR:spellR.meshes[0],
orbs:[orbG.meshes[0],orbR.meshes[0],orbY.meshes[0]],
lights:[]
}
res.spellL.scaling.scaleInPlace(0)
res.spellR.scaling.scaleInPlace(0)
res.orbs=res.orbs.map((o,i)=>{
let pointLight=new BABYLON.PointLight("light1",new BABYLON.Vector3(0,3,0),scene)
pointLight.intensity=0.3
res.lights.push(pointLight)
let sphere=BABYLON.Mesh.CreateSphere("s",16,0.7,scene)
o.setParent(sphere)
sphere.position.x+=0.3+(i*3)
sphere.scaling.scaleInPlace(0.3)
o.scaling.scaleInPlace(0.3)
scene.addMesh(o,true)
scene.addMesh(hand.meshes[0],true)
return sphere
})
return res
// 本函数加载的所有mesh,做一个返回整合
}
// 加载资源,处理资源都在这里处理吧
let createScene=async function(){
// 关键函数都写在这个里面
var scene = new BABYLON.Scene(engine)
scene.clearColor=new BABYLON.Color3(0.05, 0.05, 0.05)
// 添加整个空间的背景颜色
scene.enablePhysics(new BABYLON.Vector3(0,-9.81,0),new BABYLON.CannonJSPlugin())
// 加载资源
// const assets = await loadMeshes(scene)
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 10, new BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
let ground=BABYLON.MeshBuilder.CreateGround('ground',{width:10,height:10})
const particleSystem=new BABYLON.ParticleSystem('particle',2000)
particleSystem.emitter=new BABYLON.Vector3(0,0,0)
particleSystem.particleTexture=new BABYLON.Texture("http://192.168.1.102:8080/source/image/cloud.png")
// 尺寸随时间变化增大
particleSystem.addSizeGradient(0,0.1,0.3)
// 在开始时的大小范围0.1-0.3
particleSystem.addSizeGradient(1/2,0.5,0.7)
// 在1/2时间的时候大小范围限制
particleSystem.addSizeGradient(1,1,3)
// 在结束的时候的大小范围1,3
// 为什么不写一个函数里面呢
particleSystem.removeSizeGradient(0)
// 删掉开始的时候的渐变
for (let i = 0; i <= 2; i += 0.05) {
particleSystem.addSizeGradient(i / 2, 0.5 * (1 - (i - 1) * (i - 1)));
console.log(0.5 * (1 - (i - 1) * (i - 1)))
}
// 还可以这样加,更加丝滑
particleSystem.start()
// setTimeout(()=>{
// particleSystem.stop()
// // 关闭粒子系统
// },2000)
return scene
}
window.initFunction=async function(){
let asyncEngineCreation=async function(){
try{
return createDefaultEngine()
}catch(e){
return createDefaultEngine()
}
}
window.engine=await asyncEngineCreation()
if(!engine){
throw('engine should not be null')
}
window.scene=createScene()
}
initFunction().then(()=>{
scene.then((returnedScene)=>{
sceneToRender=returnedScene
})
engine.runRenderLoop(function(){
if(sceneToRender&&sceneToRender.activeCamera){
sceneToRender.render()
}
})
})
window.addEventListener('resize',function(){
engine.resize()
})
</script>
例子 2颜色随时间发生变化
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>Babylon - Getting Started</title>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
</body>
</html>
As you can see, we inserted in the <body> a <canvas> element. This <canvas> element will be the place where we'll display the result of our 3D rendering. Insert some style in the <head>:
<style>
html, body {
overflow: hidden;
width : 100%;
height : 100%;
margin : 0;
padding : 0;
}
#renderCanvas {
width : 100%;
height : 100%;
touch-action: none;
}
</style>
Now some javascript code to run our project. To begin with, insert at the end of your <body>:
<script>
const canvas = document.getElementById("renderCanvas");
var engine = null;
// 这里还不能用let,不然就爆炸,获取不到engine
var scene = null;
var sceneToRender = null;
const createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false}); };
let loadMeshes=async function(scene){
let spellL=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellL.meshes[0],true)
// spellL.scaling.scaleInPlace(0)
// 为什么这样就不行
let spellR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellR.meshes[0],true)
spellR.meshes[0].scaling.z=1
// spellR.scaling.scaleInPlace(0)
// 调整两个的动画速度
spellL.animationGroups[0].speedRatio=1
spellR.animationGroups[1].speedRatio=-1
let orbR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/pinkEnergyBall.glb')
let orbG=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/greenEnergyBall.glb')
let orbY=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/yellowEnergyBall.glb')
let hand=await BABYLON.SceneLoader.LoadAssetContainerAsync('https://playground.babylonjs.com/scenes/skull.babylon')
hand.meshes[0].optimizeIndices(function(){
// 先序列化一些网格,去掉一些重复的点
// 在网格具有重复顶点的情况下,优化网格的索引。该函数只会重新排序索引,不会删除未使用的顶点以避免子图出现问题。这应该和简化一起使用,以避免三角形消失。
hand.meshes[0].simplify(
[{distance:50, quality:0.1}, {distance:300, quality:0.5}, {distance:400, quality:0.3}, {distance:500, quality:0.1}],
// 精细切割简化的细则:quality:质量,0-1之间的数字,定义抽取的百分比,distance:与要添加此LOD网格的对象距离optimizeMesh:是否要优化这个网格
false,
// 并行处理:代码正常是异步处理的,这个标志甚至每个级别的处理顺序,如果设置为true,所有将一起运行,设置为false,将一个接一个的处理设置
BABYLON.SimplificationType.QUADRATIC,
// 类型:简化的类型,目前只有一种
function(){
console.log('LOD完毕')
//
}
//成功的回调
)
})
let res={
animationGroupL:spellL.animationGroups[0],
animationGroupR:spellR.animationGroups[0],
spellL:spellL.meshes[0],
spellR:spellR.meshes[0],
orbs:[orbG.meshes[0],orbR.meshes[0],orbY.meshes[0]],
lights:[]
}
res.spellL.scaling.scaleInPlace(0)
res.spellR.scaling.scaleInPlace(0)
res.orbs=res.orbs.map((o,i)=>{
let pointLight=new BABYLON.PointLight("light1",new BABYLON.Vector3(0,3,0),scene)
pointLight.intensity=0.3
res.lights.push(pointLight)
let sphere=BABYLON.Mesh.CreateSphere("s",16,0.7,scene)
o.setParent(sphere)
sphere.position.x+=0.3+(i*3)
sphere.scaling.scaleInPlace(0.3)
o.scaling.scaleInPlace(0.3)
scene.addMesh(o,true)
scene.addMesh(hand.meshes[0],true)
return sphere
})
return res
// 本函数加载的所有mesh,做一个返回整合
}
// 加载资源,处理资源都在这里处理吧
let createScene=async function(){
// 关键函数都写在这个里面
var scene = new BABYLON.Scene(engine)
scene.clearColor=new BABYLON.Color3(0.05, 0.05, 0.05)
// 添加整个空间的背景颜色
scene.enablePhysics(new BABYLON.Vector3(0,-9.81,0),new BABYLON.CannonJSPlugin())
// 加载资源
// const assets = await loadMeshes(scene)
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 10, new BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
let ground=BABYLON.MeshBuilder.CreateGround('ground',{width:10,height:10})
const particleSystem=new BABYLON.ParticleSystem('particle',2000)
particleSystem.emitter=new BABYLON.Vector3(0,1,0)
particleSystem.particleTexture=new BABYLON.Texture("https://playground.babylonjs.com/textures/flare.png")
particleSystem.addColorGradient(0,new BABYLON.Color3(1,0,0))
particleSystem.addColorGradient(1,new BABYLON.Color3(0,1,0))
particleSystem.addVelocityGradient(0,0.5)
// 开始的时候发射的功率
particleSystem.addVelocityGradient(1,3)
// 结束的时候发射的功率
// 这里是粒子的速度
particleSystem.start()
// setTimeout(()=>{
// particleSystem.stop()
// // 关闭粒子系统
// },2000)
return scene
}
window.initFunction=async function(){
let asyncEngineCreation=async function(){
try{
return createDefaultEngine()
}catch(e){
return createDefaultEngine()
}
}
window.engine=await asyncEngineCreation()
if(!engine){
throw('engine should not be null')
}
window.scene=createScene()
}
initFunction().then(()=>{
scene.then((returnedScene)=>{
sceneToRender=returnedScene
})
engine.runRenderLoop(function(){
if(sceneToRender&&sceneToRender.activeCamera){
sceneToRender.render()
}
})
})
window.addEventListener('resize',function(){
engine.resize()
})
</script>
##例子3 终生限速
particleSystem.addVelocityGradient(0,10)
开始的时候发射的功率
particleSystem.addVelocityGradient(1,0.1)
//这个是发射速度,初始发射速度越大,自然粒子在行进的过程中也会更快,但是并不是真的决定粒子行进速度的那个属性配置
particleSystem.minEmitPower = 8;
particleSystem.maxEmitPower = 8;
//感觉这俩是一个效果
particleSystem.limitVelocityDamping=0.1
// 移动的阻尼因子
particleSystem.addLimitVelocityGradient(0,10)
particleSystem.addLimitVelocityGradient(1,0.1)
// 开始和结束的速度,中间的在这个区间进行变化
// 用这里给的速度限制来检查当前的速度,如果不对,就使用阻尼因子来使他的速度靠近
##例子4 改变旋转角度
<!DOCTYPE html>
<!-- 添加小人,使用序列图 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>Babylon - Getting Started</title>
<!-- Link to the last version of BabylonJS -->
<script src="https://preview.babylonjs.com/babylon.js"></script>
<!-- Link to the last version of BabylonJS loaders to enable loading filetypes such as .gltf -->
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<!-- Link to pep.js to ensure pointer events work consistently in all browsers -->
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
</body>
</html>
As you can see, we inserted in the <body> a <canvas> element. This <canvas> element will be the place where we'll display the result of our 3D rendering. Insert some style in the <head>:
<style>
html, body {
overflow: hidden;
width : 100%;
height : 100%;
margin : 0;
padding : 0;
}
#renderCanvas {
width : 100%;
height : 100%;
touch-action: none;
}
</style>
Now some javascript code to run our project. To begin with, insert at the end of your <body>:
<script>
const canvas = document.getElementById("renderCanvas");
var engine = null;
// 这里还不能用let,不然就爆炸,获取不到engine
var scene = null;
var sceneToRender = null;
const createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false}); };
let loadMeshes=async function(scene){
let spellL=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellL.meshes[0],true)
// spellL.scaling.scaleInPlace(0)
// 为什么这样就不行
let spellR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/spellDisk.glb')
scene.addMesh(spellR.meshes[0],true)
spellR.meshes[0].scaling.z=1
// spellR.scaling.scaleInPlace(0)
// 调整两个的动画速度
spellL.animationGroups[0].speedRatio=1
spellR.animationGroups[1].speedRatio=-1
let orbR=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/pinkEnergyBall.glb')
let orbG=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/greenEnergyBall.glb')
let orbY=await BABYLON.SceneLoader.LoadAssetContainerAsync('http://192.168.1.102:8080/source/glb/yellowEnergyBall.glb')
let hand=await BABYLON.SceneLoader.LoadAssetContainerAsync('https://playground.babylonjs.com/scenes/skull.babylon')
hand.meshes[0].optimizeIndices(function(){
// 先序列化一些网格,去掉一些重复的点
// 在网格具有重复顶点的情况下,优化网格的索引。该函数只会重新排序索引,不会删除未使用的顶点以避免子图出现问题。这应该和简化一起使用,以避免三角形消失。
hand.meshes[0].simplify(
[{distance:50, quality:0.1}, {distance:300, quality:0.5}, {distance:400, quality:0.3}, {distance:500, quality:0.1}],
// 精细切割简化的细则:quality:质量,0-1之间的数字,定义抽取的百分比,distance:与要添加此LOD网格的对象距离optimizeMesh:是否要优化这个网格
false,
// 并行处理:代码正常是异步处理的,这个标志甚至每个级别的处理顺序,如果设置为true,所有将一起运行,设置为false,将一个接一个的处理设置
BABYLON.SimplificationType.QUADRATIC,
// 类型:简化的类型,目前只有一种
function(){
console.log('LOD完毕')
//
}
//成功的回调
)
})
let res={
animationGroupL:spellL.animationGroups[0],
animationGroupR:spellR.animationGroups[0],
spellL:spellL.meshes[0],
spellR:spellR.meshes[0],
orbs:[orbG.meshes[0],orbR.meshes[0],orbY.meshes[0]],
lights:[]
}
res.spellL.scaling.scaleInPlace(0)
res.spellR.scaling.scaleInPlace(0)
res.orbs=res.orbs.map((o,i)=>{
let pointLight=new BABYLON.PointLight("light1",new BABYLON.Vector3(0,3,0),scene)
pointLight.intensity=0.3
res.lights.push(pointLight)
let sphere=BABYLON.Mesh.CreateSphere("s",16,0.7,scene)
o.setParent(sphere)
sphere.position.x+=0.3+(i*3)
sphere.scaling.scaleInPlace(0.3)
o.scaling.scaleInPlace(0.3)
scene.addMesh(o,true)
scene.addMesh(hand.meshes[0],true)
return sphere
})
return res
// 本函数加载的所有mesh,做一个返回整合
}
// 加载资源,处理资源都在这里处理吧
let createScene=async function(){
// 关键函数都写在这个里面
var scene = new BABYLON.Scene(engine)
scene.clearColor=new BABYLON.Color3(0.05, 0.05, 0.05)
// 添加整个空间的背景颜色
scene.enablePhysics(new BABYLON.Vector3(0,-9.81,0),new BABYLON.CannonJSPlugin())
// 加载资源
// const assets = await loadMeshes(scene)
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 10, new BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
let ground=BABYLON.MeshBuilder.CreateGround('ground',{width:10,height:10})
const particleSystem=new BABYLON.ParticleSystem('particle',2000)
particleSystem.emitter=new BABYLON.Vector3(0,1,0)
particleSystem.particleTexture=new BABYLON.Texture("https://playground.babylonjs.com/textures/flare.png")
particleSystem.minEmitPower = 8;
particleSystem.maxEmitPower = 8;
particleSystem.limitVelocityDamping=0.1
// 移动的阻尼因子
particleSystem.addLimitVelocityGradient(0,10)
particleSystem.addLimitVelocityGradient(1,0.1)
// 开始和结束的速度,中间的在这个区间进行变化
// 用这里给的速度限制来检查当前的速度,如果不对,就使用阻尼因子来使他的速度靠近
// 改变旋转速度
particleSystem.addAngularSpeedGradient(0,0.5)
// 粒子生命周期开始时的角速度范围
particleSystem.addAngularSpeedGradient(1,3)
// 改变生命周期的阻力,可以通过对粒子施加阻力来模拟空气摩擦,并且可以更改粒子在其生命周期中所经历的阻力量。
// 沿着粒子速度方向施加阻力,0.8的阻力会将速度减为原来的20%,当阻力》1,粒子将作反向运动
particleSystem.addDragGradient(0,0.1)
particleSystem.addDragGradient(1,9.8)
// 粒子生命周期的变化
particleSystem.targetStopDuration=4
particleSystem.addLifeTimeGradient(0,0.5,0.75)
// 开始粒子的生命周期范围0.5-0.75
particleSystem.addLifeTimeGradient(0.4,0.25,0.5)
// 必须有targetStopDuration
particleSystem.addEmitRateGradient(0,1)
// 粒子系统启动时的发射率
particleSystem.addEmitRateGradient(1,5)
// 粒子结束时的发射率
// 这里的开始和结束都是以targetStopDuration为基准的
// 粒子大小的随时间变化
particleSystem.addStartSizeGradient(0,0.24)
particleSystem.addStartSizeGradient(1,15)
// 粒子的发射率的变化
particleSystem.start()
// setTimeout(()=>{
// particleSystem.stop()
// // 关闭粒子系统
// },2000)
return scene
}
window.initFunction=async function(){
let asyncEngineCreation=async function(){
try{
return createDefaultEngine()
}catch(e){
return createDefaultEngine()
}
}
window.engine=await asyncEngineCreation()
if(!engine){
throw('engine should not be null')
}
window.scene=createScene()
}
initFunction().then(()=>{
scene.then((returnedScene)=>{
sceneToRender=returnedScene
})
engine.runRenderLoop(function(){
if(sceneToRender&&sceneToRender.activeCamera){
sceneToRender.render()
}
})
})
window.addEventListener('resize',function(){
engine.resize()
})
</script>