Enhancing the performance of three.js for numerous elements/scenes featuring diverse animations and colors

On my small webpage, I have incorporated animated gradient blobs scattered throughout the layout. Each blob is attached to different elements and has its unique color palette and animation style.

$(".blob").each(function(){     

    let scene = new THREE.Scene();  

    let lightTop = new THREE.DirectionalLight(0xFFFFFF, .7);
    lightTop.position.set(0, 500, 200);
    lightTop.castShadow = true;
    scene.add(lightTop);

    let lightBottom = new THREE.DirectionalLight(0x000000, .95);
    lightBottom.position.set(0, -500, 400);
    lightBottom.castShadow = true;
    scene.add(lightBottom);

    let ambientLight = new THREE.AmbientLight(0x798296);
    scene.add(ambientLight);

    camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);

    var material = new THREE.MeshPhongMaterial({
        vertexColors: THREE.VertexColors,
        shininess: 100
    });

    var geometry = new THREE.SphereGeometry(.8, 128, 128);  

    var speedSlider = $(this).data('speed'),
        spikesSlider = $(this).data('spikes'),
        processingSlider = $(this).data('processing'),
        color1 = $(this).data('color-1');
        color2 = $(this).data('color-2');   
        color3 = $(this).data('color-3');   
                    
    var $canvas = $(this).children('canvas'),
        canvas = $canvas[0],
        renderer = new THREE.WebGLRenderer({
            canvas: canvas,
            context: canvas.getContext('webgl2'),
            antialias: false,
            alpha: false
        }),
        simplex = new SimplexNoise();

    renderer.setSize($canvas.width(), $canvas.height());
    renderer.setPixelRatio(window.devicePixelRatio * 1 || 1);

    camera.position.z = 5;

    var sphere = new THREE.Mesh(geometry, material);

    var rev = true;
    
    var color_parsed_1 = hexToRgb(color1);
    var color_parsed_2 = hexToRgb(color2);
    var color_parsed_3 = hexToRgb(color3);
    
    var cols = [{
      stop: 0,
      color: new THREE.Color(color_parsed_1)
    }, {
      stop: .55,
      color: new THREE.Color(color_parsed_2)
    }, {
      stop: 1,
      color: new THREE.Color(color_parsed_3)
    }];

    setGradient(geometry, cols, 'y', rev); 

    scene.add(sphere);

    var update = () => {

        var time = performance.now() * 0.00001 * speedSlider * Math.pow(processingSlider, 3),
            spikes = spikesSlider * processingSlider;

        for(var i = 0; i < sphere.geometry.vertices.length; i++) {
            var p = sphere.geometry.vertices[i];
            p.normalize().multiplyScalar(1 + 0.3 * simplex.noise3D(p.x * spikes, p.y * spikes, p.z * spikes + time));
        }

        sphere.geometry.computeVertexNormals();
        sphere.geometry.normalsNeedUpdate = true;
        sphere.geometry.verticesNeedUpdate = true;

    }
    
    function animate() {
        
        update();

        renderer.render(scene, camera);
        requestAnimationFrame(animate);
        
    }

    requestAnimationFrame(animate); 

});

Check out the jsfiddle demo: https://jsfiddle.net/cdigitalig/Lqdr7825/18/

I realize that rendering a separate canvas and scene for each individual '.blob' element may not be ideal for performance. The current setup results in redundant variables and lighting properties being defined repeatedly for each blob. However, consolidating these settings outside the loop causes issues with color display.

I'm facing challenges in containing all blobs within a single canvas or scene while accommodating their dynamic positions on the page. How can I optimize the performance of this setup and ensure that all animations/colors per blob are implemented effectively within a unified canvas/scene?

Answer №1

$(".blob").each(function(){

let scene = new THREE.Scene();  

let lightTop = new THREE.DirectionalLight(0xFFFFFF, .7);
lightTop.position.set(0, 500, 200);
lightTop.castShadow = true;
scene.add(lightTop);

let lightBottom = new THREE.DirectionalLight(0x000000, .95);
lightBottom.position.set(0, -500, 400);
lightBottom.castShadow = true;
scene.add(lightBottom);

let ambientLight = new THREE.AmbientLight(0x798296);
scene.add(ambientLight);

camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);

var material = new THREE.MeshPhongMaterial({
    vertexColors: THREE.VertexColors,
    shininess: 100
});

var geometry = new THREE.SphereGeometry(.8, 128, 128);  

var speedSlider = $(this).data('speed'),
    spikesSlider = $(this).data('spikes'),
    processingSlider = $(this).data('processing'),
    color1 = $(this).data('color-1');
    color2 = $(this).data('color-2');   
    color3 = $(this).data('color-3');   
                
var $canvas = $(this).children('canvas'),
    canvas = $canvas[0],
    renderer = new THREE.WebGLRenderer({
        canvas: canvas,
        context: canvas.getContext('webgl2'),
        antialias: false,
        alpha: false
    }),
    simplex = new SimplexNoise();

renderer.setSize($canvas.width(), $canvas.height());
renderer.setPixelRatio(window.devicePixelRatio * 1 || 1);

camera.position.z = 5;

var sphere = new THREE.Mesh(geometry, material);

var rev = true;

var color_parsed_1 = hexToRgb(color1);
var color_parsed_2 = hexToRgb(color2);
var color_parsed_3 = hexToRgb(color3);

var cols = [{
  stop: 0,
  color: new THREE.Color(color_parsed_1)
}, {
  stop: .55,
  color: new THREE.Color(color_parsed_2)
}, {
  stop: 1,
  color: new THREE.Color(color_parsed_3)
}];

setGradient(geometry, cols, 'y', rev); 

scene.add(sphere);

var update = () => {

    var time = performance.now() * 0.00001 * speedSlider * Math.pow(processingSlider, 3),
        spikes = spikesSlider * processingSlider;

    for(var i = 0; i < sphere.geometry.vertices.length; i++) {
        var p = sphere.geometry.vertices[i];
        p.normalize().multiplyScalar(1 + 0.3 * simplex.noise3D(p.x * spikes, p.y * spikes, p.z * spikes + time));
    }

    sphere.geometry.computeVertexNormals();
    sphere.geometry.normalsNeedUpdate = true;
    sphere.geometry.verticesNeedUpdate = true;

}

function animate() {
    
    update();

    renderer.render(scene, camera);
    requestAnimationFrame(animate);
    
}

requestAnimationFrame(animate); 

});

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

The Vue-cli webpack development server refuses to overlook certain selected files

I am attempting to exclude all *.html files so that the webpack devserver does not reload when those files change. Here is what my configuration looks like: const path = require('path'); module.exports = { pages: { index: ...

Show an Array of Nested JSON API information on an HTML page using jQuery/JavaScript

Recently, I've delved into the world of jQuery, JavaScript, and AJAX while experimenting with an API that I designed. The backend result I received looks like this: [ { "id": 1, "choice_text": "They work on List View generally", ...

Issue with form array patching causing value not to be set on material multiple select

When attempting to populate a mat-select with multiple options using an array of ids from Firestore, I encountered an issue. The approach involved looping through the array, creating a new form control for each id, and then adding it to the formArray using ...

Design an Expandable Menu for Mobile Website using Jquery and CSS

After diving into designing a mobile website using media queries and exploring various websites, it seems like accordion navigation menus are the popular choice. I've scoured the internet for an accordion walkthrough but haven't found one that ex ...

Unable to view the image in browsers other than Internet Explorer

On a webpage, there is a feature where clicking on the "Add More" link should display an input box and a "Delete" button image. Surprisingly, this functionality works perfectly on IE browsers, but not on Mozilla or Chrome. In non-IE browsers, only the text ...

The canvas is unable to render the image from the sprite sheet

I successfully drew an image representing the player, but now I'm encountering difficulties in drawing an enemy character. Despite adding alerts indicating that the program is executing the draw enemy function, the enemy character still doesn't a ...

Having trouble updating a variable's state with setState on click

Struggling with a consistent issue while working on a React project. The problem lies in setting a variable into state using setState upon a click event. Specifically, I am facing difficulty passing my player object into state as ActivePlayer when the co ...

Uploading Files with PhoneGap using Ajax

I have been attempting to execute this PhoneGap example for uploading images from a device to a server. // Wait for PhoneGap to load // document.addEventListener("deviceready", onDeviceReady, false); // PhoneGap is ready // functi ...

When the enter key is pressed, shift the text to a different input field

I am facing a complex requirement How can I detect the pressing of the ENTER key within a text box with the following conditions: If the cursor is at the end of a sentence, it should create a new text box on the next row. If the cursor is in the middle ...

Set the clock to the correct time by winding it up

I have created a vintage-inspired clock using javascript and css. function updateClock() { var now = moment(), second = now.seconds() * 6, minute = now.minutes() * 6, hour = now.hours() % 12 / 12 * 360 + 90 + minute / 12; ...

How to extract only the truthy keys from an object using Angular.js

I am looking to retrieve only the keys with a true value in the data object and display them in the console with the specified format: Object { Agent=true, Analytics / Business Intelligence=true, Architecture / Interior Design=false } The catego ...

Discovering the minimum and maximum Node.js versions that my Node.js application can support according to its dependencies

If I have 10 developer dependencies and 10 production dependencies, how can I decide on the minimum and maximum node versions required for a user to download or clone my node application and run it smoothly? How can I automate this process by analyzing all ...

Swiping carousel feature for mobile devices

My goal is to add carousel swipe functionality for touch devices using only JS/jQuery, without relying on any other libraries. I've created a function for this purpose: $(".carousel-inner").on("touchstart", function(event){ var xClick = event ...

Tips for transforming a scroll element into the viewport using Angular 2+

This is a sample Here is a component with a list of items: class HomeComponent { text = 'foo'; testObject = {fieldFirst:'foo'}; itemList = [ '1', '2', '3', & ...

Query about Javascript/Node/JSON - why isn't this functioning properly?

I thought I had a good grasp on what I was doing until the process started getting jumbled. My code is being executed through Node, not a web browser. For some reason, it jumps to the prompt at the end of the while loop first and I'm not sure why tha ...

I am looking to transmit information to the controller using AJAX

ajax console.log(total);//10 console.log(number);//4 var form = { total:total, number:number } $.ajax({ url: 'items/cart/update', type: 'POST', data:form }); Spring MVC controller @ResponseBody @P ...

The paths specified in Node.js and Express are having difficulty finding the resource files for CSS and JavaScript

I am currently using Express to develop a basic website. Everything was running smoothly until I attempted to add the following code to handle 404 errors: app.get('/*', function(req, res) { res.render('404.ejs',{ title: ' ...

Searching by date in MongoDB using Node.js

Does anyone know how to query a mongo collection by date using JavaScript? Here is an example: var startDate = new Date(dateNow.getUTCFullYear(),dateNow.getUTCMonth(),dateNow.getUTCDate(),dateNow.getUTCHours(),0); var endDate = new Date(dateNow.getUTC ...

Is it possible for images underneath to receive focus when hovering over them?

I'm struggling with a layout of thumbnails on my page. We'll refer to them as A, B, C, etc. They are currently displayed like this: A, B, C, D, E, F, G, H, I, J, K, L, M, N... and so on. When you hover over one thumbnail, it enlarges by 2.5 t ...

Switch out React video components seamlessly without any delay

My app features a video element. I want users to be able to tap a button and instantly see another video, without any white flashes as the next mp4 loads. To achieve this, I believe I need to preload one video while playing another, then seamlessly switc ...