Is SPE.Group.tick experiencing issues with a faulty delta argument in Three.js / ShaderParticleEngine?

I recently started using the ShaderParticleEngine library in Three.js to set up particle emitters.

After browsing through various code snippets online, I managed to get an emitter up and running. Initially, I thought it wasn't working as I could only see a single stationary particle on the screen.

Upon closer inspection, I realized that the particle was indeed moving, but at an extremely slow rate. It was only when I used tick(delta * 1000) that the emitter started showing some action. However, the outcome was far from ideal, with gaps and isolated particles.

Despite not having any issues with low FPS, I decided to remove the delta argument in the tick function call: particleGroup.tick().

Although the result improved slightly, it was still disappointing. See for yourself:

Online Emitter Editor:

My Result:

I'm puzzled by this inconsistency. I've utilized the same code provided in the library examples and exported the settings from the emitter editor. However, any minor tweaks I make, like adjusting particle life or velocity, yield drastically different outcomes in my game. Could it be that the particle life calculation is affected by the absence of the delta argument?

Here's a snippet from my game loop:

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);

}

Delta values per loop:

30.0000010000003385357559 9.999985195463523e-7 30.0000020000006770715117 0.0000010000003385357559 30.0000020000006770715117 0.0000010000003385357559 0.0000020000006770715117 30.0000010000003385357559 0.000002999999196617864 0.0000010000003385357559 9.999985195463523e-7 0.000002999999196617864 0.0000010000003385357559 0.000001999998858082108 0.0000010000003385357559 20.0000020000006770715117 9.999985195463523e-7 0.0000010000003385357559

Answer №1

If you're looking to improve the smoothness of your code, consider implementing the following solution:

function adjustSmoothness(sim, timeDelta, maxStep){
  var substeps = Math.floor(timeDelta/maxStep);
  var remainingTime = timeDelta % maxStep;
  while(substeps-->0){
      sim.tick(maxStep);
  }
  if(remainingTime > 0){
      //handle the remaining time
      sim.tick(remainingTime);
  }
}

By incorporating this function into your code, you can effectively break down large steps into smaller, more manageable ones. For instance, if you are targeting 60 frames per second with a 16ms interval, you can use the function as follows:

var runSimulation = function() {

    currentTime = gameClock.getTime();
    timeElapsed = gameClock.getDeltaTime();

    adjustSmoothness(mySimulation, timeElapsed, 0.016);

    if(userInput.isActive)
    {
        player.position.x += timeElapsed * 100 * 200;
        //player.position.y = player.position.x;
        //player.position.z = player.position.x; 
    }

    renderer.drawScene();

}

By following this approach, you should observe visual outcomes that align with a smooth 60fps experience. However, it's essential to bear in mind that if the hardware struggles with these substeps, you may need to refine your solver algorithm. One suggestion is to track data from the last 100 frames and utilize it to determine the appropriate subdivision for your step size.

UPDATE: To ensure accurate timing in your implementation, consider the following:

var previousTime = Date.now()/1000;
var runAnimation = function () {

    requestAnimationFrame(runAnimation);

    runSimulation();

    performanceStats.update();

};

var runSimulation = function() {

    currentTime = Date.now()/1000; 
    timeElapsed = currentTime - previousTime;
    previousTime = currentTime;

    mySimulation.update(timeElapsed);

    if(userInput.isActive)
    {
        player.position.x += timeElapsed * 100 * 200;
        //player.position.y = player.position.x;
        //player.position.z = player.position.x;
    }

    renderer.drawScene();

}

Answer №2

Sharing this as a response, hope it's okay...

I've made some adjustments to the particle engine, upgrading it to version 0.7.7, to address the issue of "not-very-smooth-looking" emitters.

Previously, the particle engine function SPE.Emitter.tick() would determine the number of particles to be activated based on the time step dt. This led to all particles starting at the same position each frame, causing the observed "clumping" effect.

Now, with the updated version:

  • SPE.Emitter.tick() still uses dt to determine particle activation.
  • Each particle's age is calculated as a fraction of dt during activation, preventing them from starting at the same position.

For example, if 100 particles are emitted per frame with a dt of 0.016, each particle's age will be calculated as (0.016 / 100) * i, where i is the particle index.

For detailed changes, see: https://github.com/squarefeet/ShaderParticleEngine/blob/master/src/ShaderParticleEmitter.js#L240-L246

Updates have been pushed to the master branch.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Verify the presence of a specific value within an array of objects in JavaScript that was retrieved from an AJAX response, and then

I am encountering an issue with the code below where I am unable to filter entry.AllLinks. The code snippet is shown here: $.ajax({ url: url, type: "get", headers: {"Accept": "application/json;odata=verbose"}, success: function (data) { ...

Executing <script> tags inside <template> on vue js

I have encountered a problem while trying to add an Iframe from a service I am using. The content comes within script tags, but when I try to insert them into Vue 3 framework, I encounter an error. I have searched for a solution and came across a thread o ...

The component encounters a transformation in which prop values shift to undefined

My component seems to be encountering some instability. The value assigned to "this.state.list" from this.props is being immediately set to "undefined". I'm struggling to comprehend why this is happening. Can anyone spot the issue in the code? this.s ...

Update Material-ui to include an inclusive Datepicker widget

I have integrated the Material-ui Datepicker into my website to allow users to download timed event information from a database. The issue I am facing is that when users select two bracketing dates, events for the end date are not showing up correctly. F ...

Need help triggering Ajax code upon clicking a link?

Can someone help me find the issue with my script? Below is the code snippet: <script> $(".icross").click(function(e){ e.preventDefault(); var obj = $(this); $.ajax({ type: "GET", url: "supprimer.php", data: 'id=&a ...

What is the best way to create router links on the fly in Vue.js?

I am currently exploring how to achieve the following in Vue.js <table> <tr v-for="item in messages"> <td><router-link to="'/user/' + item.id">{{ item.name }}</router-link></td> </tr> < ...

Only the initial value is being processed in the for loop using Javascript

I am having issues trying to sum the values within a for loop sourced from my Django database using JavaScript. Currently, when I iterate through the loop, only the first value in the array is returned. I need assistance in finding a solution that allows ...

Else statement malfunctioning with Alert() function

I have noticed an issue with my user input field. Even when I enter a valid genre name, the alert prompt still appears saying it is not a valid genre. This occurs after entering both valid and invalid inputs. For example, if the user enters "horror," whic ...

Create a customizable table without relying on external jQuery plugins

Looking to develop a table with editable content (using an "edit" button on each row) without relying on Bootstrap or any additional plugins. The goal is to utilize HTML, PHP, AJAX, and JavaScript exclusively for this task. Can anyone provide guidance, sam ...

extracting an attribute from a class's search functionality

Let's consider the following HTML structure: <div id="container"> <div> <div class="main" data-id="thisID"> </div> </div> </div> If I want to retrieve the value inside the data-id attribute ...

Modules failing to load in the System JS framework

Encountering a puzzling issue with System JS while experimenting with Angular 2. Initially, everything runs smoothly, but at random times, System JS struggles to locate modules... An error message pops up: GET http://localhost:9000/angular2/platform/bro ...

VS code is showing the directory listing instead of serving the HTML file

Recently, I attempted to use nodejs to serve the Disp.html file by following a code snippet from a tutorial I found on YouTube. const http = require("http"); const fs = require("fs"); const fileContent = fs.readFileSync("Disp.html& ...

Is it advisable to consider yarn.lock as a binary file when using git?

Could there be a rationale for this decision? I'm thinking that the potential git diff could occur in package.json. My approach is to consider the yarn.lock file as binary. ...

The CSS3 slideshow is displaying distorted and unfocused images

I have a CSS code that controls the timing of my slideshow with 3 images: .slideshow li:child(1) span { background-image: url(../../pic/bg1.jpg); } .slideshow li:child(2) span { background-image: url(../../pic/bg2.jpg); -webkit-animation-de ...

Ways to store a filestream coming from Node.js into AngularJS

When using my express server, I have a post-request set up to retrieve a pdf file from Amazon S3 and then send it back to Angular. This is the endpoint in my express server: var fileStream = s3.getObject(options).createReadStream(); fileStream.pipe(res); ...

Jumbling a word by shuffling its letters into a random order

The objective of the program is to take the word you input into a box, split it into an array of letters, and then shuffle them. Following that, it should capitalize the first letter and lowercase the rest before displaying the result in the same box. I a ...

Update the text input field from a different webpage

I am working with two PHP pages, let's call them page1.php and page2.php. On page1.php, there is a textbox with a default value of 0, while on page2.php, there is a button. I have these two pages open in different tabs in a browser. My goal is to have ...

What is the best way to trigger a child function from the parent component in React?

In my React application, there are three components: two child components and one parent component. I need to pass data (projectId) from ChildOne to ChildTwo through the Parent component and trigger a function once the data is received. Essentially, I am s ...

Is there a way to restrict the amount of user input that is allowed?

Is it possible to restrict the input quantity when using the built-in arrow icon in the text field, but not when typing manually? https://i.sstatic.net/jjogP.png <TextField variant="outlined" label="Quantity" onChan ...

What is the best way to retrieve IMDB movie data using AJAX?

I have created a code to access movie information from IMDB. To download free movies, you can visit my website . To obtain series of movie information, I need to utilize the IMDB API. However, the current code I am using refreshes the page and posts the a ...