// Update is called once per frame /// <summary> /// /// </summary> void Update() { // Convert mouse position to Grid Coordinates Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector3 local_pos = transform.InverseTransformPoint(pos); Vector3 texture_pos = local_pos + Vector3.one * 0.5f; Vector2Int pos_grid = new Vector2Int((int)(texture_pos.x * width), (int)(texture_pos.y * height)); // Get the string of what characters were pressed last frame foreach (char c in Input.inputString) { // Numbers select elements if ('1' <= c && c < '1' + (int)element_selection.size) { selected_element = (element_selection)(c - '0'); UpdateElementSelectionText(); } } string additional_text = ""; // Additional text { RenderTexture.active = textures[0, (int)material.heat_movement]; // Create a new Texture2D and read the RenderTexture image into it Texture2D tex_heat = new Texture2D(width, height, TextureFormat.RGBAFloat, false); tex_heat.ReadPixels(new Rect(0, 0, tex_heat.width, tex_heat.height), 0, 0); var temperature = tex_heat.GetPixel(pos_grid.x, pos_grid.y); RenderTexture.active = textures[0, (int)material.height]; // Create a new Texture2D and read the RenderTexture image into it Texture2D tex_height = new Texture2D(width, height, TextureFormat.RGBAFloat, false); tex_height.ReadPixels(new Rect(0, 0, tex_height.width, tex_height.height), 0, 0); var mass = tex_height.GetPixel(pos_grid.x, pos_grid.y); additional_text = temperature.a.ToString() + "°C\n" + mass.r.ToString() + "kg"; UnityEngine.Object.Destroy(tex_height); UnityEngine.Object.Destroy(tex_heat); } DebugText.text = pos_grid.ToString() + "\n" + additional_text + "\n\n" + element_selection_text; // On mouse clicks if (Input.GetMouseButton(0) || Input.GetMouseButton(1) || Input.GetMouseButton(2)) { // Place lots if (Input.GetMouseButton(0)) { PlaceElement(pos_grid, selected_element, true, 20.0f * Time.deltaTime, 3); } // Place some if (Input.GetMouseButton(2)) { PlaceElement(pos_grid, selected_element, true, 100.0f * Time.deltaTime, 1); } // Remove lots if (Input.GetMouseButton(1)) { PlaceElement(pos_grid, selected_element, true, -100.0f * Time.deltaTime, 5); } } // Make the simulation run a lot faster than the framerate float time_step = 1f / update_rate; for (float i = 0; i < Time.deltaTime; i += time_step) { // Run the shaders for (int mat = 0; mat < (int)material.size; mat++) { // Run the texture through the assigned material (implements a certain shader) Graphics.Blit(textures[0, texture_source[mat]], textures[1, texture_source[mat]], materials[mat]); // Keep the master texture in index 0 and trim the edges of the map Graphics.Blit(textures[1, texture_source[mat]], textures[0, texture_source[mat]], trim_material); } } // Highliting if (Input.GetKeyDown(KeyCode.Space)) { materials[(int)material.world].SetInt("_Highlite", (int)selected_element); } if (Input.GetKeyUp(KeyCode.Space)) { materials[(int)material.world].SetInt("_Highlite", 0); } // Chaos if (Input.GetKeyDown(KeyCode.C)) { Chaos(); } }
private void PlaceElement(Vector2Int pos_grid, element_selection sel, bool change_heat, float amount, int radius) { float small = 0.000001f; // TODO: The "proper" way to do this would be to write a shader to modify the texture then run the shader // Remember currently active render texture RenderTexture currentActiveRT = RenderTexture.active; float temperature = 0.0f; float capacity = 0.0f; // Set the selected RenderTexture as the active one switch (sel) { case element_selection.dirt: RenderTexture.active = textures[0, (int)material.dirt]; temperature = 24f; capacity = GetCapacity(material.dirt); break; case element_selection.copper: RenderTexture.active = textures[0, (int)material.copper]; temperature = 24f; capacity = GetCapacity(material.copper); break; case element_selection.obsidian: RenderTexture.active = textures[0, (int)material.obsidian]; temperature = 18f; capacity = GetCapacity(material.obsidian); break; case element_selection.water: RenderTexture.active = textures[0, (int)material.water]; temperature = 24f; capacity = GetCapacity(material.water); break; case element_selection.lava: RenderTexture.active = textures[0, (int)material.lava]; temperature = 1800f; capacity = GetCapacity(material.lava); break; case element_selection.steam: RenderTexture.active = textures[0, (int)material.steam]; temperature = 100f; capacity = GetCapacity(material.steam); break; case element_selection.heat: RenderTexture.active = textures[0, (int)material.heat_movement]; break; default: return; } // Create a new Texture2D and read the RenderTexture image into it Texture2D element_tex = new Texture2D(width, height, TextureFormat.RGBAFloat, false); element_tex.ReadPixels(new Rect(0, 0, element_tex.width, element_tex.height), 0, 0); // Get the height texture RenderTexture.active = textures[0, (int)material.height]; Texture2D height_tex = new Texture2D(width, height, TextureFormat.RGBAFloat, false); height_tex.ReadPixels(new Rect(0, 0, height_tex.width, height_tex.height), 0, 0); // Get the heat texture RenderTexture.active = textures[0, (int)material.heat_movement]; Texture2D additional_heat_tex = new Texture2D(width, height, TextureFormat.RGBAFloat, false); additional_heat_tex.ReadPixels(new Rect(0, 0, additional_heat_tex.width, additional_heat_tex.height), 0, 0); // Change every pixel in radius for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { if (Mathf.Abs(x) * Mathf.Abs(x) + Mathf.Abs(y) * Mathf.Abs(y) < radius * radius) { int pix_x = pos_grid.x + x; int pix_y = pos_grid.y + y; var element_pixel = element_tex.GetPixel(pix_x, pix_y); var height_pixel = height_tex.GetPixel(pix_x, pix_y); // Calculate change in amount float delta_amount = 0.0f; if (element_pixel.r > 0.0f && amount < 0.0f) { delta_amount = Mathf.Max(element_pixel.r + amount, 0.0f) - element_pixel.r; } else if (element_pixel.r < 1.0f && amount > 0.0f) { delta_amount = Mathf.Min(element_pixel.r + amount, 1.0f) - element_pixel.r; } else { continue; } // If there is amount to change, change it element_tex.SetPixel(pix_x, pix_y, new Color(element_pixel.r + delta_amount, element_pixel.g, element_pixel.b, element_pixel.a)); // Change height if (sel != element_selection.heat) { var final_height = Mathf.Max(height_pixel.r + delta_amount, 0.0f); height_tex.SetPixel(pix_x, pix_y, new Color(final_height, height_pixel.g, height_pixel.b, height_pixel.a)); // Change heat if (change_heat) { // Get the heat texture to add additional heat var heat_pixel = additional_heat_tex.GetPixel(pix_x, pix_y); var new_heat_value = Mathf.Max(temperature * capacity * delta_amount + heat_pixel.r, 0.0f);; additional_heat_tex.SetPixel(pix_x, pix_y, new Color(new_heat_value, heat_pixel.g, heat_pixel.b, new_heat_value / Mathf.Max(final_height, small))); } } } } } height_tex.Apply(); additional_heat_tex.Apply(); element_tex.Apply(); Graphics.Blit(height_tex, textures[0, (int)material.height]); Graphics.Blit(additional_heat_tex, textures[0, (int)material.heat_movement]); switch (sel) { case element_selection.dirt: Graphics.Blit(element_tex, textures[0, (int)material.dirt]); break; case element_selection.copper: Graphics.Blit(element_tex, textures[0, (int)material.copper]); break; case element_selection.obsidian: Graphics.Blit(element_tex, textures[0, (int)material.obsidian]); break; case element_selection.water: Graphics.Blit(element_tex, textures[0, (int)material.water]); break; case element_selection.lava: Graphics.Blit(element_tex, textures[0, (int)material.lava]); break; case element_selection.steam: Graphics.Blit(element_tex, textures[0, (int)material.steam]); break; case element_selection.heat: Graphics.Blit(element_tex, textures[0, (int)material.heat_movement]); break; } // Destroy the textures to stop memory leaks UnityEngine.Object.Destroy(element_tex); UnityEngine.Object.Destroy(height_tex); UnityEngine.Object.Destroy(additional_heat_tex); // Restore previously active render texture RenderTexture.active = currentActiveRT; }