Have Texture2Ds want alphamaps.

If I call terrainData.GetAlphamapTexture() I get a Texture2D. How would I then load that back into terrainData? SetAlphamaps requires a float[,].

Ok, figured it out. I was specifically having a problem with the CTS splat maps being in a texture on the material’s shader. (Or in the CTS component.) This will pull those splat maps and write them to the terrain data. Geez, took me 6 hours… :slight_smile: At least it’s done.

        private void DoExport()
        {
#if UNITY_EDITOR
            var sceneName = SceneManager.GetActiveScene().name;
            var timeText = DateTime.Now.ToString("HHmmss");
            var path = "Assets/Scenes/" + sceneName + "/TerrainData-" + timeText + ".asset";
            Debug.Log("Saving to: " + path);

            var terrain = GetComponent<Terrain>();
            var terrainData = terrain.terrainData;

            // Write the CTS splat map to the terrainData!
            var splats = GenerateCtsAlphamap(terrainData);

            UnityEditor.AssetDatabase.CreateAsset(terrainData, path);

            // It is necessary to re-set and save. Unity issue?
            terrainData.SetAlphamaps(0, 0, splats);
            UnityEditor.AssetDatabase.SaveAssets();
#endif
        }

        private float[,,] GenerateCtsAlphamap(TerrainData terrainData)
        {
            var cts = GetComponent<CompleteTerrainShader>();
            var splatList = new[] {cts.Splat1, cts.Splat2, cts.Splat3, cts.Splat4};

            // Ensure we have the correct size array.
            var myMap = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);

            // When we have a second splat. Two splats of 4 layers = 8.
            // var myMap = new float[terrainData.alphamapWidth, terrainData.alphamapHeight, 8];
            var layerCount = myMap.GetLength(2);

            for (var splatId = 0; splatId < 4; splatId++)
            {
                var tex = splatList[splatId];
                if (tex == null) continue;

                var colors = splatList[splatId].GetPixels();
                for (var x = 0; x < terrainData.alphamapWidth; x++)
                {
                    for (var y = 0; y < terrainData.alphamapHeight; y++)
                    {
                        // First splat will go in slots 0, 1, 2, 3
                        // Second splat will go in slots 4, 5, 6, 7
                        // Texture is 513, vs alphamap is 512. This is ok, ignore the 513th element.
                        // RGBA (Assume height and width are equal.)
                        myMap[x, y, splatId * 4 + 0] = colors[x * splatList[splatId].width + y].r;
                        if (layerCount <= splatId * 4 + 1) continue;
                        myMap[x, y, splatId * 4 + 1] = colors[x * splatList[splatId].width + y].g;
                        if (layerCount <= splatId * 4 + 2) continue;
                        myMap[x, y, splatId * 4 + 2] = colors[x * splatList[splatId].width + y].b;
                        // Sometimes there are 7 layers, so we have no where to place the 8th layer.
                        if (layerCount <= splatId * 4 + 3) continue;
                        myMap[x, y, splatId * 4 + 3] = colors[x * splatList[splatId].width + y].a;
                    }
                }
            }

            return myMap;
        }
1 Like