0
\$\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\$
  • \$\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 at 4:49
  • \$\begingroup\$ @DMGregory I changed the vector variables a few times.. This is the closest I have gotten it: link \$\endgroup\$ – Braden McPhail Feb 14 at 5:08
0
\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.