繁体   English   中英

如何为“ perlin”噪声发生器添加比例因子?

[英]How can I add scaling factors to my “perlin” noise generator?

我有一个Perlin噪声发生器,正在尝试使用它来创建滚动地形。

我有一个中心地形,围绕它的同一侧有八个地形(它们工作正常),第二个地形环是它的三倍。 对于这些,我需要我的噪声发生器来输出三倍于“密集器”的噪声,这样我就可以在较小的地形上放置较大的地形,并且除了三倍大的图块(和地图尺寸)外,它们都可以匹配。

我不想只是生成一张更大的地图; 很快就会变得令人望而却步。

我不知道该怎么办; 显而易见的解决方案都以一种或另一种方式失败了。

    /// <summary>
    /// Generates a new perlin map.
    /// </summary>
    /// <param name="xStart">The left coordinate (using 0, 0 as top-left and +, + as down and to the right).</param>
    /// <param name="yStart">The top coordinate (using 0, 0 as top-left and +, + as down and to the right).</param>
    /// <param name="width">The width of the map.</param>
    /// <param name="length">The length of the map.</param>
    /// <param name="persistance">If set, values lower than 1 make the map less noisey; values greater than 1 make the map more noisy.</param>
    /// <param name="fromShift">Low values here provide for a broader "base".</param>
    /// <param name="toShift">High values here provide for more speckled "highlights".</param>
    /// <param name="interpolate">If set to false, the algorithm will not smooth values.</param>
    public double[,] Generate(
        int xStart, int yStart,
        int width, int length,
        double? persistance,
        uint fromShift, uint toShift,
        bool interpolate = true,
    )
    {
        _noiseMap = new double[width, length];
        _workingMap = new double[width + 6, length + 6];
        _smoothedNoise = new double[width + 6, length + 6];
        int ifromShift = -(int)(toShift),
            itoShift = -(int)(fromShift);
        int idiv = 1 + (itoShift - ifromShift);
        double ddiv = 0;
        double amplitude = 0.0;
        if (persistance.HasValue)
            for (int i = ifromShift; i <= itoShift; ++i)
                ddiv += Math.Pow(persistance.Value, i);

        for (int i = ifromShift; i <= itoShift; ++i)
        {
            _frequency = Math.Pow(2, i);
            if (persistance.HasValue) amplitude = Math.Pow(persistance.Value, i);
            int useWidth = (int)(width * _frequency) + 1,
                useLength = (int)(length * _frequency) + 1;
            int useXStart = (int)(xStart * _frequency),
                useYStart = (int)(yStart * _frequency);
            double frequencyXStart = xStart * _frequency - useXStart,
                frequencyYStart = yStart * _frequency - useYStart;

            for (int y = 0; y < useLength + 5; ++y)
                for (int x = 0; x < useWidth + 5; ++x)
                {
                    int genX = ((int)(useXStart) + (int)((x) + 0.5));
                    int genY = ((int)(useYStart) + (int)((y) + 0.5));
                    _workingMap[x, y] = GenerateNoise(genX, genY);
                }

            if (interpolate)
            {
                for (int y = 1; y < length + 4; ++y)
                    for (int x = 1; x < width + 4; ++x)
                    {
                        _smoothedNoise[x, y] = SmoothedNoise(x, y);
                    }

                if (persistance.HasValue)
                    for (int y = 0; y < length; ++y)
                        for (int x = 0; x < width; ++x)
                        {
                            _noiseMap[x, y] += InterpolatedNoise((x * _frequency) + 2 + frequencyXStart, (y * _frequency) + 2 + frequencyYStart) * amplitude;
                            // _noiseMap[x, y] += _workingMap[x, y] * amplitude;
                        }
                else
                    for (int y = 0; y < length; ++y)
                        for (int x = 0; x < width; ++x)
                        {
                            _noiseMap[x, y] += InterpolatedNoise((x * _frequency) + 2 + frequencyXStart, (y * _frequency) + 2 + frequencyYStart) / idiv;
                            // _noiseMap[x, y] += _workingMap[x, y] / idiv;
                        }
            }
            else
                if (persistance.HasValue)
                    for (int y = 0; y < length; ++y)
                        for (int x = 0; x < width; ++x)
                        {
                            _noiseMap[x, y] +=
                                _workingMap[(int)((x * _frequency) + 2 + frequencyXStart), (int)((y * _frequency) + 2 + frequencyYStart)] * amplitude;
                        }
                else
                    for (int y = 0; y < length; ++y)
                        for (int x = 0; x < width; ++x)
                        {
                            _noiseMap[x, y] +=
                                _workingMap[(int)((x * _frequency) + 2 + frequencyXStart), (int)((y * _frequency) + 2 + frequencyYStart)] / idiv;
                        }
        }

        if (persistance.HasValue)
            for (int y = 0; y < length; ++y)
                for (int x = 0; x < width; ++x)
                {
                    _noiseMap[x, y] = _noiseMap[x, y] / ddiv;
                }

        return _noiseMap;
    }

谢谢。

Perlin噪声比您的样本要密集得多,因此一个算法的形状对于所有网格都是密集的。 如果需要更多细节,则必须添加八度或第二遍噪声,在这种情况下,网格将无法正确覆盖。 因此,选择一个形状并以不同的网格密度对其进行采样是一个问题。

只是要清楚(检查我对您的问题的理解)。

您生成的地图A的边尺寸为X。此地图被另外九个地图B1 ... B9包围,每个地图的边尺寸为X。现在,您想要的地图C1 ... C2将围绕地图B1...。从外面B9。 这些地图中的每个地图的边长均为3X,但只有X ^ 2个数据点(每个数据点的大小为3x3)。

对?

您是否尝试过使用最近邻居算法对数据进行插值? 当任何代码要求从坐标X获得数据时,只需将坐标四舍五入为3的倍数并使用它即可。 我认为这应该有效。

另一种选择是使用中点位移算法 ,除了您将图块分成三个部分,而不是在每个递归步骤中将其分成两个部分。 这样一来,您可以提前停一轮,从而向您展示所需的结果:高度图,仅在3x3网格的交点上生成数据点。 无需触摸其余点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM