public static void UpdateDetailLayer(TerrainData _terrain_data) { //_terrain_data.SetDetailResolution( TerrainDetailResolution, TerrainPatchDetail ); _terrain_data.wavingGrassStrength = 0.25f; _terrain_data.wavingGrassAmount = 0.25f; DetailPrototype[] _details = new DetailPrototype[10]; int _index = 0; _details[_index] = new DetailPrototype(); _details[_index].prototypeTexture = (Texture2D)Resources.Load("Grass/Grass01"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1.5f; _details[_index].renderMode = DetailRenderMode.Grass; _index = 1; _details[_index] = new DetailPrototype(); _details[_index].prototypeTexture = (Texture2D)Resources.Load("Grass/Grass02"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1.5f; _details[_index].renderMode = DetailRenderMode.Grass; _index = 2; _details[_index] = new DetailPrototype(); _details[_index].prototypeTexture = (Texture2D)Resources.Load("Grass/Grass03"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1.5f; _details[_index].renderMode = DetailRenderMode.Grass; _index = 3; _details[_index] = new DetailPrototype(); _details[_index].prototypeTexture = (Texture2D)Resources.Load("Grass/Flower01"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _index = 4; _details[_index] = new DetailPrototype(); _details[_index].prototypeTexture = (Texture2D)Resources.Load("Grass/Flower02"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.yellow; _details[_index].renderMode = DetailRenderMode.Grass; _index = 5; _details[_index] = new DetailPrototype(); _details[_index].usePrototypeMesh = true; _details[_index].prototype = (GameObject)Resources.Load("Bushes/Fern"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _index = 6; _details[_index] = new DetailPrototype(); _details[_index].usePrototypeMesh = true; _details[_index].prototype = (GameObject)Resources.Load("Bushes/Bush1"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _index = 7; _details[_index] = new DetailPrototype(); _details[_index].usePrototypeMesh = true; _details[_index].prototype = (GameObject)Resources.Load("Bushes/Bush2"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _index = 8; _details[_index] = new DetailPrototype(); _details[_index].usePrototypeMesh = true; _details[_index].prototype = (GameObject)Resources.Load("Bushes/Bush3"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _index = 9; _details[_index] = new DetailPrototype(); _details[_index].usePrototypeMesh = true; _details[_index].prototype = (GameObject)Resources.Load("Bushes/Bush4"); _details[_index].minWidth = 0.25f; _details[_index].maxWidth = 1f; _details[_index].minHeight = 0.25f; _details[_index].maxHeight = 1f; _details[_index].healthyColor = Color.white; _details[_index].renderMode = DetailRenderMode.Grass; _terrain_data.detailPrototypes = _details; TerrainDetailResolution = _terrain_data.detailResolution; int[,] _density_map_00 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_01 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_02 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_03 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_04 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_bush_00 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_bush_01 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_bush_02 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_bush_03 = new int[TerrainDetailResolution, TerrainDetailResolution]; int[,] _density_map_bush_04 = new int[TerrainDetailResolution, TerrainDetailResolution]; float _x_pos_m = (float)_terrain_data.size.x / (float)TerrainDetailResolution; float _y_pos_m = (float)_terrain_data.size.z / (float)TerrainDetailResolution; if (TerrainGrassDensity > 0 || TerrainMeshDensity > 0) { for (int a = 0; a < TerrainDetailResolution; a++) { for (int b = 0; b < TerrainDetailResolution; b++) { float _x = MathTools.Normalize(a * _x_pos_m, 0, _terrain_data.size.x); float _y = MathTools.Normalize(b * _y_pos_m, 0, _terrain_data.size.z); Vector3 _ground = _terrain_data.GetInterpolatedNormal(_y, _x); float _angle = Mathf.Abs(Vector3.Angle(_ground, Vector3.up)); float _f = 5; //float _m = Mathf.Clamp01( 1 - ( _angle / TerrainGrassAngle ) ); if (TerrainGrassDensity > 0) { _density_map_00[a, b] = Mathf.RoundToInt(UnityEngine.Random.Range(TerrainGrassDensity * 0.5f, TerrainGrassDensity) * MathTools.NormalizeRange(_angle, -_f, TerrainGrassAngle + _f, _f)); _f = 5; _density_map_01[a, b] = Mathf.RoundToInt(UnityEngine.Random.Range(TerrainGrassDensity * 0.25f, TerrainGrassDensity * 0.3f) * MathTools.NormalizeRange(_angle, 0, TerrainGrassAngle + _f, _f)); _f = 3; _density_map_02[a, b] = Mathf.RoundToInt(UnityEngine.Random.Range(TerrainGrassDensity * 0.15f, TerrainGrassDensity * 0.25f) * MathTools.NormalizeRange(_angle, -_f * 0.5f, TerrainGrassAngle + _f, _f)); _f = 2; _density_map_03[a, b] = Mathf.RoundToInt(UnityEngine.Random.Range(TerrainGrassDensity * 0.1f, TerrainGrassDensity * 0.5f) * MathTools.NormalizeRange(_angle, -_f, (TerrainGrassAngle * 0.25f) + _f, _f)); _f = 2; _density_map_04[a, b] = Mathf.RoundToInt(UnityEngine.Random.Range(TerrainGrassDensity * 0.1f, TerrainGrassDensity * 0.5f) * MathTools.NormalizeRange(_angle, -_f, (TerrainGrassAngle * 0.25f) + _f, _f)); } if (TerrainMeshDensity > 0) { _f = 5; _density_map_bush_00[a, b] = Mathf.RoundToInt((UnityEngine.Random.Range(0, Mathf.RoundToInt(100 / TerrainMeshDensity)) == 0 ? 1:0) * MathTools.NormalizeRange(_angle, (TerrainGrassAngle * 0.5f) - _f, (TerrainGrassAngle * 2f) + _f, _f)); _f = 2; _density_map_bush_01[a, b] = Mathf.RoundToInt((UnityEngine.Random.Range(0, Mathf.RoundToInt(500 / TerrainMeshDensity)) == 0 ? 1:0) * MathTools.NormalizeRange(_angle, _f, (TerrainMeshAngle * 1.5f) + _f, _f)); _f = 2; _density_map_bush_03[a, b] = Mathf.RoundToInt((UnityEngine.Random.Range(0, Mathf.RoundToInt(500 / TerrainMeshDensity)) == 0 ? 1:0) * MathTools.NormalizeRange(_angle, _f, (TerrainMeshAngle * 1.5f) + _f, _f)); _f = 2; _density_map_bush_03[a, b] = Mathf.RoundToInt((UnityEngine.Random.Range(0, Mathf.RoundToInt(500 / TerrainMeshDensity)) == 0 ? 1:0) * MathTools.NormalizeRange(_angle, _f, (TerrainMeshAngle * 1.5f) + _f, _f)); _f = 2; _density_map_bush_04[a, b] = Mathf.RoundToInt((UnityEngine.Random.Range(0, Mathf.RoundToInt(500 / TerrainMeshDensity)) == 0 ? 1:0) * MathTools.NormalizeRange(_angle, _f, (TerrainMeshAngle * 1.5f) + _f, _f)); } } } } _terrain_data.SetDetailLayer(0, 0, 0, _density_map_00); _terrain_data.SetDetailLayer(0, 0, 1, _density_map_01); _terrain_data.SetDetailLayer(0, 0, 2, _density_map_02); _terrain_data.SetDetailLayer(0, 0, 3, _density_map_03); _terrain_data.SetDetailLayer(0, 0, 4, _density_map_04); _terrain_data.SetDetailLayer(0, 0, 5, _density_map_bush_00); _terrain_data.SetDetailLayer(0, 0, 6, _density_map_bush_01); _terrain_data.SetDetailLayer(0, 0, 7, _density_map_bush_02); _terrain_data.SetDetailLayer(0, 0, 8, _density_map_bush_03); _terrain_data.SetDetailLayer(0, 0, 9, _density_map_bush_04); }
public static void UpdateSplatmap(TerrainData _terrain_data) { SplatPrototype[] _terrain_texture = new SplatPrototype[6]; _terrain_texture[0] = new SplatPrototype(); _terrain_texture[0].texture = (Texture2D)Resources.Load("Textures/Grass (Meadows)"); _terrain_texture[0].tileSize = new Vector2(5, 5); _terrain_texture[1] = new SplatPrototype(); _terrain_texture[1].texture = (Texture2D)Resources.Load("Textures/Grass (Forest)"); _terrain_texture[1].tileSize = new Vector2(5, 5); _terrain_texture[2] = new SplatPrototype(); _terrain_texture[2].texture = (Texture2D)Resources.Load("Textures/Grass (Rock)"); _terrain_texture[2].tileSize = new Vector2(15, 15); _terrain_texture[3] = new SplatPrototype(); _terrain_texture[3].texture = (Texture2D)Resources.Load("Textures/Cliff (Grassy)"); _terrain_texture[3].tileSize = new Vector2(15, 15); _terrain_texture[4] = new SplatPrototype(); _terrain_texture[4].texture = (Texture2D)Resources.Load("Textures/Cliff (Layered Rock Grass)"); _terrain_texture[4].tileSize = new Vector2(25, 25); _terrain_texture[5] = new SplatPrototype(); _terrain_texture[5].texture = (Texture2D)Resources.Load("Textures/Sand (Beach)"); _terrain_texture[5].tileSize = new Vector2(15, 15); _terrain_data.splatPrototypes = _terrain_texture; // Splatmap data is stored internally as a 3d array of floats, so declare a new empty array ready for your custom splatmap data: float[,,] splatmapData = new float[_terrain_data.alphamapWidth, _terrain_data.alphamapHeight, _terrain_data.alphamapLayers]; //float _max_debug_value =0; for (int y = 0; y < _terrain_data.alphamapHeight; y++) { for (int x = 0; x < _terrain_data.alphamapWidth; x++) { // Normalise x/y coordinates to range 0-1 float y_01 = (float)y / (float)_terrain_data.alphamapHeight; float x_01 = (float)x / (float)_terrain_data.alphamapWidth; // Sample the height at this location (note GetHeight expects int coordinates corresponding to locations in the heightmap array) //float _height = _terrain_data.GetInterpolatedHeight(y_01,x_01); // Calculate the normal of the terrain (note this is in normalised coordinates relative to the overall terrain dimensions) Vector3 _normal = _terrain_data.GetInterpolatedNormal(y_01, x_01); // Calculate the angle deviation of the terrain (normal 0) float _angle = Mathf.Abs(Vector3.Angle(_normal, Vector3.up)); //float _angle_multiplier = Mathf.Clamp01( _angle / 90 ); // Calculate the steepness of the terrain float _steepness = _terrain_data.GetSteepness(y_01, x_01); //float _waterlevel = 10; // Setup an array to record the mix of texture weights at this point float[] splatWeights = new float[_terrain_data.alphamapLayers]; // CHANGE THE RULES BELOW TO SET THE WEIGHTS OF EACH TEXTURE ON WHATEVER RULES YOU WANT // BASIC FOREST - Texture[0] has constant influence splatWeights[0] = 0.5f; // GRASS MEADOWS - Texture[1] stronger on flatter terrain splatWeights[1] = 1f - Mathf.Clamp01(_steepness * _steepness / (_terrain_data.heightmapHeight / 5.0f)); // BASIC CORRECTION - reduce the Texture[0] according to the MEADOW value //splatWeights[0] = Mathf.Clamp01( splatWeights[0] - ( splatWeights[1] / 2 ) ); // MEADOW CORRECTION - splatWeights[1] will be also required on flatt hills //splatWeights[1] = ( splatWeights[1] > Mathf.Clamp01( ( _steepness * Mathf.Clamp01(-_normal.z) ) - _height ) ? splatWeights[1] : Mathf.Clamp01( ( _steepness * Mathf.Clamp01(-_normal.z) ) - _height ) ); // BOULDERS - Texture[2] will be required only on flat hillslopes splatWeights[2] = MathTools.NormalizeRange(_angle, 4, 18, 6); //* ( _normal.z > 0 ? 1f : 0f ); splatWeights[3] = MathTools.NormalizeRange(_angle, 10, 45, 6) * Mathf.Clamp01(_normal.z * ((90 - _angle) * 0.1f)); // ( _normal.z > 0 ? 1f : 0f );// Mathf.Clamp01( ( _steepness * Mathf.Clamp01(_normal.z) ) - ( _height * _height) );//Mathf.Clamp01( Mathf.Clamp01( _normal.z * _normal.z ) );//1.0f - Mathf.Clamp01(steepness*steepness/(_terrain_data.heightmapHeight/5.0f)); splatWeights[1] = Mathf.Clamp01(splatWeights[1] - (splatWeights[3] * splatWeights[3])); // ROCK - Texture[4] will be required on cliffy surfaces over 35 degrees splatWeights[4] = MathTools.NormalizeRange(_angle, 35, 90, 10); // ( _normal.z > 0 ? 1f : 0f );// Mathf.Clamp01( ( _steepness * Mathf.Clamp01(_normal.z) ) - ( _height * _height) );//Mathf.Clamp01( Mathf.Clamp01( _normal.z * _normal.z ) );//1.0f - Mathf.Clamp01(steepness*steepness/(_terrain_data.heightmapHeight/5.0f)); splatWeights[2] = (splatWeights[2] == 0 ? MathTools.NormalizeRange(_angle, 30, 45, 5) : splatWeights[2]); //if( _height > _max_debug_value ) // _max_debug_value = _height; float _sum = splatWeights.Sum(); // Loop through each terrain texture for (int _i = 0; _i < _terrain_data.alphamapLayers; _i++) { // Normalize so that sum of all texture weights = 1 splatWeights[_i] /= _sum; // Assign this point to the splatmap array splatmapData[x, y, _i] = splatWeights[_i]; } } } //Debug.Log( _max_debug_value ); // Finally assign the new splatmap to the terrainData: _terrain_data.SetAlphamaps(0, 0, splatmapData); }