Procedural landscape programming in Unity 3D

I try to get along with the process generation, I am definitely not a professional in unity, however I followed this guide: click and got some results. At the moment, I have two problems, I have a basic idea of ​​how to solve them, but I would like to hear some other opinions.

(I already posted this question in Unity answers, however I don't have an answer at all, if there is some missing information, or it is impossible to explain in a few words, please let me know or give advice on how to find this information)

Main problem: spaces between pieces:

enter image description here

they seem to disappear if I zoom in, but the textures remain unusable, and that's great.

Secondly, as you can see, I have a problem with red (I don’t know what to call it) on the ground. I tried using the material from the manual, but got the same effect.

Also, Perlin Noise (I know that I can use Diamond or Simplex) is a pseudo-random algorithm, so it will return the same values ​​for the same input parameters, so that means my pieces will always be the same

My code (I use the LibNoise library from the manual):

void Awake() { var settings = new TerrainChunkSettings(129, 129, 100, 40, FlatTexture, SteepTexture, TerrainMaterial); var noiseProvider = new NoiseProvider(); for (var i = 0; i < 4; i++) for (var j = 0; j < 4; j++) new TerrainChunk(settings, noiseProvider, i, j).CreateTerrain(); } public class TerrainChunkSettings { public int HeightmapResolution { get; private set; } public int AlphamapResolution { get; private set; } public int Length { get; private set; } public int Height { get; private set; } public Texture2D FlatTexture { get; private set; } public Texture2D SteepTexture { get; private set; } public Material TerrainMaterial { get; private set; } public TerrainChunkSettings(int heightmapResolution, int alphamapResolution, int length, int height, Texture2D flatTexture, Texture2D steepTexture, Material terrainMaterial) { HeightmapResolution = heightmapResolution; AlphamapResolution = alphamapResolution; Length = length; Height = height; FlatTexture = flatTexture; SteepTexture = steepTexture; TerrainMaterial = terrainMaterial; } } public class TerrainChunk { private Terrain Terrain { get; set; } private TerrainChunkSettings Settings { get; set; } private NoiseProvider NoiseProvider { get; set; } public int X { get; private set; } public int Z { get; private set; } private TerrainData Data { get; set; } private float[,] Heightmap { get; set; } public TerrainChunk(TerrainChunkSettings settings, NoiseProvider noiseProvider, int x, int z) { X = x; Z = z; Settings = settings; NoiseProvider = noiseProvider; } public void CreateTerrain() { var terrainData = new TerrainData(); terrainData.heightmapResolution = Settings.HeightmapResolution; terrainData.alphamapResolution = Settings.AlphamapResolution; var heightmap = GetHeightmap(); terrainData.SetHeights(0, 0, heightmap); ApplyTextures(terrainData); terrainData.size = new Vector3(Settings.Length, Settings.Height, Settings.Length); var newTerrainGameObject = Terrain.CreateTerrainGameObject(terrainData); newTerrainGameObject.transform.position = new Vector3(X * Settings.Length, 0, Z * Settings.Length); Terrain = newTerrainGameObject.GetComponent<Terrain>(); Terrain.Flush(); } private float[,] GetHeightmap() { var heightmap = new float[Settings.HeightmapResolution, Settings.HeightmapResolution]; for (var zRes = 0; zRes < Settings.HeightmapResolution; zRes++) { for (var xRes = 0; xRes < Settings.HeightmapResolution; xRes++) { var xCoordinate = X + (float)xRes / (Settings.HeightmapResolution - 1); var zCoordinate = Z + (float)zRes / (Settings.HeightmapResolution - 1); heightmap[zRes, xRes] = NoiseProvider.GetValue(xCoordinate, zCoordinate); } } return heightmap; } private void ApplyTextures(TerrainData terrainData) { var flatSplat = new SplatPrototype(); var steepSplat = new SplatPrototype(); flatSplat.texture = Settings.FlatTexture; steepSplat.texture = Settings.SteepTexture; terrainData.splatPrototypes = new SplatPrototype[] { flatSplat, steepSplat }; terrainData.RefreshPrototypes(); var splatMap = new float[terrainData.alphamapResolution, terrainData.alphamapResolution, 2]; for (var zRes = 0; zRes < terrainData.alphamapHeight; zRes++) { for (var xRes = 0; xRes < terrainData.alphamapWidth; xRes++) { var normalizedX = (float)xRes / (terrainData.alphamapWidth - 1); var normalizedZ = (float)zRes / (terrainData.alphamapHeight - 1); var steepness = terrainData.GetSteepness(normalizedX, normalizedZ); var steepnessNormalized = Mathf.Clamp(steepness / 1.5f, 0, 1f); splatMap[zRes, xRes, 0] = 1f - steepnessNormalized; splatMap[zRes, xRes, 1] = steepnessNormalized; } } terrainData.SetAlphamaps(0, 0, splatMap); } } public interface INoiseProvider { float GetValue(float x, float z); } public class NoiseProvider : INoiseProvider { private Perlin PerlinNoiseGenerator; public NoiseProvider() { PerlinNoiseGenerator = new Perlin(); } public float GetValue(float x, float z) { return (float)(PerlinNoiseGenerator.GetValue(x, 0, z) / 2f) + 0.5f; } } 
+5
source share
2 answers

1) Main problem: spaces between pieces

You can stitch the terrain together to provide the same LOD with SetNeighbors(Terrain left, Terrain top, Terrain right, Terrain bottom);

From the documentation:

Allows you to configure the connection between neighboring Terrains.

This ensures LOD compliance in adjacent sections. Please note that this is not enough to call this function on one landscape, you need to set the neighbors of each landscape.

2) Second: red marks on the ground

This problem should come from the textures you use in your landscape object.

+2
source

Gaps are due to the fact that you create different objects of the landscape. The main point of using landscapes is to have a procedural piece of mesh that you can optimize as you wish.

The engine optimizes landscapes by reducing their LOD, the farther you are from them. This means that two adjacent pieces can get two different LODs, which means that one has half the vertex resolution of the other, which leads to a break. You will notice how they seem to happen to every other vertex if you pay close attention. It also seems to disappear up-close because you are not getting any LODs-up-close.

The way this engine moves is to stitch an extra vertex into the relief area with a lower resolution. However, this cannot be done in your case, because there are separate objects of the landscape, and they do not know about the existence of each other. What you probably want to do to solve the problem is to combine all the objects of a smaller area into one large landscape.

+2
source

Source: https://habr.com/ru/post/1266295/


All Articles