2014-11-03 30 views
2

我为Three.js使用ShaderParticleEngine库来创建粒子发射器。Three.js/ShaderParticleEngine - SPE.Group.tick错误的三角参数?

我在互联网上挑选了几个代码片段,使其具有工作发射器。首先,我认为这是行不通的。

但事实上,发射器显示在地图上,但一个静止的粒子在屏幕上。 经过一番调试,我发现粒子在移动,但无限缓慢。我需要使用tick(delta * 1000)来查看运行中的发射器。结果是相当丑陋(充满空白,单独的粒子)。 我没有低FPS的问题。

我发现的唯一解决方案是删除tick函数调用中的delta参数:particleGroup.tick()

结果是改善了,但自己还是欺骗,法官:

在线发射编辑: Editor

我的结果: Ingame

我无法理解。我使用库示例中提出的相同代码,并在发射器编辑器中使用导出功能。 如果我尝试其他变化(例如,对粒子寿命/速度),我在我的游戏中得到了非常不同的结果,也许粒子寿命计算不正确,因为没有给出三角参数?

我的游戏循环:

30.0000010000003385357559 9.999985195463523e-7 30.0000020000006770715117 0.0000010000003385357559 30.0000020000006770715117 0.0000010000003385357559 0.0000020000006770715117 30.0000010000003385357559:

var animate = function() { 

    requestAnimationFrame(animate); 

    render(); 

    stats.update(); 

}; 

var render = function() { 

    time = ctx3d.clock.getElapsedTime(); 
    delta = ctx3d.clock.getDelta(); 

    particleGroup.tick(delta); 

    if(ctx3d.move) 
    { 
     ctx3d.ship.position.z += delta * 500 * 3000; 
     //ctx3d.camera.position.x = ctx3d.ship.position.x; 
     //ctx3d.camera.position.z = ctx3d.ship.position.z; 
    } 

    ctx3d.renderer.render(ctx3d.scene, ctx3d.camera); 

} 

三角洲循环值循环0.000002999999196617864 0.0000010000003385357559 9.999985195463523e-7 0.000002999999196617864 0.0000010000003385357559 0.000001999998858082108 0.0000010000003385357559 20.0000020000006770715117 9.999985195463523e-7 0.0000010000003385357559

+0

对不起,我没有适合您的解决方案。但是如果点从左向右移动,底部的将是一个很棒的'脉冲喷射'粒子发射器。你可以在任何地方窥视它吗? – gnarbarian 2014-11-03 21:40:41

+0

哈哈:) 你能重新表达你的最后一句话吗? (我是法国人,我的英语有点差。) 如果我明白你想在网上看到它?恐怕图形结果取决于很多机器,这是时间和增量的问题。 – 2014-11-03 21:51:57

+0

你完全理解。无论如何,我仍然喜欢在jsfiddle或其他东西上看到它。 :)你在使用什么在线发射器编辑器? 你在做什么? – gnarbarian 2014-11-03 22:17:07

回答

1

我希望张贴这作为一个答案是可以的...

我碰着粒子引擎升级到0.7.7的小版本,已经为您的“不太流畅的”发射器问题实施了修复。

什么是以前发生的事情是这样的:

  • SPE.Emitter.tick()调用一个dt
  • tick功能决定了粒子应根据dt参数传递给它被标记活着。对于较大的值dt,更多的粒子被标记为有效,因为更小的值被标记为ALICE。
  • 发射器然后重置这些粒子并等待下一个呼叫。

假设多于一个颗粒将被标记为alive每帧,它们都起源于在空间中相同的位置,则所有的颗粒将在相同的位置时,他们激活。这就是为什么你看到一些“聚集”发生。

现在会发生什么情况是这样的:

  • SPE.Emitter.tick()调用一个dt值,就像以前一样。
  • tick功能现在决定了粒子应该被标记为活着的,而标记他们,所以,设置每个粒子的年龄是在通过dt价值的一小部分。

所以(!),假设每帧发射100个粒子,并且将0.016的值传递给发射器的功能,那些将被标记为存活的那些100个粒子中的每一个都被赋予年龄值(0.016/100) * i,其中i是粒子指数(在这种情况下,值为0到100)。

我希望这是有道理的。您可以在此处看到更改:https://github.com/squarefeet/ShaderParticleEngine/blob/master/src/ShaderParticleEmitter.js#L240-L246

主分支已更新。

+0

谢谢!这个效果很好,增量为0.016。 http://i.imgur.com/QbSvALe.png 但是当我使用Clock.getDelta时,我遇到了和以前一样的问题(http://i.imgur.com/RYTrbXm.png),你觉得有一个bug three.js所?使用Travnik在他的回答编辑中显示的日期,它可以工作。不是很好,但它工作。 再次,非常感谢您的工作! – 2014-11-04 09:43:26

+0

另一个问题:根据相机的位置,发射器原点似乎有点不同,这是否正常? – 2014-11-04 12:25:20

3

为了解决平滑,请尝试以下操作:

function makeSmoothSPETick(simulator, timeDelta, maxSubstepSize){ 
    var numSubsteps = Math.floor(timeDelta/maxSubstepSize); 
    var leftOverTime = timeDelta%maxSubstepSize; 
    while(numSubsteps-->0){ 
     simulator.tick(maxSubstepSize); 
    } 
    if(leftOverTime> 0){ 
     //handle the rest 
     simulator.tick(leftOverTime); 
    } 
} 

如果您使用此功能在你的代码中 - 它将允许你基本上细分这些步骤太大而不是固定大小。作为SquareFeet指出,譬如说60FPS 16ms的 - 你可以使用这样的事情:

var render = function() { 

    time = ctx3d.clock.getElapsedTime(); 
    delta = ctx3d.clock.getDelta(); 

    makeSmoothSPETick(particleGroup, delta, 0.016); 

    if(ctx3d.move) 
    { 
     ctx3d.ship.position.z += delta * 500 * 3000; 
     //ctx3d.camera.position.x = ctx3d.ship.position.x; 
     //ctx3d.camera.position.z = ctx3d.ship.position.z; 
    } 

    ctx3d.renderer.render(ctx3d.scene, ctx3d.camera); 

} 

你应该得到的结果在视觉上相似,如果你是在60fps的流畅运行你所期望。但要小心,如果目标硬件无法处理这些子步骤 - 您可能需要在解算器算法中获得更多逻辑。我建议保留过去100帧左右的统计数据,然后使用它来确定您可以将您的传入步数值分成多少。

编辑: 要确保你的时间没有得到错位,请尝试以下方法:

var lastFrameTime = Date.now()/1000; 
var animate = function() { 

    requestAnimationFrame(animate); 

    render(); 

    stats.update(); 

}; 

var render = function() { 

    time = Date.now()/1000; //getting current time in seconds since epoch 
    delta = time-lastFrameTime; 
    lastFrameTime = time; 

    particleGroup.tick(delta); 

    if(ctx3d.move) 
    { 
     ctx3d.ship.position.z += delta * 500 * 3000; 
     //ctx3d.camera.position.x = ctx3d.ship.position.x; 
     //ctx3d.camera.position.z = ctx3d.ship.position.z; 
    } 

    ctx3d.renderer.render(ctx3d.scene, ctx3d.camera); 

} 
+0

此外,我可以定期在粒子轨迹上看到清晰的条带,所以我猜想某些位置更新正在这些条带边界处触发(可能是您代码中的其他位置)。 – travnik 2014-11-03 22:59:42

+0

谢谢你的帮助。 _(警告,Math.floow上的代码存在拼写错误)_ 不幸的是,结果与简单的刻度(delta)相同,我得到的只是我的Universe中的一个单一的非移动粒子:http:/ /i.imgur.com/fsuqEUv.png 顺便说一句,我没有改变发射器位置或其他任何东西。 – 2014-11-03 23:08:30

+0

@MorganTouvereyQuilling:是的,这是因为发射器的刻度代码已经试图为你“赶上”这个模糊的近似值(参见:https://github.com/squarefeet/ShaderParticleEngine/blob/master/src/ShaderParticleEmitter。 JS#L245-L252)。然而,这个问题是它不能在帧*之间发射粒子*。我想知道是否我可以设置粒子的年龄是正确的,尽管它与其他粒子同时发射......让我试验一下,我会找回你的! – SquareFeet 2014-11-03 23:17:52