public static void GenerateNoiseMapWithSmoothManyBioms(int width, int height, int seed, float offsetX,float offsetZ,float CHUNK_SIZE, int[] biombsIds, out float[] noiseMap, out float[] smooothNoiseMap){
// Массив данных о вершинах, одномерный вид поможет избавиться от лишних циклов впоследствии
noiseMap = new float[width*height];
smooothNoiseMap = new float[width*height];
// Порождающий элемент
System.Random rand = new System.Random(seed);
// Сдвиг октав, чтобы при наложении друг на друга получить более интересную картинку
float[] octavesOffsetX = new float[BiomInfo.MAX_OCTAVES];//МАКСИМАЛЬНОЕ КОЛИЧЕСТВО ОКТАВ КОТОРОЕ МОЖЕТ БЫТЬ в biomInfo
float[] octavesOffsetY = new float[BiomInfo.MAX_OCTAVES];//МАКСИМАЛЬНОЕ КОЛИЧЕСТВО ОКТАВ КОТОРОЕ МОЖЕТ БЫТЬ в biomInfo
for (int i = 0; i < BiomInfo.MAX_OCTAVES; i++){
// Учитываем внешний сдвиг положения
octavesOffsetX[i] = rand.Next(-100000, 100000);
octavesOffsetY[i] = rand.Next(-100000, 100000);
}
// Учитываем половину ширины и высоты, для более визуально приятного изменения масштаба
float halfWidth = width / 2f;
float halfHeight = height / 2f;
float scale, octaves, persistence, lacunarity, amplitude, frequency, noiseHeight, noiseHeightSmooth, superpositionCompensation;
// Генерируем точки на карте высот
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
scale = BiomInfo.BiomList[biombsIds[y * height + x]].Scale;
octaves = BiomInfo.BiomList[biombsIds[y * height + x]].Octaves;
persistence = BiomInfo.BiomList[biombsIds[y * height + x]].Persistence;
lacunarity = BiomInfo.BiomList[biombsIds[y * height + x]].Lacunarity;
// Задаём значения для первой октавы
amplitude = 1;
frequency = 1;
noiseHeight = 0;
noiseHeightSmooth = 0;
superpositionCompensation = 0;
var offset = new Vector2((((float)CHUNK_SIZE / scale) * (float)(CHUNK_SIZE * offsetX)), ((float)CHUNK_SIZE / scale) * (float)(CHUNK_SIZE * offsetZ));
// Обработка наложения октав
for (int i = 0; i < octaves; i++){
var octOffsetX = (octavesOffsetX[i] + offset.x)/width;
var octOffsetY = (octavesOffsetY[i] + offset.y)/height;
// Рассчитываем координаты для получения значения из Шума Перлина
float xResult = (x - halfWidth) / scale * frequency + octOffsetX * frequency;
float yResult = (y - halfHeight) / scale * frequency + octOffsetY * frequency;
// Получение высоты из ГСПЧ
float generatedValue = Mathf.PerlinNoise(xResult, yResult);
// Наложение октав
noiseHeight += generatedValue * amplitude;
// Компенсируем наложение октав, чтобы остаться в границах диапазона [0,1]
noiseHeight -= superpositionCompensation;
// Расчёт амплитуды, частоты и компенсации для следующей октавы
amplitude *= persistence;
frequency *= lacunarity;
superpositionCompensation = amplitude / 2;
if (i == 0) // сглаженная карта идёт на первой октаве
noiseHeightSmooth = noiseHeight;
}
// Сохраняем точку для карты высот
// Из-за наложения октав есть вероятность выхода за границы диапазона [0,1]
noiseMap[y*height+x] = Mathf.Clamp01(noiseHeight);
smooothNoiseMap[y*height+x] = Mathf.Clamp01(noiseHeightSmooth);
}
}
}
P.S. Кстате если пишешь на питоне, вообще отлично потому-что есть даже примеры кода, я писал на шарпе поэтому приходилось влазить в код нативных математических библиотек питона, чтобы понять как работают функции и переписать их под себя на C#. Но я их еще попутно оптимизировал поэтому всё работало еще быстрее