如何随着无限图的增长不断产生Perlin噪声?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何随着无限图的增长不断产生Perlin噪声?相关的知识,希望对你有一定的参考价值。

我正在创建一个二维的,由程序生成的世界。随着播放器移动,我从光盘上加载和卸载块。我正在使用元胞自动机功能来定义每个块中的局部图块的设计方式,但是我需要噪音(在这种情况下为Perlin)来定义每个块在创建新块时的生物群系类型。我了解如何转换0到1之间的小数来表示这一点,我唯一的问题是我遵循的有关创建Perlin噪声的教程要求您将其传递给预定义的2d数组,并返回相同大小的噪声数组。因为我的世界是动态增长的,所以我对如何使用固定大小的数组指定新的块类型感到有些困惑。

我见过的其他答案未完全涵盖如何处理噪声生成的无限部分。我最好的猜测是,我需要以某种方式生成或扩展每个新创建的块的噪声,尽管我这样做的方式使我感到困惑。

这里是一些我从这里翻译成C#的代码:http://devmag.org.za/2009/04/25/perlin-noise/

当然,这里我还不完全了解一些数学,尤其是按位运算!

public class PerlinNoiseGenerator
    {
        public int OctaveCount { get; set; }
        public float Persistence { get; set; }


        public PerlinNoiseGenerator(int octaveCount, float persistence)
        {
            this.OctaveCount = octaveCount;
            this.Persistence = persistence;
        }

        public float[,] GenerateWhiteNoise(int width, int height)
        {
            float[,] noiseFieldToReturn = new float[width, height];
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    noiseFieldToReturn[i, j] = (float)Game1.Utility.RGenerator.NextDouble() % 1;
                }
            }
            return noiseFieldToReturn;
        }

        public float[,] SmoothNoiseField(float[,] whiteNoise, int octave)
        {
            int width = whiteNoise.GetLength(0);
            int height = whiteNoise.GetLength(1);
            float[,] smoothField = new float[width, height];

            int samplePeriod = 1 << octave;

            float sampleFrequency = 1.0f / samplePeriod;

            for(int i =0; i < width; i++)
            {
                int samplei0 = (i / samplePeriod) * samplePeriod;
                int samplei1 = (samplei0 + samplePeriod) % width;

                float horizontalBlend = (i - samplei0) * sampleFrequency;
                for(int j =0; j < height; j++)
                {
                    int samplej0 = (j/samplePeriod) * samplePeriod;
                    int samplej1 = (samplej0 + samplePeriod) % height;
                    float verticalBlend = (j - samplej0) * sampleFrequency;

                    float top = LinearInterpolate(whiteNoise[samplei0, samplej0],
                        whiteNoise[samplei1, samplej0], horizontalBlend);

                    float bottom = LinearInterpolate(whiteNoise[samplei0, samplej1],
                        whiteNoise[samplei1, samplej1], horizontalBlend);

                    smoothField[i, j] = LinearInterpolate(top, bottom, verticalBlend);
                }
            }

            return smoothField;
        }

        public float[,] GeneratePerlinNoise(float[,] baseNoise, int octaveCount)
        {
            int width = baseNoise.GetLength(0);
            int height = baseNoise.GetLength(1);

            float[][,] smoothNoise = new float[octaveCount][,];

            float persistance = .5f;

            for(int i =0; i < octaveCount;i++)
            {
                smoothNoise[i] = SmoothNoiseField(baseNoise, i);
            }
            float[,] perlinNoise = new float[width, height];
            float amplitude = 1f;
            float totalAmplitude = 0.0f;

            for(int octave = octaveCount - 1; octave > 0; octave-- )
            {
                amplitude *= persistance;
                totalAmplitude += amplitude;

                for(int i =0; i < width;i++)
                {
                    for(int j =0; j < height; j++)
                    {
                        perlinNoise[i, j] += smoothNoise[octave][i, j] * amplitude;
                    }
                }
            }

            for(int i =0; i < width; i++)
            {
                for(int j =0; j < height; j++)
                {
                    perlinNoise[i, j] /= totalAmplitude;
                }
            }
            return perlinNoise;
        }

        public float LinearInterpolate(float a, float b, float alpha)
        {
            return a * (1 - alpha) + alpha * b;
        }
    } 

此代码应编译并产生固定大小的噪声数组

答案

您要确保的主要事情是起始随机噪声是伪随机的,因此对于坐标,您始终会有一个“固定随机值”。

可能必须使用坐标作为输入来重写随机噪声生成器。我想您的地图有一个随机的种子数,因此您可以将本文作为起点,添加1个因子:A pseudo-random number generator based on 2 inputs

为您的地图制作带来一些启发,我前一段时间写了这篇文章:https://steemit.com/map/@beeheap/create-a-fantasy-grid-map-in-excel

以上是关于如何随着无限图的增长不断产生Perlin噪声?的主要内容,如果未能解决你的问题,请参考以下文章

Chapter 4 Perlin Noise

Java 中的 Perlin 噪声

ActionScript 3 使用perlin噪声的AS3阈值转换效果

需要分数布朗噪声(FBM)与柏林噪声澄清

未来增长潜力无限

未来增长潜力无限