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.