Enhancing the efficiency of the rendering process

My website project involves displaying a fish brain with numerous neurons, loaded as triangles and links from a database. While trying to render the models, I've encountered a performance issue that I suspect is related to how I'm handling the meshes and geometries in the scene, especially since I'm new to WebGL.

Here's an example image of the brain model with a subset of neurons:

https://i.sstatic.net/9Yiet.png

The rendering code:

Due to the complexity of the code, which includes various functionalities like search options, I've omitted certain sections such as mouse controls and raycasts.

<script>

    var container;
    var camera, controls, scene, renderer;       
    var brain;
    var dirLight;
    var viewport_width;
    var viewport_height;
    var neurons;
    var line_width = 2;    
    var show_brain = true;
    var selected_brain_resolution = {{ brain.resolution }};

    init();
    animate();


    function init() {    

        {% for n in aligned_neurons %}

            random_color = getRandomColor();          
            colors_scheme.push(random_color);            

        {% endfor %}        

        container = document.getElementById('visualization');

        viewport_width = container.clientWidth;
        viewport_height = 0.75 * viewport_width;

        renderer_offset_rectangle = container.getBoundingClientRect();

        camera = new THREE.PerspectiveCamera(60, viewport_width / viewport_height, 1, 100000);
        camera.position.z = 1000;

        renderer = new THREE.CanvasRenderer();
        renderer.setClearColor(0xcccccc);
        renderer.setPixelRatio(viewport_width / viewport_height);
        renderer.setSize(viewport_width, viewport_height);
        renderer.sortObjects = false;
        container.appendChild(renderer.domElement);


        neurons = new THREE.Group();
        brain = new THREE.Group();
        scene = new THREE.Scene();

        draw_neurons();

        if (show_brain) {
            draw_brain();
        }
        brain.rotation.z = 3.14;
        brain.add(neurons);
        scene.add(brain);

        draw_intersection_plane();

        dirLight = new THREE.DirectionalLight(0xffffff, 1);
        dirLight.position.set(camera.position.x, camera.position.y, camera.position.z);
        scene.add(dirLight);

    }

 function animate() {

        requestAnimationFrame(animate);

        render();
    }

    function render() {

        dirLight.position.set(camera.position.x, camera.position.y, camera.position.z);
        renderer.render(scene, camera);
    }

    function draw_brain() {

        var geometry = new THREE.Geometry();
        var counter = 0;

        {% for face in brain.face_set.all %}

            v1 = new THREE.Vector3(({{ face.pt_1.x }}-{{ brain.center.x }}), ({{ face.pt_1.y }}-{{ brain.center.y }}), {{ face.pt_1.z }}-{{ brain.center.z }});
            v2 = new THREE.Vector3(({{ face.pt_2.x }}-{{ brain.center.x }}), ({{ face.pt_2.y }}-{{ brain.center.y }}), {{ face.pt_2.z }}-{{  brain.center.z }});
            v3 = new THREE.Vector3(({{ face.pt_3.x }}-{{ brain.center.x }}), ({{ face.pt_3.y }}-{{ brain.center.y }}), {{ face.pt_3.z }}-{{  brain.center.z }});

            geometry.vertices.push(v1);
            geometry.vertices.push(v2);
            geometry.vertices.push(v3);

            index0 = counter;
            index1 = counter + 1;
            index2 = counter + 2;

            geometry.faces.push(new THREE.Face3(index0, index1, index2));                
            counter += 3;

        {% endfor %}

        geometry.computeFaceNormals();

        var material = new THREE.MeshPhongMaterial({
            wireframe: false,
            color: 0xcccccc,
            specular: 0xffffff,
            shininess: 30,
            opacity: 0.5
        });

        var mesh = new THREE.Mesh(geometry, material);        
        brain.add(mesh)
    }

    function draw_neurons() {

        {% for neuron in aligned_neurons %}           

            var color = colors_scheme[{{ forloop.counter0 }}];
            var soma_material = new THREE.MeshPhongMaterial({
                wireframe: false,
                color: color,
                specular: 0xffffff,
                shininess: 30
            });

            var line_material = new THREE.LineBasicMaterial({color: color, linewidth: line_width});

            var spheregeometry = new THREE.SphereGeometry(1, 10, 10);
            var soma = new THREE.Mesh(spheregeometry, soma_material);
            soma.position.set({{ neuron.view.0.start_node.position.x }}-{{  brain.center.x }},
                    {{ neuron.view.0.start_node.position.y }}-{{  brain.center.y }},
                    {{ neuron.view.0.start_node.position.z }}-{{  brain.center.z }});
            var radius = 7;           

                {% for link in neuron.view %}

                    var n_position = new THREE.Vector3({{ link.start_node.position.x }} -{{  brain.center.x }}, {{ link.start_node.position.y }}-{{ brain.center.y }}, {{ link.start_node.position.z }}-{{ brain.center.z }});
                    var p_position = new THREE.Vector3({{ link.end_node.position.x }} -{{  brain.center.x }}, {{ link.end_node.position.y }}-{{  brain.center.y }}, {{ link.end_node.position.z }} -{{ brain.center.z }});

                    var line_geometry = new THREE.Geometry();
                    line_geometry.vertices.push(n_position, p_position);
                    var line = new THREE.Line(line_geometry, line_material);

                    neurons.add(line);

                {% endfor %}           

            soma.scale.set(radius, radius, radius);
            neurons.add(soma);


        {% endfor %}
    }
</script>

If you have any suggestions or advice on how to enhance the performance of this project, I would greatly appreciate it. Thank you.

Answer №1

Consider exploring the use of BufferGeometry for efficient rendering of many vertices and faces. There are multiple examples showcasing how to achieve this in a fast manner.

  • Have you determined the number of vertices being generated in draw_brain()?
  • How many neuron spheres are being generated in draw_neurons()?
  • What about the neuron lines in draw_neurons()?

Have you tested the performance impact of removing the brain mesh or the neuron mesh(es)?

Upon review, it seems that optimizing the construction of THREE.Line in draw_neurons() could be beneficial. If the lines within each neuron share the same material, it may be more efficient to use a single geometry and a single THREE.LineSegments mesh instead of individual geometries and THREE.Lines for each line or segment.

Answer №2

Let's take a moment to expand on the response to msun's answer. The BufferGeometry() class offers a convenient method

.fromGeometry ( Geometry )

By using this method, you can transfer data from a Geometry object to a BufferGeometry with minor modifications to your code. Here's an example:

var bufgeometry = new THREE.BufferGeometry().fromGeometry( geometry );
var mesh = new THREE.Mesh(bufgeometry, material);        
brain.add(mesh);

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

Clicking will open the link in both a new tab and the current tab

I'm looking to enable ng click functionality to work in both new tabs and the current tab. The URL is dynamically generated based on a certain condition. Here is the HTML: <a ng-href="{{myPathVariable }} " ng-click=" GoToThemes()" class="shift-l ...

Information is being received, but unfortunately, it cannot be displayed

Currently, I am experimenting with using the axios http request to showcase some data. My focus is on exploring how to exhibit api data on the client side with react. If you are interested in seeing my progress so far, feel free to check out the link belo ...

Detecting a mobile device when using NextJS can be accomplished by using user

With so many topics and questions on Stack Overflow, I am struggling to find the most efficient solution for detecting mobile devices. I have two components - one designed solely for desktops and another for mobile devices. {isMobile? (<SecondComponen ...

Issues with React Router server-side rendering: Error: Required prop 'history' was not specified in 'RoutingContext' prop validation

I am currently working on a fun little project to improve my React/Hapi skills and so far everything has been smooth sailing until I attempted to set up server-side routing. The server is running without any issues and successfully renders "/" with a simpl ...

Flickering Textures in THREE.js

Check out this link . Do you see how one of the textures, either the cloud or earth, flickers as the earth rotates? Any suggestions on how to resolve this issue? ...

The differences between using the opacity attribute in HTML and the opacity property

There are two distinct methods for adjusting opacity in HTML: <div opacity="0.5"></div> and <div style="opacity: 0.5;"></div> I am familiar with setting these values in JavaScript as well: div.setAttribute("opacity", 0.5); and ...

Exploring the Unpredictable Results of Recursive Functions in JavaScript

Take a look at this recursive code snippet. function calculateFactorial(n) { if (n === 0 || n === 1) { return 1; } else { console.log(calculateFactorial( (n - 1) )); return n * calculateFactorial(n - 1); } } const num = ...

How can you use Vue.js @mouseover to target a specific <path> element within an <svg>?

Check out this Codepen example. I am working with an SVG map that contains various paths holding data. My goal is to retrieve the state name when hovering over a specific path. Currently, I have added an event listener to the svg element and am trying to ...

The Ajax readyState consistently displaying a value of 0

I am encountering an issue with my Ajax code as it always returns 0 when I access 'readyState'. I have not been able to identify the source of the problem yet. Any assistance on this matter would be greatly appreciated: var xhr = null; function ...

Unidentified event listener

I am currently facing an issue where I keep getting the error message "addEventListerner of null" even though I have added a window.onload function. The page loads fine initially but then the error reoccurs, indicating that the eventListener is null. Str ...

Finding a specific object within an array of objects by searching through a key value pair

In my collection, I have an array of objects structured as follows: [{ "businessunit": [{ "Area": [{ "Asset": [{ "Wells": { "Well": "Well 11" }, "name": "Field ...

Exploring the FunctionDirective in Vue3

In Vue3 Type Declaration, there is a definition for the Directive, which looks like this: export declare type Directive<T = any, V = any> = ObjectDirective<T, V> | FunctionDirective<T, V>; Most people are familiar with the ObjectDirectiv ...

React page is not loading properly after refreshing, displaying unprocessed data instead

Hello everyone! I am currently working on developing an app using Node, React, and Mongoose without utilizing the CRA command, and I have also incorporated custom webpack setup. Initially, I was able to build everything within a single React page (App.jsx ...

The functionality of .map() in Javascript is non-existent

I am completely new to this community (and JavaScript is also new for me), so I apologize in advance for asking some very basic questions. I have an HTML page with various images, all of which share a common class. After using getElementsByClassName, I obt ...

Ensuring form input validity in real-time using jQuery's keyup event

I've been working on a form where the user can fill in an input and press enter to move to the next field. Although I have managed to get the functionality to show the next div, I am facing issues with validation... // Moving to next div on Enter ...

Capturing user input in HTML and passing it to JavaScript

I have a good grasp on how to implement input in HTML to execute JavaScript functions that are defined in the same directory as the HTML file. For example: <input type="button" value="Submit" onclick="someFunc(500)" > When the button is clicked, th ...

Retrieving POST data from requests in Node.js

My goal is to extract parameters from a POST request and store them in the variable postData using the request module. I found helpful information on handling post requests with Express.js here. Additionally, I came across this useful thread on how to retr ...

Triggering blur event manually in Ionic 3

Is there a way to manually trigger the blur event on an ion-input element? The ideal scenario would be with an ionic-native method, but any javascript-based workaround will suffice. My current configuration: Ionic: ionic (Ionic CLI) : 4.0.1 (/User ...

Tips for using conditional rendering with React and TypeScript

Issue with Conditional Rendering in TypeScript It seems like I might have encountered a problem with the way I declare my components. Take a look at this TypeScript snippet: import React, { FunctionComponent } from 'react'; export const Chapte ...

Use jQuery to clear the content within a div element following the removal of an element

A dynamic generation of checkboxes is introduced to div1: $.each(json, function(idx, obj) { $("#tbl1").append('<input type="checkbox" id='+obj.firstId+' onclick=nextPopulate('+obj.firstId+'); >'); } Upon selection, ch ...