Creating a visually stunning landscape in Three.JS by rendering a detailed map using various texture atlas tilesets

Introduction:

In my current project, I am using Three.JS (v95, WebGL Renderer) to render an isometric map that consists of various graphic tilesets. The specific tile is obtained through a TextureAtlasLoader and its position from a JSON file. Here's an example of what the map looks like: https://i.sstatic.net/Jbh2X.png

However, as I add more tiles to the map (approximately 120,000 tiles), the performance decreases significantly. Moving the camera becomes sluggish and challenging. While I understand that there are better approaches than adding each tile as a sprite to the scene, I'm struggling to implement them effectively.

Here is an excerpt from the code used to create the tiles within a loop:

var ts_tile = Map.Imagesets[ims].Map.getTexture((bg_left / tw), (bg_top / th));
var material = new THREE.SpriteMaterial({ map: ts_tile, color: 0xffffff, fog: false });
var sprite = new THREE.Sprite(material);
sprite.position.set(pos_left, -top, 0);
sprite.scale.set(tw, th, 1);

scene.add(sprite)

I've also attempted rendering the tiles as Mesh, but it hasn't improved performance:

var material = new THREE.MeshBasicMaterial({ map: ts_tile, color: 0xffffff, transparent: true, depthWrite: false });
var geo = new THREE.PlaneGeometry(1, 1, 1);
var sprite = new THREE.Mesh(new THREE.BufferGeometry().fromGeometry(geo), material);

Possible solutions explored:

I've discovered that adding numerous sprites or meshes to a scene negatively impacts performance. Despite trying different methods and studying examples where similar scenarios work smoothly, I haven't been able to adapt those approaches to my own code. Each tile on my map has a unique texture and position.

An example in the official three.js documentation showcases the use of PointsMaterial and Points, reducing the number of rendered elements significantly while maintaining visual integrity. They only add 5 points to the scene, which represent around 10,000 "vertices/images". Documentation link:

Another approach can be found on GitHub at https://github.com/YaleDHLab/pix-plot. In this project, they construct 5 meshes, each containing roughly 4,096 "tiles" built with Faces, Vertices, etc.

Final question:

My main concern revolves around improving the performance of rendering my map. I find myself overwhelmed by the task of implementing one of the potential solutions suggested above. How can I tackle this challenge efficiently?

Answer №1

In my opinion, following the advice of Sergiu Paraschiv seems like a step in the right direction. Breaking up your rendering process into smaller chunks could greatly improve performance. You can find more tips on optimizing tilemap performance in this article: Optimizing Tilemap Performance. Depending on the complexity of your terrain, adjusting the size of these chunks may be necessary. By only re-rendering sections that have changed, you can optimize efficiency. If your terrain remains static, consider rendering the entire landscape onto a texture to minimize processing power. This tutorial on rendering to a texture in Three.js offers valuable insights to get you started on rendering your chunks effectively.

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

Any ideas on how I can adjust this basic JSON to avoid triggering the "Circular structure to JSON" error?

Learning Journey I am currently teaching myself JavaScript and exploring JSON along the way. My current project involves developing a JavaScript WebScraper where I plan to store my results in JSON format. While I am aware of other methods like using data ...

Tallying the number of messages on Facebook

Greetings everyone! I have been utilizing the Facebook JS SDK to retrieve the number of messages sent. Below is the code snippet: <script> function statusChangeCallback(response) { console.log('statusChangeCallback'); console.log ...

Exploring the intersection of objects and shader materials in Three.js

My current scene features objects intersected using Lambert material, as showcased in this jsFiddle. Now I'm exploring the idea of switching the material of one particular plane to a Shader material, which would transform the plane into a background ...

A helpful guide on resetting ReactJs to its default state when data is not found

Currently, I'm fetching data from my database, but just for the sake of this question, I have opted to manually create an example with fake data. I am in the process of creating a search bar for my users to navigate through all the data retrieved fro ...

Using Ajax to dynamically generate column headers in Datatables

Is there a way to create a header title from an ajax file? I've been trying my best with the following code: $('#btntrack').on('click', function() { var KPNo = $('#KPNo').val(); var dataString = & ...

Import data from a file into a JavaScript 2D array

Looking for a way to load an array from a text file in JavaScript? Here's what I have: var linePoints = [[0, 3], [4, 8], [8, 5], [12, 13]]; But rather than defining it in the code, I'd like to read it from a text file. The file looks like this: ...

Incorporate WebGL visuals into PowerPoint presentations or generate animated GIFs directly from WebGL content

Has anyone discovered a method for embedding a webgl animation into PowerPoint? Are there any server-side tools available to capture an animated GIF? I've been unsuccessful in my attempts to directly embed webgl HTML into PowerPoint. ...

ng-change not firing when selecting from ng-options list

I am struggling with this code snippet <select ng-model="trabajadores.orderSelected" ng-options="excel for excel in trabajadores.csv.result[1]" ng-change="console.log('changed')"> </select> Despite my best ...

What is the best way to iterate through an array of images and upload them individually, ensuring that they do not have duplicate names

In my current code snippet, I am working with an array of images called images and uploading each image within that array. Everything seems to be working correctly, but I am encountering a minor issue where all the uploaded images end up having the same na ...

Error message: An undefined error occurred in the uncaught promise of an async function

Before creating or updating an entry, I am performing validations using the code snippet below: async save(){ return new Promise((resolve, reject)=>{ if(!this.isCampaignValid){ this.handleError() reject() } ...

Organizing mongoose functions in a nodejs application while utilizing promises

I'm looking to enhance the organization of my code by keeping certain mongoose functions separate. I want to work with promises for better handling, and below is a demonstration of my approach. In my Model.js file, var User = module.exports = mongoo ...

The vue-croppa component is showing unusual behavior, with an error message stating "Failed to mount component: template or render function not

I recently tried utilizing vue-croppa for image cropping in my project. I installed it using the npm package manager with the command: npm install --save vue-croppa However, when attempting to implement it as usual: import Croppa from 'vue-croppa&a ...

Update Jquery Dialog's Button After Making an Ajax Request

I am facing an issue with my dialog window that contains some confirmation elements following a form submission: $('#newUserDialog').dialog({ autoOpen: false, width: 600, modal: true, resizable: false, cl ...

Using AngularJS to invoke the ng-required directive and trigger a function

Is it possible to make the required value dependent on a function? Something similar to this? I need to achieve this in order to dynamically change the required attribute for form inputs... HTML: Name: <input type="text" ng-model="user.name" ng-r ...

The integration of Material-UI Autocomplete and TextField causes google autocomplete to activate

I am currently working on integrating the Autocomplete component into my project. However, I am facing an issue where the browser's autofill/autocomplete feature kicks in after some time. Is there a way to disable this behavior? ...

Encountering an error of "Cannot set headers after they are sent" when attempting to manage a user session during a test using the Chai request agent

We're currently facing a challenge with an error message stating Uncaught Error: Can't set headers after they are sent. when attempting to link a user sign-in to a test using chai-http. The test signs in a user already existing in the database v ...

Creating a JSON object from an array of data using TypeScript

This might not be the most popular question, but I'm asking for educational purposes... Here is my current setup: data = {COLUMN1: "DATA1", COLUMN2: "DATA2", COLUMN3: "DATA3", ..., COLUMNn: "DATAn"}; keyColumns = ["COLUMN2", "COLUMN5", "COLUMN9"]; ...

Verify the existence of the email address, and if it is valid, redirect the user to the dashboard page

Here is the code snippet from my dashboard's page.jsx 'use client' import { useSession } from 'next-auth/react' import { redirect } from 'next/navigation' import { getUserByEmail } from '@/utils/user' export d ...

Concealing external scripts on specific webpages

In my HTML template, I have integrated a third-party JavaScript code that provides a chat option. This script is included in my header.html so that it appears on all pages. However, I do not want this chat option to display on the login page. I want it to ...

Running concurrently, the JavaScript if and else statements execute together

I am looking to create a clickable link that changes the background color when clicked. If the same link is clicked again, I want the background to return to its original state. Here is my current script: <div style="background: transparent;" onclick=" ...