Unity-佩林噪声八度

时间:2019-05-05 09:00:31

标签: c# visual-studio unity3d perlin-noise

在下面的教程中,我试图统一设置简单的Terrain Generator,到目前为止,它可以按预期工作,但是我想做得更“自然”,并发现我需要做Octaves或MultiLevel噪声。

我在网上发现的有关多级Perlin噪声的所有信息,对我来说都是无法理解的,或者使用了完全不同的方法。

using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
public class Mesh_Generator : MonoBehaviour
{

    #region Variables
    Mesh mesh;

    Vector3[] vertices;
    //Vector2[] Uvs;
    Color[] colors;
    int[] triangles;

    [Range(1, 9999)]
    public int xSize = 100;
    [Range(1, 9999)]
    public int zSize = 100;

    public Gradient gradient;

    public float MinHeight = 0;
    public float MaxHeight = 0;

    public bool Reset_Min_Max;
    #endregion
    #region Octaves
    [Range(1, 6)]
    public int Octaves = 6;
    public int Scale = 50;

    public float offsetX = 0f;
    public float offsetY = 0f;

    public float Frequency_01 = 5f;
    public float FreqAmp_01 = 3f;

    public float Frequency_02 = 6f;
    public float FreqAmp_02 = 2.5f;

    public float Frequency_03 = 3f;
    public float FreqAmp_03 = 1.5f;

    public float Frequency_04 = 2.5f;
    public float FreqAmp_04 = 1f;

    public float Frequency_05 = 2f;
    public float FreqAmp_05 = .7f;

    public float Frequency_06 = 1f;
    public float FreqAmp_06 = .5f;
    #endregion
    #region Start
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        offsetX = Random.Range(0f, 99999f);
        offsetY = Random.Range(0f, 99999f);
    }
    #endregion
void ResetMinMax()
{
    MinHeight = 0f;
    MaxHeight = 0f;
        Reset_Min_Max = false;
}
#region Update
private void Update()
    {
        if (Reset_Min_Max)
            ResetMinMax();

        CreateShape();
        UpdateMesh();
    }
    #endregion
    #region CreateShape
    void CreateShape()
    {
        #region Vertices
        vertices = new Vector3[(xSize + 1) * (zSize + 1)];

        for (int i = 0, z = 0; z <= zSize; z++)
        {
            for (int x = 0; x <= xSize; x++)
            {
                float y = Calculate(x, z);
                vertices[i] = new Vector3(x, y, z);

                if (y > MaxHeight)
                    MaxHeight = y;
                if (y < MinHeight)
                    MinHeight = y;

                i++;
            }
        }

        int vert = 0;
        int tris = 0;
        #endregion
        #region Triangles
        triangles = new int[xSize * zSize * 6];

        for (int z = 0; z < zSize; z++)
        {
            for (int x = 0; x < xSize; x++)
            {
                triangles[tris + 0] = vert + 0;
                triangles[tris + 1] = vert + xSize + 1;
                triangles[tris + 2] = vert + 1;
                triangles[tris + 3] = vert + 1;
                triangles[tris + 4] = vert + xSize + 1;
                triangles[tris + 5] = vert + xSize + 2;

                vert++;
                tris += 6;
            }
            vert++;
        }
        #endregion
        #region Gradient Color
        colors = new Color[vertices.Length];
        for (int i = 0, z = 0; z <= zSize; z++)
        {
            for (int x = 0; x <= xSize; x++)
            {
                float Height = Mathf.InverseLerp(MinHeight, MaxHeight, vertices[i].y);
                colors[i] = gradient.Evaluate(Height);
                i++;
            }
        }
        #endregion
        #region UVs
        /*
         Uvs = new Vector2[vertices.Length];
         for (int i = 0, z = 0; z <= zSize; z++)
         {
             for (int x = 0; x <= xSize; x++)
             {
                 Uvs[i] = new Vector2((float)x / xSize, (float)z / zSize);
                 i++;
             }
         }
         */
        #endregion
    }
    #endregion
    #region Octaves Calculation
    float Calculate(float x, float z)
    {
        float[] octaveFrequencies = new float[] { Frequency_01, Frequency_02, Frequency_03, Frequency_04, Frequency_05, Frequency_06 };
        float[] octaveAmplitudes = new float[] { FreqAmp_01, FreqAmp_02, FreqAmp_03, FreqAmp_04, FreqAmp_05, FreqAmp_06 };
        float y = 0;

        for (int i = 0; i < Octaves; i++)
        {
            y += octaveAmplitudes[i] * Mathf.PerlinNoise(
                     octaveFrequencies[i] * x + offsetX * Scale,
                     octaveFrequencies[i] * z + offsetY * Scale) ;

        }

        return y;
    }
    #endregion
    #region UpdateMesh
    void UpdateMesh()
    {
        mesh.Clear();

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.colors = colors;
        //mesh.uv = Uvs;

        mesh.RecalculateNormals();

    }
    #endregion
    #region  Gizmos
    /* 
     private void OnDrawGizmos()
    {
        if (vertices == null)
            return;

        for (int i = 0; i < vertices.Length; i++){
            Gizmos.DrawSphere(vertices[i], .1f);
        }           
    }
    */
    #endregion
}

下面的链接中是我当前的结果以及我正在尝试实现的结果。

https://imgur.com/a/m9B6ga4

使用这种方法是否有可能获得这种结果? 如果可以的话,可以显示脚本示例吗?

非常感谢您。

*再次更新代码

1 个答案:

答案 0 :(得分:1)

多级或多倍频程perlin只是将标准perlin加在一起的几次迭代。 示例代码如下所示:

float[] octaveFrequencies=new float() {1,1.5f,2,2.5f} ;
float[] octaveAmplitudes=new float() {1,0.9f,0.7f,0.f} ;
float y=0;
for(int i=0;i<octaveFrequencies.Length;i++)
 y += octaveAmplitudes[i]* Mathf.PerlinNoise(
      octaveFrequencies[i]*x + .3f, 
      octaveFrequencies[i]* z + .3f) * 2f ;

您放入数组中的数字将决定噪声的最终形状。频率数组中的值乘以您的输入,幅度数组中的值乘以该层上得到的贝林。