如何向我的“perlin”视图添加缩放因子噪音发生器?

发布于 2024-10-23 13:44:30 字数 5080 浏览 4 评论 0原文

我有一个柏林噪声发生器,我试图用它来创建滚动地形。

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

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

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

    /// <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;
    }

谢谢。

I have a Perlin noise generator which I am attempting to use to create scrolling terrain.

I've got a center terrain, eight terrains of the same side surrounding it (these are working fine) and a second ring of terrains which are three times larger. For these, I need my noise generator to output noise that is three times "denser", such that I could place a larger terrain over a smaller terrain and, except for the three times larger tiles (and map size), they'd match.

I don't want to just generate a larger map; that would quickly get prohibitive.

I do not know what to do; the obvious solutions all failed, one way or another.

    /// <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;
    }

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为人所爱 2024-10-30 13:44:30

只是为了清楚(检查我对你的问题的理解)。

您生成边长为 X 的地图 A。
该地图周围还有九张地图 B1.​​..B9,每张地图的边长为 X。
现在您需要地图 C1...C2,它将从外部包围地图 B1.​​..B9。这些地图中的每一个都有大小为 3X 的边,但只有 X^2 个数据点(每个数据点的大小为 3x3)。

正确的?

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

另一种选择是使用中点位移算法,除非您将图块分成三个每个递归步骤中只有两个部分而不是两个部分。这将允许您提前停止一轮,这将向您呈现您正在寻找的结果:仅在 3x3 网格的交点上生成数据点的高度图。无需触及其余点。

Just to be clear (to check my understanding of your problem).

You generate a map A with side of size X.
This map is surrounded by nine more maps B1...B9, each with side of size X.
Now you want maps C1...C2, which will surround maps B1...B9 from the outside. Each of these maps will have a side of size 3X, but with only X^2 data points (each data point will be of size 3x3).

Right?

Have you tried just interpolating the data with nearest neighbor algorithm? When any code asks for a data from coordinate X, just round the coordinate to a multiple of three and use it. I think this should work.

Another option would be to use the midpoint displacement algorithm, except you would split the tile into three parts instead of just two in each recursive step. This would allow you to stop one round early, which would present you with the result you are looking for: A height map with data points generated only on intersection points of 3x3 grid. Without ever having to touch the remaining points.

瞎闹 2024-10-30 13:44:30

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

Perlin noise is alot more dense than your samples can be, so the shape of one algorythm is dense for all grids. if you want extra detail, you have to add an octave or a second pass of noise, in which case the grids wouldnt overlay properly. so it's a question of choosing a shape and sampling it with different grid densities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文