using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; struct DifferentialEquationData { public float water; public float vegetation; } public class GrassController : MonoBehaviour { int _structSize() { return sizeof(float) + sizeof(float); } private GameObject cube; public float updateInterval; float timePassed; Terrain terrain; public ComputeShader computeShader; [Header("equation coeffs")] public float DWater = 1.0f; public float DVegetation = 0.5f; public float feedRate = 0.055f; public float killRate = 0.0462f; public float dT = 0.10f; public int stepsNumber = 1; int sizeX; int sizeY; ComputeBuffer vegetation; ComputeBuffer oldVegetation; // Start is called before the first frame update void Start() { terrain = gameObject.GetComponent(); sizeX = terrain.terrainData.detailWidth; sizeY = terrain.terrainData.detailHeight; initComputeShader(); } bool doUpdate() { timePassed += Time.deltaTime; if (timePassed < updateInterval) { return false; } else { timePassed = 0; return true; } } void initKillFeedBuffers() { //tutaj stworz } public void initBufferValues() { // tutaj uzupelnij wartosci buforow float[] initValues = new float[sizeX * sizeY]; for (int i = 0; i < sizeX * sizeY; i++) { initValues[i] = Random.Range(0.0f, 1.0f); } vegetation.SetData(initValues); oldVegetation.SetData(initValues); } public void resetGrass() { initBufferValues(); //var detail = new int[sizeX, sizeY]; //for (int i = 0; i < sizeX; i++) { // detail[i, i] = 16; //} //terrain.terrainData.SetDetailLayer(0, 0, 1, detail); } void initParameters() { //tutaj zainicjalizuj parametry computeShader.SetInt("sizeX", sizeX); computeShader.SetInt("sizeY", sizeY); } void initComputeShader() { //tutaj zainicjalizuj compute shader vegetation = new ComputeBuffer(sizeX * sizeY, sizeof(float)); oldVegetation = new ComputeBuffer(sizeX * sizeY, sizeof(float)); computeShader.SetBuffer(0, "vegetation", vegetation); computeShader.SetBuffer(0, "oldVegetation", oldVegetation); initKillFeedBuffers(); initBufferValues(); initParameters(); } void swapBuffers() { //tutaj zamien bufory ze soba var temp = vegetation; vegetation = oldVegetation; oldVegetation = temp; computeShader.SetBuffer(0, "vegetation", vegetation); computeShader.SetBuffer(0, "oldVegetation", oldVegetation); } void doSimulationSteps(int steps) { //tutaj wykonaj kroki symulacji for (int i = 0; i < steps; i++) { computeShader.Dispatch(0, sizeX, sizeY, 1); } } void recoverData() { //tutaj odczytaj bufor i przeslij wynik jako mapa detali var result = new float[sizeX * sizeY]; vegetation.GetData(result); int[,] detailLayer = new int[sizeX, sizeY]; for (int i = 0; i < sizeX; i++) { for (int j = 0; j < sizeX; j++) { detailLayer[i, j] = Mathf.FloorToInt(result[i + j * sizeX] * 10); } } terrain.terrainData.SetDetailLayer(0, 0, 1, detailLayer); } // Update is called once per frame void Update() { if (doUpdate()) { terrain = gameObject.GetComponent(); initParameters(); doSimulationSteps(stepsNumber); recoverData(); } } }