I'am trying to setup simple Terrain Generator in unity following tutorial, so far it works as intended, but i wanted to do more "natural" look and found out that i need to do Octaves or MultiLevel noise.
Everything i found online regarding Multilevel Perlin noise, was not understandable for me or used completly different methode.
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
}
In link below is my current result and result which i'am trying to achieve.
https://i.sstatic.net/FFMLQ.jpg
is it possible to achieve such result using this method ? if so would be possible to show script example ?
Thank you a lot.
*updated code again
multi level, or multi octave perlin is just few iterations of standard perlin added together. An example code could look like this:
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 ;
The numbers you put into arrays will decide the final shape of the noise. Values from the frequencies array are multiplied by your input, values from the amplitudes array are multiplied by the resulting perlin at that layer.