Navigating memory in Three.js while handling multiple textures

I am in the process of developing a fairly straightforward Three.js Application.

Overview: The concept involves navigating with your camera along a path through a virtual "world". This world consists entirely of basic Sprites with SpriteMaterials adorned with transparent textures. These textures essentially consist of GIF images with alpha transparency.

The entire application is functioning smoothly and the performance is commendable. I have minimized the camera depth to render objects only in close proximity, enhancing efficiency.

However, I am encountering an issue where the memory usage is escalating significantly (exceeding 2GB) due to the multitude of textures being used. Despite reusing Texture/Material references for identical elements within the scene (such as trees and rocks), the memory consumption continues to rise.

When traversing through the world, not all objects are initially visible or displayed, even though all sprites are added to the scene from the start. Upon inspection in the console, it becomes apparent that textures for non-visible objects are loaded only when progressing further into the world and new elements come into view. Consequently, the memory usage gradually climbs.

Implementing "object pooling" for constructing the world is not feasible due to its specific layout constraints.

In order to test this scenario, I incorporated a function that removes objects from the scene and disposes their material.map once the camera moves past them:

this.env_sprites[i].material.map.dispose();
this.env_sprites[i].material.dispose();
this.env_sprites[i].geometry.dispose();
this.scene.remove(this.env_sprites[i]);
this.env_sprites.splice(i,1);

This method effectively triggers garbage collection and releases memory. However, the challenge arises when moving back with the camera - the Sprites must be readded to the scene and the materials/textures loaded again, which poses a considerable strain on performance and seems inefficient.

Are there established techniques to address such a setup in terms of memory management and the process of removing and adding objects and textures (in the same location)?

I trust that I have sufficiently articulated the problem at hand.

Here is a visual representation of the "World" for reference:

https://i.sstatic.net/iLRYb.png

Answer №1

Individual sprites can waste a significant amount of memory due to their non-square shapes, leading to inefficiencies in storage space. Additionally, the inclusion of mipmaps for each sprite further contributes to high memory usage. On lower-end devices, you may encounter limitations on the quantity of textures you can utilize, potentially posing challenges.

To optimize GPU memory utilization when dealing with numerous distinct sprites, utilizing a texture atlas is recommended. By consolidating multiple sprites within a few textures and assigning unique UV coordinates for each sprite, memory consumption can be minimized. While some memory wastage may still occur over time due to defragmentation, employing texture atlases significantly reduces the rate at which memory is depleted. Texture atlases offer the advantage of potentially enabling the simultaneous loading of all sprites without frequent deallocations.

If approaching the issue programmatically appeals to you, consider utilizing a library designed for dynamic management of sprite texture atlases. This tool, originally created for text rendering, utilizes canvas functions to generate images. It employs a basic Knapsack algorithm for sprite allocation across textures, reducing the reliance on numerous individual sprite textures in favor of just a couple of larger ones. This method proves highly efficient in conserving GPU memory.

For offline applications, specialized tools exist to streamline the generation of texture atlases and UV coordinates for sprites. Combining node.js with the aforementioned library could facilitate offline creation of textures and UV data for subsequent online use in a three.js environment. The process of integrating these components is left as an exercise for individuals interested in this approach.

Another strategy worth exploring involves grouping commonly used sprites into primary texture atlases that remain loaded at all times, while selectively loading and unloading less frequently utilized sprites as needed.

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

Tips for managing modal closure when the InertiaJS form succeeds?

Hello everyone! Currently, I'm involved in a Laravel project where I am using laravel/breeze VueJS with Inertia. The login functionality is implemented using a bootstrap modal component. While validation and authentication are working smoothly, the on ...

Switching to a different view in a React Native application

I am encountering difficulties while navigating between pages in my React Native application. Whenever I try to use the button, an error message pops up saying: TypeError: undefined is not an object (evaluating '_this.props.navigation'). My app c ...

Efficient methods for adding data to pages using Node.js

Since transitioning from PHP to NodeJS, I have been exploring new ways of sending data and am curious if there is something equivalent to the 'echo' function in NodeJS. I am looking for a method that would allow me to send data in parts, enabling ...

In the process of creating my initial discord bot, struggling to incorporate advanced functionalities beyond basic commands

I am currently using discord.js and JavaScript to code. I have created a test bot and followed step-by-step guides meticulously, but the bot only responds to basic "ping pong" commands. Whenever I try to add more complex commands, the bot stops functioning ...

Obtain the parameter fetching identical identifier

When I click on a search result on the left, I want it to load in the right div without refreshing the page or opening a new one. The search generates three results with pagination. However, no matter which result I click, the same ID loads. Can anyone spo ...

A JavaScript function that smoothly scrolls an element into view while considering any scrollable or positioned parent elements

I needed a function that could smoothly scroll a specific element into view with some intelligent behavior: If the element is a descendant of a scrollable element, I wanted the ancestor to be scrolled instead of the body. If the element is within a posit ...

When scrolling down, the popup window shifts its position

I have implemented a popup window which displays a list on hover. It works perfectly on the default page, but when I scroll down, the popup also moves with the scrollbar. Below is the HTML code that creates the hidden popup list initially and shows it on ...

Locating Undiscovered Users within mongodb

I have created a post collection where each user who marks a post as read has their user ID added to an array within the post document. Now, I am attempting to identify which users have not read certain posts by utilizing the $nin function while iteratin ...

Node.js and Angular.js communication: from requests to responses

Efforts are being made to solicit data from a node.js server through angular.js. However, an unexpected challenge persists: post-data response, a stark white browser screen shows up with the JSON object in plain sight. The goal is for angular.js to acknowl ...

Invoke JavaScript when the close button 'X' on the JQuery popup is clicked

I am implementing a Jquery pop up in my code: <script type="text/javascript"> function showAccessDialog() { var modal_dialog = $("#modal_dialog"); modal_dialog.dialog ( { title: "Access Lev ...

An incorrect object was removed from the array

Having an issue where the wrong item is getting deleted from an array in my component's state. Here is a simplified version of my parent Component: export default class BankList extends Component { state = { banks: [new Bank("Name1"), new ...

ExpressJS and cookies - Struggling to initialize a cookie with express-cookie

I recently followed a tutorial on YouTube (https://youtu.be/hNinO6-bDVM?t=2m33s) that demonstrated how to display a cookie in the developer tools Application tab by adding the following code snippet to the app.js file: var session = require('express- ...

What is the process for implementing a fallback image in Material UI?

Hey there! I'm currently looking to customize the fallback image of a Material UI Avatar with my own original image. Does anyone have any tips on how I can achieve this? const fallbackImage = "../../fallback/img.png" const AvatarWithBadge = ...

CSS positioning with absolute value + determine the number of elements positioned above

Is it feasible to adjust the position of an absolutely positioned element based on the height of the element above it? The objective is to align elements with the class "pgafu-post-categories" one line above an H2 heading, even when the lengths v ...

Steps for configuring mode as 'open' when generating a shadow element with vue-custom-element

Here is the method I used to generate a shadow component Vue.customElement('my-element', MyElement, { shadow: true, shadowCss: mystyles, }); ...

Transfer information from an array to a Vue function

Having some difficulties passing data to the function myChart within the mounted section. As a beginner in vuejs, I'm struggling with identifying the issue. I am trying to pass data in labels and datasets, which are called from my function. Can anyone ...

Ways to extract a specific element from a webpage's body section

When utilizing node-fetch to retrieve the body of a site, I follow this process: import fetch from 'node-fetch'; (async () => { const response = await fetch('link'); const body = await response.text(); console.log(body) ...

Utilizing the checked or clicked property of radio buttons for my specific scenario

Hello everyone, I am currently working on Rails 3.2.13 and have implemented the following script in my view file. Whenever a user selects 'Other' as their owner type, I need the div with id=group_user_id to open and save the operation at the end. ...

AngularJS - Increase the input date by 6 hours before converting it to JSON

Is there a way to add 6 hours to an input date in AngularJS? I attempted the following code: var eventStart = new Date ($scope.event.startdateid); var startDate = new Date ( eventStart ); startDate.setHours ( eventStart.getHours() + 6 ); event.startdate ...

The code malfunctions following the maintenance

Recently, I started learning JavaScript and trying to improve the readability of my code by moving away from inline functions. I have a piece of code that iterates through a JSON array containing comments and then appends those comments to the DOM. Strange ...