Search Unity

Question Replacing SplatMaps in TerrainData

Discussion in 'General Graphics' started by Opeth001, Mar 23, 2021.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Hello Everyone,

    I'm trying to make a tool that helps resize terrains without changing their actual details.
    I have successfully modified the terrain splatmaps to fit the new size but I am not able to replace the old splatmaps with the new ones created.

    so how to replace a terrain Splatmap with a texture ?

    Thanks!
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
  3. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yeah, I guess that page doesn't really explain what the values are very well. The Get function does a slightly better job.
    https://docs.unity3d.com/ScriptReference/TerrainData.GetAlphamaps.html

    But that doesn't really tell you the connection between "splat maps" and "alpha maps". By "splat maps" I'm assuming you're actually referring to the splat map control texture(s). The control texture is an RGBA texture that has up to 4 terrain layer densities stored in them. Each channel of a control texture is effectively a single terrain alpha map. I'm not sure exactly which order it's in, but I would expect the R, G, B, and A channels of the first control texture should line up with the 0, 1, 2, and 3 alpha map layer index. For the
    float[,,]
    you need to pass to the
    SetAlphamaps
    function, the z of that value relates to the layer index.

    The x and y of the
    float[,,]
    are the 0.0 to 1.0 range x and y position on the splat map. So to convert from a
    Texture2D
    to the
    float[,,]
    would be something like this:
    Code (csharp):
    1. // might be more than one of these if the terrain has more than 4 layers, and you'll need them all
    2. // but for this example just handling one control texture
    3. Color[] pix = splatTex.GetPixels();
    4.  
    5. // hard coding to 4 in this example
    6. // but really you need to get this from the original terrain's alphamapLayers
    7. int numAlphaLayers = 4;
    8.  
    9. float[,,] alphaMaps = new float[splatTex,width, splatTex.height, numLayers];
    10. for (int x=0; x<splatTex.width; x++)
    11. {
    12.   float xNorm = x / float(splatTex.width - 1);
    13.   for (int y=0; y<splatTex.height; y++)
    14.   {
    15.     float yNorm = y / float(splatTex.height - 1);
    16.  
    17.     Vector4 pixColor = pix[x + y * splatTex.width];
    18.     for (int i=0; i<numAlphaLayers; i++)
    19.       alphaMaps[xNorm, yNorm, pixColor[i]);
    20.   }
    21. }
    22.  
    23. terrainData.SetAlphamaps(alphaMaps);
     
    Opeth001 likes this.
  5. Sobe459

    Sobe459

    Joined:
    Aug 28, 2012
    Posts:
    27
    Sorry for the old Reply But this is exactly what ive been trying to do. I got it working no problem. Im having trouble with hoow to set up the pixels for multiple splat maps(RGBA Pngs).. Can anyone help? Thanks! Heres my Load Function:

    Code (CSharp):
    1. IEnumerator LoadSplats()
    2.         {
    3.             Debug.Log("Load Terrain");
    4.          
    5.             var dirPath = dir + "/../TerrainImages/";
    6.             TerrainData terrainData = myTerrain.terrainData;
    7.             int alphaMapsCount = terrainData.alphamapTextureCount;
    8.             var w2 = terrainData.alphamapWidth;
    9.  
    10.             List<Texture2D> splatMaps = new List<Texture2D>();
    11.             List<Color> pix;
    12.          
    13.             for (int a = 0; a < alphaMapsCount; a++)
    14.             {
    15.                 string path = dirPath + "SplatAlpha " + a + ".txt";
    16.                 StreamReader reader = new StreamReader(path);
    17.                 string newLoadString = reader.ReadToEnd().ToString();
    18.  
    19.                 Texture2D tex = new Texture2D(w2,w2);
    20.              
    21.              
    22.                 byte[] b64_bytes = System.Convert.FromBase64String(newLoadString);
    23.              
    24.                 tex.LoadImage(b64_bytes);
    25.  
    26.                 splatMaps.Add(tex);
    27.             }
    28.  
    29.             pix = splatMaps[0].GetPixels().ToList();
    30.          
    31.             float[,,] alphamapData = new float[w2, w2, terrainData.terrainLayers.Length];
    32.          
    33.             for (int y=0; y<w2; y++)
    34.             {
    35.                 for (int x=0; x<w2; x++)
    36.                 {
    37.                     Vector4 pixColor = pix[x + y * w2];
    38.  
    39.                     for (int i = 0; i < 4; i++)
    40.                     {
    41.                         alphamapData[y, x, i] = pixColor[i];
    42.                     }
    43.                      
    44.                 }
    45.             }
    46.             terrainData.SetAlphamaps(0, 0, alphamapData);
    47.  
    48.             yield return null;
    49.         }
     
  6. brandonjames444

    brandonjames444

    Joined:
    Aug 28, 2019
    Posts:
    2
    Thank you!!!!