Beispiel #1
0
    // 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();
        }
    }
Beispiel #2
0
    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;
    }