Unity3D Worley noise algorithm code implementation

Worley Noise noise algorithm

The algorithm process of Worley noise is as follows.
First, a 2D 'grid' needs to be created. The 'grid' is composed of 'grids'. The 'grid' here does not correspond to a single pixel, but a 'grid' contains many pixels.
(A grid as shown in the figure, a grid is composed of 9 pixels, and a 'grid' is composed of countless such 'grids', how many pixels a grid consists of has a great influence on the final effect) 1.
insert image description here
Each A grid will be associated with a randomly generated point, which is called a feature point here. The point must be inside the grid.
2. For each pixel, calculate the distance to its nearest feature point as the gray value of the pixel.

So how to find which feature point is closest to the pixel? Just loop through the Jiugong grid centered on the grid where the pixel is located. Simple calculations can be used to prove that the nearest feature point to the pixel will not be outside the position of the Jiugongge.

Code

The hash function used is as follows. This hash function returns another point given a point, that is, given a 'grid' and then returns a feature point in the grid. The hash function can be designed by yourself, as long as the following conditions are met. 1. For
the
same The input has the same output
2. Roughly satisfy the statistical randomness
3. Each component of the point is between [0,1] (so, using trigonometric functions is a good choice)

        static Vector2 hash(Vector2 p)
        {
    
    
            float random = Mathf.Sin(666 + p.x * 5678 + p.y * 1234) * 4321;
            return new Vector2(p.x+Mathf.Sin(random)/2+0.5f, p.y+Mathf.Cos(random)/2+0.5f);
        }

Then, as mentioned above, a nine-square grid loop, to find the nearest point,
the return value can also be reversed (that is, subtract itself from 1), and the picture generated by worly noise is quite artistic whether it is normal or reversed.

public static float noise(float x, float y)
        {
    
    
            float distance = float.MaxValue;
            for (int Y = -1; Y <= 1; Y++)
            {
    
    
                for (int X = -1; X <= 1; X++)
                {
    
    
                    Vector2 cellPoint = hash(new Vector2((int) x + X, (int) y + Y));
                    distance = Mathf.Min(distance, Vector2.Distance(cellPoint, new Vector2(x, y)));
                }
            }

            return 1-distance;
        }

In this way, the code of worly noise is finished.
Then we create a c# script to generate a texture based on this function.
Create a Texture2D and use the SetPixel function in a double loop to set the color of the corresponding pixel, because we want to create a grayscale image, so the rgb components are all the same.
It should be noted that when we pass in the parameters, we divide the coordinate value by 16, which means that there are 16 pixels in a 'grid'.
Finally, I wrote a function to save the created texture as a picture.
Mount this class on an object to generate a noise image and paste it on the object, and save the image in the Assets folder.

    public class CreateWorlyNoise : MonoBehaviour
    {
    
    
        [Range(1, 512)] public int cellSize=16;

        private void Start()
        {
    
    
            Texture2D texture = new Texture2D(512, 512);
            this.GetComponent<Renderer>().material.mainTexture = texture;
            for (int y = 0; y < texture.height; y++)
            {
    
    
                for (int x = 0; x < texture.width; x++)
                {
    
    
                    float grayscale = WorlyNoise.noise(x / (float) cellSize, y / (float) cellSize);
                    texture.SetPixel(x, y, new Color(grayscale, grayscale, grayscale));
                }
            }

            texture.Apply();
            saveTexture2D(texture, "tex");
        }

        void saveTexture2D(Texture2D texture, string fileName)
        {
    
    
            var bytes = texture.EncodeToPNG();
            var file = File.Create(Application.dataPath + "/04WorlyNoise/" + fileName + ".png");
            var binary = new BinaryWriter(file);
            binary.Write(bytes);
            file.Close();
            AssetDatabase.Refresh();
        }
    }

Effect demonstration

The effect is as follows. In fact, according to the previous algorithm, you can also guess that since there is an operation to find the nearest point, many circles will definitely be generated.
(If you adjust the color, it actually looks like some cell tissue)
insert image description here
After inverting
insert image description here

terrain generation

We also use worly noise to generate a terrain try

using Algorithm;
using UnityEngine;

public class CreateTerrain : MonoBehaviour
{
    
    
    
    void Start()
    {
    
    
        for (int z = 0; z < 128; z++)
        {
    
    
            for (int x = 0; x < 128; x++)
            {
    
    
                float grayscale = ValueNoise.noise(x / (float) 16, z / (float) 16);
                var cube=GameObject.CreatePrimitive(PrimitiveType.Cube);
                int cubeY = (int) (grayscale * 10);
                cube.transform.position = new Vector3(x, cubeY, z);
                cube.GetComponent<Renderer>().material.color=new Color(0,grayscale,0);
            }
        }
    }
}

Mount this script on an object in any scene, and you can get the following effects.
insert image description here
The repetition is too strong, it seems not suitable for terrain generation

full code

public static class WorlyNoise
    {
    
    
        public static float noise(float x, float y)
        {
    
    
            float distance = float.MaxValue;
            for (int Y = -1; Y <= 1; Y++)
            {
    
    
                for (int X = -1; X <= 1; X++)
                {
    
    
                    Vector2 cellPoint = hash(new Vector2((int) x + X, (int) y + Y));
                    distance = Mathf.Min(distance, Vector2.Distance(cellPoint, new Vector2(x, y)));
                }
            }

            return 1-distance;
        }

        static Vector2 hash(Vector2 p)
        {
    
    
            float random = Mathf.Sin(666 + p.x * 5678 + p.y * 1234) * 4321;
            return new Vector2(p.x+Mathf.Sin(random)/2+0.5f, p.y+Mathf.Cos(random)/2+0.5f);
        }
       
    }

class for generating images

using System.IO;
using UnityEditor;
using UnityEngine;

namespace Algorithm
{
    
    
    public class CreateWorlyNoise : MonoBehaviour
    {
    
    
        [Range(1, 512)] public int cellSize=16;

        private void Start()
        {
    
    
            Texture2D texture = new Texture2D(512, 512);
            this.GetComponent<Renderer>().material.mainTexture = texture;
            for (int y = 0; y < texture.height; y++)
            {
    
    
                for (int x = 0; x < texture.width; x++)
                {
    
    
                    float grayscale = WorlyNoise.noise(x / (float) cellSize, y / (float) cellSize);
                    texture.SetPixel(x, y, new Color(grayscale, grayscale, grayscale));
                }
            }

            texture.Apply();
            saveTexture2D(texture, "tex");
        }

        void saveTexture2D(Texture2D texture, string fileName)
        {
    
    
            var bytes = texture.EncodeToPNG();
            var file = File.Create(Application.dataPath + "/04WorlyNoise/" + fileName + ".png");
            var binary = new BinaryWriter(file);
            binary.Write(bytes);
            file.Close();
            AssetDatabase.Refresh();
        }
    }
}

In addition, the code has also been passed to the github warehouse, you can also pay attention to it~
my github

Guess you like

Origin blog.csdn.net/o83290102o5/article/details/117425429