Unity noise map generation (Editor extension)

Recently, I discovered that many shaders in the project require noise maps. (The shadergraph has its own noise map generation.) When a noise map is needed, it is very troublesome to find it, so I read the information on the Internet and wrote a Unity extended noise map generation.

Perlin noise

Perlin noise is a gradient noise algorithm invented by Ken Perlin in 1983 for generating random textures with continuous and smooth changes in computer graphics. It is often used to simulate natural shapes, such as mountains, clouds, water waves, etc., and can also be used to increase the detail and realism of textures.

Perlin noise is generated by
dividing the space into a series of regular grid cells (usually squares or cubes).

Randomly generate a gradient vector (usually 2D or 3D) at the vertex position of each grid cell.

For each spatial point, calculate its position within the grid cell, and calculate its interpolation with the grid vertex based on the gradient vector and position. Interpolation can use different methods like linear interpolation, cubic interpolation, etc.

The interpolation values ​​of different grid cells are weighted and added to obtain the final Perlin noise value.
There are math libraries available in Unity

Mathf.PerlinNoise(xCoord, yCoord)

He used a two-dimensional random vector to replace the original random value, causing a certain gradient transformation between each point, so that the generated noise map had almost no obvious blockiness.
insert image description here

Just call it directly

Simple noise

Simple Noise, also known as Value Noise, is a relatively simple noise algorithm. It is simpler than Perlin noise and does not involve the calculation of gradient vectors. Instead, it generates random values ​​at discrete grid points, and then uses an interpolation algorithm to obtain noise values ​​between these random values.

The generation process of simple noise is as follows:

Divide space into a series of regular grid cells (usually squares or cubes).

Randomly generate a random value (usually between 0 and 1) at each grid cell's vertex position.

For each point in space, its position within the grid cell is calculated and interpolated based on the random value of the vertex. Interpolation can use different methods like linear interpolation, cubic interpolation, etc.

Get the noise value at this point, as part of a simple noise texture.

Simple noise is faster to calculate than Perlin noise because it does not require complex gradient calculations. However, simple noise may show obvious edges and dividing lines in the generated texture. This is because the interpolation method is relatively simple, causing the change of noise to be not smooth enough.

   //线性差值 1接近Y 0接近X
    float mix(float x, float y, float level)
    {
    
    
        return x * (1 - level) + y * level;
    }
    float value_noise(Vector2 coord)
    {
    
    
        Vector2 i = floor(coord);
        Vector2 f = fract(coord);

        // 4 corners of a rectangle surrounding our point
        float tl = rand(i);
        float tr = rand(i + new Vector2(1.0f, 0.0f));
        float bl = rand(i + new Vector2(0.0f, 1.0f));
        float br = rand(i + new Vector2(1.0f, 1.0f));

        Vector2 cubic = f * f * (new Vector2(3.0f, 3.0f) - 2.0f * f);

        float topmix = mix(tl, tr, cubic.x);
        float botmix = mix(bl, br, cubic.x);
        float wholemix = mix(topmix, botmix, cubic.y);

        return wholemix;

    }

"Blocky feeling"
insert image description here

Cellular Noise

is a noise generation algorithm that simulates cellular structures. It is widely used in computer graphics and game development to generate textures with fine particles, spots, holes, and uniform distribution. The principle of cell noise is to divide the space into many regular or irregular cells, randomly generate a point in each cell, and then calculate the distance from other points to the nearest point. These distances are used to generate noise maps.

The generation process of cell noise is as follows:

Divide space into a series of regular or irregular cells.

A point is randomly generated in each cell, called a "Feature Point".

For each spatial point, calculate its distance to the nearest feature point. The distance is usually calculated using Euclidean distance or Manhattan distance etc.

Noise values ​​can be generated based on distance, for example using functions such as the inverse of distance or the inverse square of distance.

Cellular noise is often used to simulate effects such as speckled textures, uniformly distributed particles, skin textures, terrains, etc. It can generate organic and natural-looking textures because it is based on cell-like structures rather than simple random values. Cell noise is a very useful tool in game development and computer graphics, where it can be used to enhance visual effects and add complexity to textures.

float cellular_noise(Vector2 coord)
    {
    
    
        Vector2 i = floor(coord);
        Vector2 f = fract(coord);

        float min_dist = 99999.0f;
        // going through the current tile and the tiles surrounding it
        for (float x = -1.0f; x <= 1.0; x++)
        {
    
    
            for (float y = -1.0f; y <= 1.0; y++)
            {
    
    

                // generate a random point in each tile,
                // but also account for whether it's a farther, neighbouring tile
                Vector2 node = rand2(i + new Vector2(x, y)) + new Vector2(x, y);

                // check for distance to the point in that tile
                // decide whether it's the minimum
                float dist = Mathf.Sqrt((f - node).x * (f - node).x + (f - node).y * (f - node).y);
                min_dist = Mathf.Min(min_dist, dist);
            }
        }
        return min_dist;
    }

cell
insert image description here

Pseudo-random generation for random use, post all codes later

FBM

Fractal Brownian motion noise is a noise generation algorithm based on fractal technology. It generates complex textural effects by stacking multiple noise layers of different frequencies and amplitudes. FBM noise is often used to generate textures with a level of detail, such as clouds, flames, waves and other effects.

The generation process of FBM noise is as follows:

Divide a space into a series of regular or irregular grid cells (usually squares or cubes).

Randomly generates a noise value (usually between 0 and 1) at the vertex position of each grid cell.

For each spatial point, its position within the grid cell is calculated and interpolated based on the noise value of the vertex. Interpolation can use different methods, such as linear interpolation, cubic interpolation, etc.

The interpolation values ​​of different grid cells are weighted and added, and multiplied by a scaling factor to obtain the final FBM noise value.

The characteristic of FBM noise is that the detail and roughness of the texture can be controlled by adjusting the frequency and amplitude of different layers. By increasing the number of layers and scaling factors, you can make textures appear more complex and natural. FBM noise can simulate many complex phenomena in nature, so that the generated texture has a more realistic and detailed appearance.

loat fbm(Vector2 coord)
    {
    
    
        int OCTAVES = 4;

        float normalize_factor = 0.0f;
        float value = 0.0f;
        float scale = 0.5f;

        for (int i = 0; i < OCTAVES; i++)
        {
    
    
            value += Mathf.PerlinNoise(coord.x, coord.y) * scale;
            normalize_factor += scale;
            coord *= 2.0f;
            scale *= 0.5f;
        }
        return value / normalize_factor;
    }

FBM noise is generated by stacking multiple Perlin noise layers of different frequencies, so more complex and diverse textures can be generated with a richer level of detail. Some math libraries used by
Perlin many times
insert image description here

  Vector2 mod(Vector2 coord, float a)
    {
    
    
        return new Vector2(coord.x % a, coord.y % a);
    }
    float fract(float x)
    {
    
    
        return x - Mathf.Floor(x);
    }
    Vector2 fract(Vector2 x)
    {
    
    
        return new Vector2(x.x - Mathf.Floor(x.x), x.y - Mathf.Floor(x.y));
    }
    Vector2 floor(Vector2 x)
    {
    
    
        return new Vector2(Mathf.Floor(x.x), Mathf.Floor(x.y));
    }
    float rand(Vector2 coord)
    {
    
    
        // prevents randomness decreasing from coordinates too large
        coord = mod(coord, 10000.0f);
        // returns "random" float between 0 and 1
        return fract(Mathf.Sin(Vector2.Dot(coord, new Vector2(12.9898f, 78.233f))) * 43758.5453f);
    }
   //线性差值 1接近Y 0接近X
    float mix(float x, float y, float level)
    {
    
    
        return x * (1 - level) + y * level;
    }
    Vector2 rand2(Vector2 coord)
    {
    
    
        // prevents randomness decreasing from coordinates too large
        coord = mod(coord, 10000.0f);
        // returns "random" vec2 with x and y between 0 and 1
        return fract((new Vector2(Mathf.Sin(Vector2.Dot(coord, new Vector2(127.1f, 311.7f))), Mathf.Sin(Vector2.Dot(coord, new Vector2(269.5f, 183.3f))))) * 43758.5453f);
    }

Take the modulo operation, take the decimal part, take the integer part, pseudo-random code
to implement a random function by yourself, and this random function is "controllable", and the same input should get the same output.

 void SaveTexture(Texture2D texture)
    {
    
    
        byte[] bytes = texture.EncodeToPNG();//读取图像为PNG
        var dirPath = Application.dataPath + "/" + AssetsName + "/";//当前文件夹路径
        Debug.Log("生成路径:" + dirPath);//生成路径位置
        if (!Directory.Exists(dirPath))
        {
    
    
            Directory.CreateDirectory(dirPath);//没有路径则生成
        }
        for (int i = 0; i < 1000; i++)
        {
    
    
            if (!File.Exists(dirPath + "Image" + "(" + i + ")" + ".png"))
            {
    
    
                File.WriteAllBytes(dirPath + "Image" + "(" + i + ")" + ".png", bytes);//写入文件里面
                break;
            }
        }
    }


    Texture2D GenerateTexture()
    {
    
    
        Texture2D texture = new Texture2D(width, height);//新建贴图

        for (int x = 0; x < width; x++)
        {
    
    
            for (int y = 0; y < height; y++)
            {
    
    
                Color color = CalculateColor(x, y);//计算颜色,遍历像素
                texture.SetPixel(x, y, color);//设置像素颜色
            }
        }
        texture.Apply();//应用贴图修改

        return texture;
    }

Image file saving

some reference materials

Unity implements the production of noise maps (Perlin Noise).
Use Unity to generate various types of noise maps. Share the basic generation method of
FBM fractal Brownian motion noise function . I will upload the .cs file in the future. Click here to download.


Guess you like

Origin blog.csdn.net/qq_45498613/article/details/131905507