Visible Grid-Lines in Perlin Noise Generation Algorithm

26 Views Asked by At

I'm trying to create a Perlin-Noise Generation algorithm for a personal project, and I've run into a problem in which the resulting noise has very visible switch-ups in the colors between grids. The image is below it is originally in BMP format: The current result

I've tried switching some of the x/y and x2/y2 variables in some of the statements, including the easedInterpolation arguments, as well as trying to normalize the offset variables (calculated in the dotProduct() calls).

Here is my code:

#include "../include/NoiseGenerator.hpp"
#include "../include/Math.hpp"
#include <cmath>
#include <ctime>
#include <ratio>
#include <iostream>
#include <chrono>

using namespace Math;
using namespace std::chrono;

float easedInterpolate(float a, float b, float x);

std::vector<Color> NoiseGenerator::generatePerlinNoise(int finalWidth, int finalHeight, int spacing) {
    // Generate gradients
    double theta;
    std::vector<vec2> normals((finalWidth / spacing + 1) * (finalHeight / spacing + 1));
    high_resolution_clock::time_point start = high_resolution_clock::now();
    for (int i = 0; i < normals.size(); i++) {
        srand(i + 1000000000 * duration_cast<duration<double>>(high_resolution_clock::now() - start).count());
        theta = (rand() % 360) * 3.1415 / 180.0;
        normals[i] = vec2(sin(theta), cos(theta));
    }
    vec2 tLCorner, tRCorner, bLCorner, bRCorner;
    float tL, tR, bL, bR, xI1, xI2, finalColor;
    std::vector<Color> result(finalWidth * finalHeight);
    // Traverse cells
    for (int x = 0; x < finalWidth / spacing; x++) {
        for (int y = 0; y < finalHeight / spacing; y++) {
            // Find the four corner normals
            tLCorner = normals[x + (finalWidth / spacing + 1) * y];
            tRCorner = normals[(x + 1) + (finalWidth / spacing + 1) * y];
            bLCorner = normals[x + (finalWidth / spacing + 1) * (y + 1)];
            bLCorner = normals[(x + 1) + (finalWidth / spacing + 1) * (y + 1)];
            // Traverse pixels
            for (int x2 = 0; x2 < spacing; x2++) {
                for (int y2 = 0; y2 < spacing; y2++) {
                    // Calculate dot-products with four corners
                    tL = dotProduct(vec2(x2, y2) / spacing, tLCorner);
                    tR = dotProduct(vec2(x2 - spacing, y2) / spacing, tRCorner);
                    bL = dotProduct(vec2(x2, y2 - spacing) / spacing, bLCorner);
                    bR = dotProduct(vec2(x2 - spacing, y2 - spacing) / spacing, bRCorner);
                    // Interpolate values
                    xI1 = easedInterpolate(tL, tR, (float) x2 / (float) (spacing - 1));
                    xI2 = easedInterpolate(bL, bR, (float) x2 / (float) (spacing - 1));
                    finalColor = (easedInterpolate(xI1, xI2, (float)y2 / (float) (spacing - 1)) + 1.0) / 2.0f;

                    result[(x * spacing) + x2 + ((y * spacing) + y2) * (finalWidth)] = Color(255, 255, 255) * finalColor;
                }
            }
        }
    }

    return result;
}

float easedInterpolate(float a, float b, float x)
{
    float easedX = 6*x*x*x*x*x - 15*x*x*x*x + 10*x*x*x;
    return a + (b - a) * easedX;
}
0

There are 0 best solutions below