Rendering enormous amount of images for NFT game

The past few weeks I have been thinking of creating some sort of NFT game as a web application. I have some ideas in my mind but I have been stuck on one specific idea due to a performance issue.

I am not going into the details of the game but the application should somehow be able to render an enormous amount of images. NFT ‘spacing’ (in different sizes) can be claimed by the user. This claimed space should display the user’s most valuable NFT. I assume that this will soon no longer be as efficient due to the large number of images.

I was thinking of using Three.js to accomplish this. I have looked in to concepts like Point clouds, InstancedMesh, LOD and Frustum Culling a little bit. But from what I understand, even with things like this, it can still be very difficult (or maybe even impossible) to deal with huge amounts. I am talking about hundreds of thousands, in an unlikely and extreme case, let’s even think of a million images.

Now let’s suppose I would only need to display a huge amount of images on some sort of landing page on which I can then navigate further. Instead of using Three.js I started thinking about compressing images myself using an automated back-end maybe and then just displaying them in the front-end, use lazy loading etc, but again, doesn’t seem like a really performant way of doing this to me?

I was just wondering if anyone would have other ideas on how one could create something like this? How limited are the average hardware capabilities? Could it be possible using Three.js, maybe I just don’t have enough knowledge about it yet?

Hi, I don’t know if this would be useful to you, but I am working on an InstancedMesh class that also includes frustum culling and other optimisations. In the case of non-animated meshes with simple geometries, if only one part is in the frustum, it can render up to a million of them.

Here is an example of the almost finished class:

const boxes = new InstancedMesh2({
  geometry: new BoxGeometry(),
  material: new MeshNormalMaterial(),
  count: 1000000,
  onCreateEntity: (obj, index) => {
    obj.position.random().multiplyScalar(500).subScalar(250);
    obj.quaternion.random();
    obj.scale.random().addScalar(0.1);
  },
});
1 Like

Each draw call can use no more than ~16 textures depending on your hardware. A common rule of thumb is to aim for no more than 100 draw calls.

Each 1K image is about 6 MB in memory, including mipmaps. One 4K image is about 90 MB in memory. Mobile devices begin to crash if you use more than 200–500 MB memory.

From those numbers alone, it will be very hard to really load millions of images. I would look for ways to give the appearance of more, for example by creating a large spritesheet with lower resolution versions of all the images, and only loading high-resolution versions of the images you need to show in more detail.

5 Likes