1
\$\begingroup\$

I am quite new to the wondrous world of "Procedural Textures", and I am trying to create a double precission perlin noise algorithm.

Noise

I am almost done with it except for the fact that the coordinates seem to be off, any idea what I've done wrong? Here's 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);
    }
}

\$\endgroup\$
3
  • \$\begingroup\$ It looks to me like your v and g variables don't agree with one another. g1 is the gradient for the corner (ix+1, iy+1), but you're dotting it with the vector from (ix + 1, iy) \$\endgroup\$
    – DMGregory
    Feb 14 '20 at 4:49
  • \$\begingroup\$ @DMGregory I changed the vector variables a few times.. This is the closest I have gotten it: link \$\endgroup\$ Feb 14 '20 at 5:08
  • \$\begingroup\$ A good first question! Can’t believe my eyes \$\endgroup\$ Jul 13 '20 at 6:47
1
\$\begingroup\$

Found The answer! My linear interpolation values were just flipped and when I flipped them back, instead of being inverted and creating layers, it was reverted to its normal state. Code Changed:


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

// To: 


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

// Also my v and g vectors were unaligned

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .