【问题标题】:Perlin Noise Assistance柏林噪音援助
【发布时间】:2012-03-02 21:00:14
【问题描述】:

好的,所以我找到了this 文章,我对它的某些部分感到困惑。如果有人能更深入地向我解释这个过程,我将不胜感激,因为我已经尝试编写这个代码 2 个月了,但仍然没有得到一个正确的版本。我对文章的持久性部分特别感到困惑,因为我大多不明白作者试图解释什么,在文章的底部他谈到了这个的 2D 伪代码实现,但是 PerlinNoise_2D 函数没有对我来说有意义,因为在随机值经过平滑和插值之后,它是一个整数值,但函数采用浮点值?在余音部分下面是八度音阶部分。我不太明白,因为他将平滑函数“添加”在一起以获得 Perlin 函数。他所说的“添加”是什么意思,因为您显然没有将这些值相加。因此,如果有人可以向我解释这些部分,我将非常高兴。谢谢。

这是我的代码:

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class TerrainGen extends JPanel {

public static int layers = 3;
public static float[][][][] noise = new float[16][16][81][layers];
public static int[][][][] octaves = new int[16][16][81][layers];
public static int[][][][] perlin = new int[16][16][81][layers];
public static int[][][] perlinnoise = new int[16][16][81];
public static int SmoothAmount = 3;
public static int interpolate1 = 0;
public static int interpolate2 = 10;
public static double persistence = 0.25;

//generate noise
//smooth noise
//interpolate noise
//perlin equation

public TerrainGen() {
    for(int t = 0; t < layers; t++) {
        for(int z = 0; z < 81; z++) {
            for(int y = 0; y < 16; y++) {
                for(int x = 0; x < 16; x++) {
                    noise[x][y][z][t] = GenerateNoise();
                }
            }
        }
    }

    for(int t = 0; t < layers; t++) {
        SmoothNoise(t);
    }

    for(int t = 0; t < layers; t++) {
        for(int z = 0; z < 81; z++) {
            for(int y = 0; y < 16; y++) {
                for(int x = 0; x < 16; x++) {
                    octaves[x][y][z][t] = InterpolateNoise(interpolate1, interpolate2, noise[x][y][z][t]);
                }
            }
        }
    }

    for(int t = 0; t < layers; t++) {
        PerlinNoise(t);
    }
}

public static Random generation = new Random(5);
public float GenerateNoise() {
    float i = generation.nextFloat();
    return i;
}

public void SmoothNoise(int t) {
    //Huge smoothing algorithm
}

//Cosine interpolation
public int InterpolateNoise(int base, int top, float input) {
    return (int) ((1 - ((1 - Math.cos(input * 3.1415927)) * 0.5)) + top * ((1 - Math.cos(input * 3.1415927)) * 0.5));
}

public void PerlinNoise(int t) {
    double f = Math.pow(2.0, new Double(t));
    double a = Math.pow(persistence, new Double(t));
    for(int z = 0; z < 81; z++) {
        for(int y = 0; y < 16; y++) {
            for(int x = 0; x < 16; x++) {
                perlin[x][y][z][t] = (int) ((octaves[x][y][z][t] * f) * a);
            }
        }
    }
}

public static void main(String [] args) {
    JFrame frame = new JFrame();
    frame.setSize(180, 180);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    TerrainGen test = new TerrainGen();
    frame.add(test);
    frame.setVisible(true);
}

public static int size = 5;
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    int i = 0;
    for(int t = 0; t < 9; t++) {
        for(int z = 0; z < 9; z++) {
            for(int y = 0; y < 16; y++) {
                for(int x = 0; x < 16; x++) {
                    g.setColor(new Color(perlin[x][y][i][0] * 10, perlin[x][y][i][0] * 10, perlin[x][y][i][0] * 10));
                    g.fillRect((z * (16 * size)) + (x * size), (t * (16 * size)) + (y * size), size, size);
                }
            }
            i++;
        }
    }
    repaint();
}
}

我没有包括平滑部分,因为那是大约 400 行代码来在块之间进行平滑。

【问题讨论】:

  • 你真的是医生教授吗?
  • .....感谢您的帮助...哈哈哈

标签: 2d interpolation smooth noise perlin-noise


【解决方案1】:

本文所说的持久性是指高频噪声的幅度在它们组合时如何“衰减”。

“八度”就是文章所说的不同频率的噪声函数。

您取 1.0 并反复乘以持久性,以获得将每个八度音阶乘以的幅度列表 - 例如0.8 的持久性给出因子 1.0、0.8、0.64、0.512。

噪声不是整数,他的函数 Noise1 会产生 0..1 范围内的噪声 - 即变量 n 是一个 Int32 位,它返回一个浮点数。

输入参数是整数,即 Noise1 函数仅在 (1, 0) 或 (2, 2) 处评估。 在 SmoothNoise_1 中对噪声进行一点平滑/涂抹后,值会被插值以产生介于两者之间的值。

希望有所帮助!

【讨论】:

  • 而频率每次都只是乘以2?
  • 是的,但如果你使用其他因素来提高频率,我可能没关系。
  • 好的,谢谢,还有 1 或 2 个问题... 这个过程按什么顺序进行?生成噪声、平滑、插值,然后使用 perlin 方程或其他方法?
  • 那我做对了那部分,但代码仍然没有产生任何接近噪声应该看起来的东西......我认为它是柏林噪声方程本身。哈哈哈你能解释一下最后一件事,文章中用伪代码编写的perlin噪声方程。我不明白 x 和 y 需要什么值以及为什么需要它们,因为“总 = 总 + 插值噪声(x * 频率,y * 频率)* 幅度”这行让我很困惑
  • 尝试使用 0..1 作为范围 - 它的哪一部分让您感到困惑?
【解决方案2】:

这个循环从二维噪声产生八度音阶。相同的循环适用于 3d perlin...

   function octaves( vtx: Vector3 ): float
    {
        var total = 0.0;    
        for (var i:int = 1; i < 7; i ++)//num octaves
        {
            total+= PerlinNoise(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
        }

        return total;//added multiple perlins into noise with 1/2/4/8 etc ratios

    }

我在学习 perlin 方面看到的最好的事情是以下代码。它使用基于 sin 的半随机函数而不是哈希表。使用 2-3 个八度音程,它变成了高质量的 perlin……令人惊奇的是,我在实时景观上运行了 30 个八度音程,它并没有减速,而我使用 1 voronoi 一次,它正在减速。所以...令人惊叹的代码值得学习。

#ifndef __noise_hlsl_
#define __noise_hlsl_

// hash based 3d value noise
// function taken from https://www.shadertoy.com/view/XslGRr
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// ported from GLSL to HLSL

float hash( float n )
{
    return frac(sin(n)*43758.5453);
}

float noise( float3 x )
{
    // The noise function returns a value in the range -1.0f -> 1.0f

    float3 p = floor(x);
    float3 f = frac(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
                   lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
               lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
                   lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

请注意,sin 在 CPU 上的开销很大,您可以使用:

function hash ( n: float ): float
{//random -1, 1
    var e = ( n *73.9543)%1;
    return  (e*e*142.05432)%2-1;// fast cpu random by me :) uses e*e rather than sin
}

【讨论】:

    猜你喜欢
    • 2012-12-21
    • 2012-06-25
    • 2012-07-22
    • 2011-11-22
    • 2023-03-04
    • 1970-01-01
    • 2013-07-17
    • 2021-04-29
    • 2012-01-29
    相关资源
    最近更新 更多