I'm making procedural terrain generation for my Unity game, and I want to add octaves to my terrain to make it look more like in the image. How would I go about doing this?
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class MapGenerator : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
public int xSize = 20;
public int zSize = 20;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
void CreateShape()
{
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 = Mathf.PerlinNoise(x * .3f, z * .3f) * 2f;
vertices[i] = new Vector3(x, y, z);
i ;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
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 ;
}
}
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
}
I tried this code below, but it looked more like spikes than a landscape. I would use this tutorial here if I were even able understand it at all.
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 ;
CodePudding user response:
I'm assuming you are implementing this code correctly. It seems like your amplitudes are pretty high. I find that a frequency that doubles each iteration and an amplitude that halves each generation looks nice. The values you choose depend on what kind of terrain you want.
float[] octaveFrequencies=new float() {1,2f,4f,8f} ;
float[] octaveAmplitudes=new float() {1,5f,0.25f,0.125f} ;
Try using these values. These are the settings I commonly use. If you want different-looking terrain, try to change them around a little bit. Changing these values can drastically change the look of the terrain.
Alternatively, you could do this automatically:
const int numOctaves = 4;
float y = 0;
float frequency = 1;
float amplitude = 1;
const float frequencyMult = 2f;
const float amplitudeMult = 0.5f;
for(int i = 0; i < numOctaves; i ) {
y = Mathf.PerlinNoise(x * frequency, z * frequency) * amplitude;
frequency *= frequencyMult;
amplitude *= amplitudeMult;
}
This code does the same thing as before, except you can arbitrarily set the amount of octaves. Increasing the numOctaves increases the detail. Higher frequencyMult increases detail at the cost of smooth terrain, and higher amplitudeMult increases the influence of the detail at the cost of smooth terrain. Change the constants to get a different result. To change the max height, just multiply "y" after this loop. Some variables and syntax might be wrong, because I just typed this up.
If you haven't noticed, the frequency increases exponentially and the amplitude decreases exponentially. If you decrease amplitude linearly, then there might be too much influence on detail, causing large spikes. Also, if you increase frequency linearly, then similar frequencies will add up, causing the same high hills and valleys.