Procedural generation in Three.js involves algorithmically creating 3D content rather than manually modeling it. This technique is highly valuable for generating diverse and dynamic scenes, reducing memory footprint, and enabling real-time content creation.
BufferGeometry class is fundamental for this, allowing efficient creation and manipulation of complex shapes.PlaneGeometry based on a heightmap. Heightmaps are typically generated using noise functions like Perlin noise or Simplex noise, which produce organic, natural-looking patterns.This example demonstrates a conceptual approach to generating a simple procedural terrain using a noise function to displace vertices of a plane. This requires a Three.js setup.
import *s THREE from 'three';
// Scene, Camera, Renderer setup (assuming these are already defined)
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Add basic lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Create a plane geometry
const planeGeometry = new THREE.PlaneGeometry(10, 10, 100, 100); // Large number of segments for detail
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00, wireframe: false });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2; // Rotate to be horizontal
scene.add(plane);
// Simple noise function (conceptual - a real noise function would be more complex)
function getNoise(x, y) {
return Math.sin(x * 0.5) * Math.cos(y * 0.5) * 0.5 + 0.5;
}
// Displace vertices based on noise
const positionAttribute = plane.geometry.getAttribute('position');
for (let i = 0; i < positionAttribute.count; i++) {
const x = positionAttribute.getX(i);
const y = positionAttribute.getY(i);
const z = positionAttribute.getZ(i);
const noiseValue = getNoise(x, y);
positionAttribute.setZ(i, z + noiseValue * 2); // Displace along Z (up/down)
}
positionAttribute.needsUpdate = true; // Important: tell Three.js to update the buffer
plane.geometry.computeVertexNormals(); // Recalculate normals for correct lighting
camera.position.set(0, 5, 5);
camera.lookAt(0, 0, 0);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});