What I have
I am experimenting with procedural terrain generation. I have a class called TerrainGenerator, which takes width and segments as parameters and uses them to create a PlaneGeometry. Then, I iterate over all vertices and compute their height based on their x and y positions using simplex noise and other techniques. I have also implemented a biome system that assigns colors based on specific rules. After looping through all vertices, I use the setAttribute method to add colors to my PlaneGeometry.
// pseudocode
const geometry = new THREE.PlaneGeometry(width, width, segments, segments);
let vertices = this.geometry.attributes.position.array;
const colors = new Float32Array(vertexCount * 3);
for (let i = 0; i <= vertices.length; i += 3) {
const z = noise(x, y);
vertices[i + 2] = z;
const color = predictBiome(z, climate).color;
colors[i] = color.r;
colors[i + 1] = color.g;
colors[i + 2] = color.b;
}
geometry.attributes.position.needsUpdate = true;
geometry.setAttribute('color', new BufferAttribute(colors, 3));
geometry.computeVertexNormals();
return this.geometry;
As a material for the mesh created with this geometry, I use a standard material:
const material = new THREE.MeshStandardMaterial({
vertexColors: true,
flatShading: false,
});
The result looks like this:
As you can see colors are dynamically assigned based on some set of rules. Now i want to take it step futher and instead of using raw colors I want to add some textures.
What I tried to do
I can easily add some texture to whole PlaneGeomerty and create mesh, which looks like this:
But I’m stuck when it comes to placing multiple textures on it. I attempted to use shaders to blend textures. I even managed to implement a shader that dynamically selects one of two available textures.
Unlike the previous approach, which used MeshStandardMaterial with a texture passed as a map, this one uses ShaderMaterial. However, the problem is that the PlaneGeometry is no longer affected by the lights in my scene. From what I’ve read, I would need to manually implement lighting effects in the shader to make this work. Additionally, this approach makes it difficult to integrate my existing biome system abstraction (or at least, I am not aware of an efficient way to do so).
ChatGPT came up with using MultiMaterial, but from what I understand, this would require computing separate groups for every biome instance in my PlaneGeometry, which seems problematic.
Have you any tips or advice for this situation? Are there better solution about which i didn’t think about? Or maybe I should use one of mentioned approaches? I’m not really into computer graphics, and I work with Three.js very little so I could miss something obvious.



