5

I am trying to get along with procedural generation, I definitely not a pro in unity, however I was following this guide: click and got some results. For now I have 2 problems, I have some basic idea how to resolve them, however I would like to hear some other opinions.

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

The main issue is : gaps between chunks:

enter image description here

they kinda disappear if I will zoom, however textures remain unfit and it is remarkable.

The second, as you can see I have a problem with red (I don't really know how to call it) marks on the ground. I have tried to use material from guide, but got same effect.

Besides, Perlin Noise ( I know that I can use Diamond square or simplex) is pseudo-random algorithm, so it will return the same values for the same input parameters, so does it mean that my chunks will always be the same?

My code ( I am using LibNoise library from guide):

    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;
    }
}
user7803907
  • 301
  • 3
  • 11
  • 1
    Can you make it more clear what your question is? I see three possible questions in your post (1. gaps, 2. red marks, and 3. Perlin Noise values). Generally, you should try to ask only one thing in a question on Stack Overflow, but exceptions can be made if the questions are very closely related. Also, you can make it more clear that something is a question if you end it with a question mark. – PJvG Apr 04 '17 at 09:30
  • 1
    About the Perlin noise, you can see in [the LibNoise library on GitHub](https://github.com/ricardojmendez/LibNoise.Unity/blob/master/Generator/Perlin.cs) that it has a `Seed` property. If you want different results, you should use a different seed for your `Perlin` object. Perhaps do some more research on pseudorandom generators and seeds if you're still confused. – PJvG Apr 04 '17 at 09:36
  • 1
    @PjvG i know about 1 question per post (common rule on forums), however i don't really think that i should separate them. So, i will try to clarify my self, the main question is about gaps, there is some common (must do this way) solution? I have asked about marks just in case if someone had the same problem, i am pretty sure i just did something wrong in shading options. – user7803907 Apr 04 '17 at 11:59

2 Answers2

4

1) The main issue is : gaps between chunks

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

From the documentation:

Lets you setup the connection between neighboring Terrains.

This ensures LOD matches up on neighboring terrains. Note that it is not enough to call this function on one Terrain, you need to set the neighbors of each terrain.

2) The second: red marks on the ground

This problem should come from the textures you are using in your terrain object.

Ludovic Feltz
  • 11,416
  • 4
  • 47
  • 63
  • Do you have any ideas, what kind of a problem with textures can be? (For me it really looks like some "metallic" effect from the material.) – user7803907 Apr 06 '17 at 06:20
  • Regarding your texture artefacts, are you running a DX10 or lower GPU? Check out this https://answers.unity.com/questions/1300325/reflection-artifacts-on-standard-shader.html for a possible solution, it's in the update – stalem May 06 '18 at 15:12
2

The gaps happen because you're creating different terrain objects. The main point of using terrains is to have a procedural piece of mesh you can optimize as you see fit.

The engine optimizes terrains by decreasing their LOD the farther you are from them. This means that two neighboring chunks may get two different LODs, effectively meaning one has half the vertex resolution of the other, which causes the gaps. You'll notice how they seem to happen with every other vertex if you pay close attention. It also seems to disappear up-close because you don't get any LODs up-close.

The way the engine solves this is by stitching the extra vertex to the lower-resolution part of the terrain. It can't do this in your case, however, because there are separate terrain objects and they're unaware of each other's existence. What you probably want to do to solve the problem is to merge all the smaller terrain objects into one big terrain.

Arshia001
  • 1,854
  • 14
  • 19
  • 1
    The original project (from the guide) had something about this. In the guide project chunks contain (as far as i remember) references on 4 closest chunks (up, bottom, left and right). I ll try to look again a bit closely this evening, however i think my question is answered. Btw, do you have any ideas how to fix those red marks (they are really annoying)? – user7803907 Apr 05 '17 at 07:15