opengl — Perlin Noise, получающий неправильные значения по оси Y (C ++)

Я пытаюсь реализовать алгоритм Perlin Noise в 2D с одной октавой размером 16×16. Я использую это как данные карты высот для ландшафта, однако кажется, что он работает только по одной оси. Всякий раз, когда точка выборки перемещается в новую секцию Y в сетке Perlin Noise, градиент сильно отличается от того, что я ожидаю (например, он часто колеблется от 0,98 до -0,97, что является очень внезапным изменением).
введите описание изображения здесь

Это изображение показывает рельефную местность в направлении z (которая является осью y в 2D-сетке Perlin Noise)

Я поместил код, который вычисляет, какую точку выборки использовать в конце, так как она довольно длинная, и я считаю, что проблема не в этом, но, по сути, я уменьшаю ландшафт, чтобы соответствовать сетке Perlin Noise (16×16), а затем пробую через все точки.

Градиент в точке

Таким образом, код, который вычисляет градиент в точке выборки, выглядит следующим образом:

// Find the gradient at a certain sample point
float PerlinNoise::gradientAt(Vector2 point)
{
// Decimal part of float
float relativeX = point.x - (int)point.x;
float relativeY = point.y - (int)point.y;
Vector2 relativePoint = Vector2(relativeX, relativeY);

vector<float> weights(4);

// Find the weights of the 4 surrounding points
weights = surroundingWeights(point);float fadeX = fadeFunction(relativePoint.x);
float fadeY = fadeFunction(relativePoint.y);float lerpA = MathUtils::lerp(weights[0], weights[1], fadeX);
float lerpB = MathUtils::lerp(weights[2], weights[3], fadeX);
float lerpC = MathUtils::lerp(lerpA, lerpB, fadeY);return lerpC;
}

Окружающие веса точки

Я полагаю, что проблема где-то здесь, в функции, которая вычисляет веса для 4 окружающих точек точки выборки, но я не могу понять, что не так, так как все значения кажутся разумными в функции при переходе через нее ,

// Find the surrounding weight of a point
vector<float> PerlinNoise::surroundingWeights(Vector2 point){

// Produces correct values
vector<Vector2> surroundingPoints = surroundingPointsOf(point);

vector<float> weights;

for (unsigned i = 0; i < surroundingPoints.size(); ++i) {
// The corner to the sample point
Vector2 cornerToPoint = surroundingPoints[i].toVector(point);

// Getting the seeded vector from the grid
float x = surroundingPoints[i].x;
float y = surroundingPoints[i].y;
Vector2 seededVector = baseGrid[x][y];

// Dot product between the seededVector and corner to the sample point vector
float dotProduct = cornerToPoint.dot(seededVector);

weights.push_back(dotProduct);
}

return weights;

}

Настройка OpenGL и точка выборки

Настройка карты высот и получение точки выборки. Переменные «неправильный A» и «неправильный A» является примером того, когда градиент переворачивается и изменяется внезапно.

void HeightMap :: GenerateRandomTerrain () {

int perlinGridSize = 16;

PerlinNoise perlin_noise = PerlinNoise(perlinGridSize, perlinGridSize);

numVertices = RAW_WIDTH * RAW_HEIGHT;
numIndices = (RAW_WIDTH - 1) * (RAW_HEIGHT - 1) * 6;

vertices = new Vector3[numVertices];
textureCoords = new Vector2[numVertices];
indices = new GLuint[numIndices];

float perlinScale = RAW_HEIGHT/ (float) (perlinGridSize -1);

float height = 50;

float wrongA = perlin_noise.gradientAt(Vector2(0, 68.0f / perlinScale));
float wrongB = perlin_noise.gradientAt(Vector2(0, 69.0f / perlinScale));

for (int x = 0; x < RAW_WIDTH; ++x) {
for (int z = 0; z < RAW_HEIGHT; ++z) {
int offset = (x* RAW_WIDTH) + z;

float xVal = (float)x / perlinScale;
float yVal = (float)z / perlinScale;

float noise = perlin_noise.gradientAt(Vector2( xVal , yVal));

vertices[offset]        = Vector3(x * HEIGHTMAP_X,      noise * height,  z * HEIGHTMAP_Z);
textureCoords[offset]   = Vector2(x * HEIGHTMAP_TEX_X,  z * HEIGHTMAP_TEX_Z);

}
}
numIndices = 0;
for (int x = 0; x < RAW_WIDTH - 1; ++x) {
for (int z = 0; z < RAW_HEIGHT - 1; ++z) {
int a = (x      * (RAW_WIDTH)) + z;
int b = ((x + 1)* (RAW_WIDTH)) + z;
int c = ((x + 1)* (RAW_WIDTH)) + (z + 1);
int d = (x      * (RAW_WIDTH)) + (z + 1);

indices[numIndices++] = c;
indices[numIndices++] = b;
indices[numIndices++] = a;

indices[numIndices++] = a;
indices[numIndices++] = d;
indices[numIndices++] = c;
}
}
BufferData();

}

2

Решение

Оказалось, проблема была в стадии интерполяции:

 float lerpA = MathUtils::lerp(weights[0], weights[1], fadeX);
float lerpB = MathUtils::lerp(weights[2], weights[3], fadeX);
float lerpC = MathUtils::lerp(lerpA, lerpB, fadeY);

У меня была неправильная интерполяция по оси Y, так что это должно было быть:

lerp(lerpB, lerpA, fadeY)

Вместо:

lerp(lerpA, lerpB, fadeY)
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]