Попытка использовать perlinnoise для генерации ландшафта

#c #noise #procedural-generation

#c #шум #процедурная генерация

Вопрос:

Я пытаюсь сгенерировать процедурный ландшафт, используя шум Перлина. Раньше я просто создавал ландшафт размером 1000 * 1000 вершин, поэтому у меня была простая функция, которая заполняла карту высот значениями шума.

Однако сейчас я пытаюсь сгенерировать ландшафт, который генерирует фрагменты при перемещении камеры, и я не думаю, что этот метод подходит, поскольку каждый фрагмент будет сгенерирован с его собственной случайной картой высот, и фрагменты не будут выглядеть согласованными друг с другом. Вместо этого я использую этот заголовочный файл для генерации шума, который просто принимает и x и y, но какие бы значения я ни давал, они, похоже, не генерируют согласованные значения, и я не уверен, почему

 class Noise {    
public:
int seed;

Noise(int seed) {
    this->seed = seed;
}

float noise(int x, int y) {
    int n = x   y * 57   seed;
    n = ( n << 13 ) ^ n;
    float rand = 1 - ( (n * (n * n * 15731   789221)   1376312589) amp; 0x7fffffff) / 1073741824.0f;
    return rand;
}

float noise(int x, int y, int z) {
    int n = x   y   z * 57   seed;
    n = ( n << 13 ) ^ n;
    float rand = 1 - ( (n * (n * n * 15731   789221)   1376312589) amp; 0x7fffffff) / 1073741824.0f;
    return rand;
}

float smoothNoise(int x, int y) {
    float corners = (noise(x 1, y 1)   noise(x 1, y-1)   noise(x-1, y 1)   noise(x-1, y-1)) / 16.0f;
    float sides = (noise(x, y 1)   noise(x, y-1)   noise(x-1, y)   noise(x 1, y)) / 8.0f;
    float center = noise(x, y) / 4.0f;
    
    return corners   sides   center;
}

float interpolatedNoise(float x, float y) {
    int integerX = (int)x;
    float fractionalX = x - integerX;
    
    int integerY = (int)y;
    float fractionalY = y - integerY;
    
    float v1 = smoothNoise(integerX, integerY);
    float v2 = smoothNoise(integerX   1, integerY);
    float v3 = smoothNoise(integerX, integerY   1);
    float v4 = smoothNoise(integerX   1, integerY   1);
    
    float i1 = interpolateCosine(v1, v2, fractionalX);
    float i2 = interpolateCosine(v3, v4, fractionalX);
    
    return interpolateCosine(i1, i2, fractionalY);
    
}

// x must be in the range [0,1]
float interpolateLinear(float a, float b, float x) {
    return a * (1 - x)   b * x;
}

float interpolateCosine(float a, float b, float x) {
    float ft = x * (float)glm::pi<float>();
    float f = (1 - ((float)glm::pi<float>())) * 0.5f;
    return a * (1 - f)   b * f;
} 
 

};`

Я вызываю interpolatedNoise() следующим образом:

 for(int y=x; x < config->width;x  )
{
   for(int y = 0; y < config->height;y  )
   { 
       map[x * config->height   y] = noise.interpolatedNoise((config->width * gridPosX   x) * 0.1f,(config->height * gridPosY   y) * 0.1f)/2.0f   0.5f; // convert from -1:1 to 0:1
   }  
} 
 

Вот как выглядит ландшафт с помощью этого
#10;:

но я хочу, чтобы ландшафт был гладким. Параметры, которые я передаю в функцию, делятся на некоторое значение. Чем больше я делаю это значение для более случайного ландшафта, тем меньше поля, и чем меньше я его делаю, я просто получаю большие поля, но более однородный ландшафт.

Ответ №1:

Я не совсем уверен, как вы вызываете свой конструктор шума, но одна проблема, которую я вижу, заключается в конструкторе. Так и должно быть this->seed = seed; , иначе вы присваиваете начальное значение аргумента самому себе. Начальная переменная шума тогда была бы просто случайным числом, и я чувствую, что это вызывает проблемы. Опять же, не уверен, как ваш вызывающий конструктор шума, но это мое лучшее предположение.

Комментарии:

1. Я только что случайно избавился от ‘this->’ при попытке доработать код в этом сообщении. Спасибо, что указали на это.

2. Да, не был уверен, было ли это намеренно или нет. Оставил бы комментарий, но недостаточно репутации.