Процедурный ландшафт на основе шума

Процедурная генерация ландшафта в Three.js основана на создании геометрии, вершины которой определяются значениями шума. Наиболее часто используется Perlin Noise или Simplex Noise, обеспечивающие плавные, естественные переходы высот.

Основы создания геометрии

Для начала требуется плоскость, которая станет основой ландшафта:

const width = 200;
const height = 200;
const widthSegments = 199;
const heightSegments = 199;

const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
geometry.rotateX(-Math.PI / 2); // поворот для горизонтального расположения
  • width и height определяют размеры ландшафта.
  • widthSegments и heightSegments — количество сегментов, которые задают детализацию. Чем больше сегментов, тем более плавный и детализированный рельеф.

Использование шума для высот

Для генерации высот применяется шум, который возвращает значения от 0 до 1. Для Perlin Noise можно использовать библиотеку simplex-noise:

import SimplexNoise from 'simplex-noise';

const simplex = new SimplexNoise();

const vertices = geometry.attributes.position.array;

for (let i = 0; i < vertices.length; i += 3) {
    const x = vertices[i];
    const z = vertices[i + 2];

    const y = simplex.noise2D(x * 0.05, z * 0.05) * 10; // масштабирование координат и высоты
    vertices[i + 1] = y;
}

geometry.computeVertexNormals();
  • Масштаб координат (x * 0.05) управляет частотой шума: меньше значение — плавный рельеф, больше — более мелкие детали.
  • Масштаб высоты (* 10) контролирует максимальную амплитуду гор и впадин.
  • После изменения вершин необходимо вызвать computeVertexNormals() для корректного расчета освещения.

Материалы для ландшафта

Выбор материала влияет на визуальное восприятие рельефа. Для базового варианта используют MeshStandardMaterial с текстурами и картой нормалей:

const material = new THREE.MeshStandardMaterial({
    color: 0x556655,
    roughness: 0.8,
    metalness: 0.2,
});

Для имитации разнообразия можно использовать градиент высот:

const colors = [];

for (let i = 0; i < vertices.length; i += 3) {
    const y = vertices[i + 1];
    let color = new THREE.Color();

    if (y < 2) color.set(0x223322);        // низины — темно-зеленые
    else if (y < 6) color.set(0x55aa55);   // средние участки — зеленые
    else color.set(0xaaaaaa);               // вершины — серые

    colors.push(color.r, color.g, color.b);
}

geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
material.vertexColors = true;

Оптимизация производительности

  • LOD (Level of Detail): для больших ландшафтов следует использовать несколько уровней детализации, чтобы при удалении от камеры уменьшать количество вершин.
  • Instancing: для повторяющихся объектов (деревья, камни) применяется InstancedMesh.
  • Dynamic updates: при необходимости анимации рельефа изменяются только атрибуты вершин, избегая пересоздания геометрии.

Освещение и тени

Для реалистичного отображения рельефа необходимы направленные источники света и корректные тени:

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(50, 100, 50);
directionalLight.castShadow = true;

scene.add(directionalLight);
mesh.castShadow = true;
mesh.receiveShadow = true;
  • Тени подчеркивают рельеф, создавая ощущение глубины.
  • Важна оптимизация параметров shadow.mapSize и shadow.camera для снижения нагрузки.

Анимация и изменение рельефа

Процедурный ландшафт легко анимировать, изменяя параметры шума во времени:

const time = performance.now() * 0.0001;

for (let i = 0; i < vertices.length; i += 3) {
    const x = vertices[i];
    const z = vertices[i + 2];

    vertices[i + 1] = simplex.noise3D(x * 0.05, z * 0.05, time) * 10;
}

geometry.attributes.position.needsUpdate = true;
geometry.computeVertexNormals();
  • Использование 3D-шума (noise3D) позволяет плавно анимировать рельеф.
  • needsUpdate = true обязательно для обновления позиции вершин в WebGL.

Дополнительные улучшения

  1. Текстурирование с картой высот — реалистичное сочетание травы, камней, снега.
  2. Эрозия и фильтры — моделирование естественных процессов: сглаживание крутых склонов, накопление осадков.
  3. Добавление растительности и объектов — при помощи InstancedMesh и процедурной расстановки объектов на основе высоты и наклона.

Процедурная генерация ландшафта в Three.js сочетает математику шума, гибкую работу с геометрией и освещением, обеспечивая детализированные и динамичные 3D-сцены. Такой подход позволяет создавать разнообразные миры без использования готовых моделей и текстур.