c # – Wonky perlin noise

I am quite new to the wonderful world of "Procedural textures," and I am trying to create a double precision noise perlin algorithm.

noise

I'm almost done, except for the fact that the coordinates seem to be off, any idea what I've done wrong? Here is the code:


public static class Noise {
    static int() p = new int(Convert.ToInt32(Math.Pow(2,16)));
    public static vector2dDouble v1i;
    public static vector2dDouble v2i;
    public static vector2dDouble v3i;
    public static vector2dDouble v4i;

    public static double(,) GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector3 offset) {
        double(,) noiseMap = new double(mapWidth, mapHeight);

        System.Random prng = new System.Random(seed);
        Vector2() octaveOffsets = new Vector2(octaves);
        for (int i = 0; i < octaves; i++) {
            float offsetX = prng.Next(-100000, 100000) + offset.x;
            float offsetY = prng.Next(-100000, 100000) + offset.z;
            octaveOffsets(i) = new Vector2(offsetX, offsetY);
        }

        if (scale <= 0) {
            scale = 0.0001f;
        }

        float maxNoiseHeight = float.MinValue;
        float minNoiseHeight = float.MaxValue;

        float halfWidth = mapWidth / 2f;
        float halfHeight = mapHeight / 2f;

        for (int y = 0; y < mapHeight; y++) {
            for (int x = 0; x < mapWidth; x++) {

                float amplitude = 1;
                float frequency = 1;
                double noiseHeight = 0;

                for (int i = 0; i < octaves; i++) {
                    double sampleX = (double)(x - halfWidth) / scale * frequency + octaveOffsets(i).x + 0.001;
                    double sampleY = (double)(y - halfHeight) / scale * frequency + octaveOffsets(i).y + 0.001;

                    double perlinValue = Noise2d(sampleX, sampleY);
                    noiseHeight += perlinValue * amplitude;
                    //Debug.Log(perlinValue);


                    amplitude *= persistance;
                    frequency *= lacunarity;
                }

                if (noiseHeight > maxNoiseHeight) {
                    maxNoiseHeight = (float)noiseHeight;
                }
                else if (noiseHeight < minNoiseHeight) {
                    minNoiseHeight = (float)noiseHeight;
                }
                noiseMap(x, y) = noiseHeight;
            }
        }

        for (int y = 0; y < noiseMap.GetLength(1); y++) {
            for (int x = 0; x < noiseMap.GetLength(0); x++) {
                noiseMap(x, y) = (double)Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, (float)noiseMap(x, y));
            }
        }

(!(enter image description here)(1))(1)
        return noiseMap;
    }

    public static void init(int seed) {
        createGradients(p, seed);
    }

    public static int() createGradients(int() p, int seed) {
        System.Random prng = new System.Random(seed);
        for (int i = 0; i < p.GetLength(0) / 2; i++) {
            p(i) = prng.Next(0, 256);
            p(i + ((int)p.GetLength(0) / 2)) = p(i);
        }

        return p;
    }

    static vector2dDouble generateGradient(int val) {
        int hash = val & 3;
        switch (hash) {
            case 0:
                return new vector2dDouble(1.0, 1.0);
            case 1:
                return new vector2dDouble(-1.0, 1.0);
            case 2:
                return new vector2dDouble(-1.0, -1.0);
            case 3:
                return new vector2dDouble(1.0, -1.0);
            default: return new vector2dDouble(0, 0);
        }
    }

    static double Noise2d(double x, double y) {

        int ix = Convert.ToInt32(Math.Floor(x)) & (p.GetLength(0) / 2 - 1);
        int iy = Convert.ToInt32(Math.Floor(y)) & (p.GetLength(0) / 2 - 1);


        x -= Math.Floor(x);
        y -= Math.Floor(y);

        vector2dDouble v1 = new vector2dDouble(x - 1, y),
                       v2 = new vector2dDouble(x - 1, y - 1),
                       v3 = new vector2dDouble(x, y), 
                       v4 = new vector2dDouble(x, y - 1);

        int g1 = p(p(ix + 1) + iy + 1),
            g2 = p(p(ix) + iy + 1),
            g3 = p(p(ix + 1) + iy), 
            g4 = p(p(ix)  + iy);

        double u = fade(x);
        double v = fade(y);

        double f1 = v1.dot(generateGradient(g1)), 
               f2 = v2.dot(generateGradient(g2)), 
               f3 = v3.dot(generateGradient(g3)), 
               f4 = v4.dot(generateGradient(g4));


        return lerp(u, lerp(v, f2, f4), lerp(v ,f1, f3));
    }

    static double lerp(double t, double argc, double argv) { return argc + t * (argv - argc); }

    static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
}

(System.Serializable)
public struct vector2dDouble {
    public double x, y;

    public vector2dDouble(double argx, double argy) {
        x = argx;
        y = argy;
    }

    public double dot(vector2dDouble argc) {
        argc.x *= x;
        argc.y *= y;

        return argc.x + argc.y;
    }

    public void print() {
        Debug.Log(x + "," + y);
    }
}