Home > database >  Unity - How to create circular gradient?
Unity - How to create circular gradient?

Time:11-01

I need a small help, I am trying to create an Island generator using Unity.

However I do not know how to make circular fall Off map.But instead I manage to create an island that is more of a box shaped island.

This is what I am doing:

  1. I am generating Height map using Perlin noise
  2. I will generate FallOff map and substract it from Perlin noise
  3. The Island getsgenerated, but instead of having circular shape the island hasbox-like shape

I want to create this enter image description here

This is my Perlin noise function

public float[,] GenerateNoise(int mapSize,int octaves, string seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
    {
        if (noiseScale <= 0)
        {
            noiseScale = 0.0001f;
        }
        
        float halfWidth = mapSize / 2f;
        float halfHeight = mapSize / 2f;
        
        float[,] noiseMap = new float[mapSize   1, mapSize   1];
        System.Random rand = new System.Random(seed.GetHashCode());

        //Octaves offset
        Vector2[] octavesOffset = new Vector2[octaves];
        for (int i = 0; i < octaves; i  )
        {
            float offset_X = rand.Next(-100000, 100000)   offset.x;
            float offset_Y = rand.Next(-100000, 100000)   offset.y;
            octavesOffset[i] = new Vector2(offset_X / mapSize, offset_Y / mapSize);
        }

        for (int x = 0; x < mapSize; x  )
        {
            for (int y = 0; y < mapSize; y  )
            {
                float amplitude = 1;
                float frequency = 1;
                float noiseHeight = 0;
                float superpositionCompensation = 0;


                for (int i = 0; i < octaves; i  )
                {
                    float sampleX = (x - halfWidth) / noiseScale * frequency   octavesOffset[i].x;
                    float sampleY = (y - halfHeight) / noiseScale * frequency   octavesOffset[i].y;

                    float perlinValue = Mathf.PerlinNoise(sampleX, sampleY);
                    noiseHeight  = perlinValue * amplitude;
                    noiseHeight -= superpositionCompensation;

                    amplitude *= persistence;
                    frequency *= lacunarity;
                    superpositionCompensation = amplitude / 2;

                }

                noiseMap[x, y] = Mathf.Clamp01(noiseHeight);

            }
        }

        return noiseMap;
    }

And this is my FallOff map function

public float[,] GenerateFallOffMap(int mapSize)
{
    float[,] fallOffMap = new float[mapSize , mapSize];

    for (int x = 0; x < mapSize; x  )
    {
        for (int y = 0; y < mapSize; y  )
        {
            int index = x * mapSize   y;
            float fallOff_A = x / (float)mapSize * 2 - 1;
            float fallOff_B = y / (float)mapSize * 2 - 1;

            float value = Mathf.Max(Mathf.Abs(fallOff_A), Mathf.Abs(fallOff_B));
            fallOffMap[x,y] = Evaluate(value);
        }
    }

    return fallOffMap;
}

static float Evaluate(float value)
{
    float a = 3;
    float b = 2.2f;

    return Mathf.Pow(value, a) / (Mathf.Pow(value, a)   Mathf.Pow(b - b * value, a));
}

CodePudding user response:

Use the distance from the center of the grid as the parameter to calculate the falloff value.

/// value - The calculated value to process
/// radius - The distance from center to calculate falloff distance
/// x - The x-coordinate of the value position
/// y - The y-coordinate of the value position
/// cx - The x-coordinate of the center position
/// cy - The y-coordinate of the center position
public float RadialFallOff(float value, float radius, int x, int y, float cx, float cy) 
{
  float dx = cx - x;
  float dy = cy - y;
  float distSqr = dx * dx   dy * dy;
  float radSqr = radius * radius;

  if (distSqr > radSqr) return 0f;
  return value;
}

This will result in a hard cutoff at radius. If you want a softer transition along the edges, you can use an innerRadius and an outerRadius to produce a feathered effect:

/// value - The calculated value to process
/// innerRadius - The distance from center to start feathering
/// outerRadius - The distance from center to fully fall off
/// x - The x-coordinate of the value position
/// y - The y-coordinate of the value position
/// cx - The x-coordinate of the center position
/// cy - The y-coordinate of the center position
public float FeatheredRadialFallOff(float value, float innerRadius, float outerRadius, int x, int y, float cx, float cy) 
{
  float dx = cx - x;
  float dy = cy - y;
  float distSqr = dx * dx   dy * dy;
  float iRadSqr = innerRadius * innerRadius;
  float oRadSqr = outerRadius * outerRadius;

  if (distSqr >= oRadSqr) return 0f;
  if (distSqr <= iRadSqr) return value;

  float dist = Mathf.Sqr(distSqr);
  float t = Mathf.InverseLerp(innerRadius, outerRadius, dist);
  return value * t;
}

You can use it like such:

float value = Mathf.Max(Mathf.Abs(fallOff_A), Mathf.Abs(fallOff_B));
value = Evaluate(value)

fallOffMap[x,y] = RadialFalloff(value, someRadius, x, y, mapSize / 2f, mapSize / 2f);
// or
fallOffMap[x,y] = FeatheredRadialFalloff(value, someInnerRadius, someOuterRadius, x, y, mapSize / 2f, mapSize / 2f);
  • Related