ExportGrass.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace AmazingAssets.TerrainToMesh.Example
  5. {
  6. [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
  7. public class ExportGrass : MonoBehaviour
  8. {
  9. public TerrainData terrainData;
  10. public int vertexCountHorizontal = 100;
  11. public int vertexCountVertical = 100;
  12. void Start()
  13. {
  14. if (terrainData == null)
  15. return;
  16. //1. Export mesh from terrain////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. Mesh terrainMesh = terrainData.TerrainToMesh().ExportMesh(vertexCountHorizontal, vertexCountVertical, TerrainToMesh.Normal.CalculateFromMesh);
  18. GetComponent<MeshFilter>().sharedMesh = terrainMesh;
  19. //2. Create material////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  20. string shaderName = Utilities.GetUnityDefaultShader(); //Default shader based on used render pipeline
  21. Material material = new Material(Shader.Find(shaderName));
  22. GetComponent<Renderer>().sharedMaterial = material;
  23. //3. Export grass//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  24. DetailPrototypesData[] detailPrototypesData = terrainData.TerrainToMesh().ExportGrassData(vertexCountHorizontal, vertexCountVertical, 1, 1, 8, 1);
  25. Mesh grassMesh = Utilities.CreateGrassMesh(1); //Create grass quad mesh
  26. Shader grassShader = Shader.Find(Constants.shaderGrass); //Simple Mobile/Diffuse shader with Alpha cutout
  27. string mainTexturePropName = Utilities.GetMaterailPropMainTex(); //_MainTex property name inside shader.
  28. //Instantiate grass objects
  29. for (int t = 0; t < detailPrototypesData.Length; t++)
  30. {
  31. GameObject grassParent = new GameObject("Grass"); //Used as parent for all current type of grass objects
  32. grassParent.transform.SetParent(this.gameObject.transform, false);
  33. //Each type of grass needs its own material with texture from prototype
  34. Material grassMaterial = new Material(grassShader);
  35. grassMaterial.SetTexture(mainTexturePropName, detailPrototypesData[t].detailPrototype.prototypeTexture);
  36. for (int p = 0; p < detailPrototypesData[t].position.Count; p++)
  37. {
  38. GameObject grass = new GameObject("Grass");
  39. //Use quad mesh for grass
  40. grass.AddComponent<MeshFilter>().sharedMesh = grassMesh;
  41. //Assign material
  42. grass.AddComponent<MeshRenderer>().sharedMaterial = grassMaterial;
  43. //Assign parent
  44. grass.transform.SetParent(grassParent.transform, true);
  45. //Position
  46. grass.transform.localPosition = detailPrototypesData[t].position[p];
  47. //Add random rotation
  48. grass.transform.localRotation = Quaternion.Euler(0, Random.value * 360, 0);
  49. //Scale
  50. grass.transform.localScale = detailPrototypesData[t].scale[p];
  51. }
  52. //After all grass objects of the current type are created, it is better to combine them into one mesh
  53. List<Mesh> combinedMeshes = Utilities.CombineGameObjects(grassParent, grassMaterial, "Grass", detailPrototypesData[t].detailPrototype.prototypeTexture.name, UnityEngine.Rendering.IndexFormat.UInt16);
  54. //Bake grass Healthy and Dry color inside vertex color
  55. foreach (var mesh in combinedMeshes)
  56. {
  57. BakeHealthyAndDryColorsInsideVertexColor(mesh, detailPrototypesData[t].detailPrototype);
  58. }
  59. }
  60. }
  61. void BakeHealthyAndDryColorsInsideVertexColor(Mesh mesh, DetailPrototype detailPrototype)
  62. {
  63. Vector3[] vertexPosition = mesh.vertices;
  64. Color[] colors = mesh.colors; //Mesh already contains 'Alpha' value for Top and Bottom position
  65. Color healthyColor = detailPrototype.healthyColor;
  66. healthyColor.a = 1;
  67. Color dryColor = detailPrototype.dryColor;
  68. dryColor.a = 1;
  69. for (int i = 0; i < vertexPosition.Length; i++)
  70. {
  71. float pNoise = Mathf.PerlinNoise(vertexPosition[i].x * detailPrototype.noiseSpread, vertexPosition[i].z * detailPrototype.noiseSpread);
  72. //Multiply with existing color
  73. colors[i] *= Color.Lerp(dryColor, healthyColor, pNoise);
  74. }
  75. mesh.colors = colors;
  76. }
  77. }
  78. }