Does threejs's instancedMesh work when a lot are rendered?

I have been working on a voxel game in three.js. So far it’s going great! However, I came up with an idea to group the world into chunks, so I tried making each chunk (which is a 10 by 10 blocks area) as an instanced mesh. My code should work logically, however when I run the html file, the canvas doesn’t show any meshes or anything at all apart from the color of the scene. How can I render the instanced meshes of the chunks? Below is my code and some pictures.

    var chunks = [];
	var xoff = 0;
	var zoff = 0;
	var inc = 0.05;
	var amplitude = 30 + (Math.random() * 70);
	var renderDistance = 30;
	var chunkSize = 10;
	camera.position.x = renderDistance * chunkSize / 2 * 5;
	camera.position.z = renderDistance * chunkSize / 2 * 5;
	camera.position.y = 50;

	for(var i = 0; i < renderDistance; i++){
		for(j = 0; j < renderDistance; j++){
			var chunk = [];
			for(var x = i * chunkSize; x < (i * chunkSize) + chunkSize; x++){
				for(var z = j * chunkSize; z < (j * chunkSize) + chunkSize; z++){
					xoff = inc * x;
					zoff = inc * z;
					var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
					chunk.push(new Block(x * 5, v, z * 5));
				}
			}
			chunks.push(chunk);
		}
	}

	var loader = new THREE.TextureLoader();
	var materialArray = [
		new THREE.MeshBasicMaterial({map : loader.load("texture/side4.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side1.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/top.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/bottom.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side2.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side3.jpg")}),
	];

	var instancedChunkMeshes = [];
	var blockBox = new THREE.BoxGeometry(5, 5, 5);
	for(var i = 0; i < chunks.length; i++){ 
		var instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, chunks[i].length);
		for(var j = 0; j < chunks[i].length; j++){
			let matrix = new THREE.Matrix4().makeTranslation(
				chunks[i][j].x,
				chunks[i][j].y,
				chunks[i][j].z
			);
			instancedChunk.setMatrixAt(j, matrix);
		}
		instancedChunkMeshes.push(instancedChunk);
	}

	for(var i = 0; i < instancedChunkMeshes.length; i++){
		scene.add(instancedChunkMeshes[i]);
	}

The above code should work. However, when run it produces a blank screen…

Any help would be greatly appreciated!

Does this work if you use a single material, rather than a material array? I’m not sure whether InstancedMesh can support multiple materials, and it’d probably be more efficient if you can avoid that.

But to the original question – using multiple InstancedMesh batches in the same scene should be OK.

So you are saying that my code should work?

No, but the only obvious issue that I see is the use of multiple materials. If you can create a demo that reproduces the error I can try testing that.

Oh, maybe one other thing — InstancedMesh probably requires a BoxBufferGeometry, not a BoxGeometry.

1 Like