How to make Perlin Noise Seemless on a sphere?

So, i have made a script to generate perlinnoise, randomly. But what i need is for it to be able to loop on a sphere, and not go small at the top. Here is the script:
using UnityEngine;
using System.Collections;

public class Planet : MonoBehaviour
{
    public int width = 256;
    public int height = 256;

    public float scale = 20f;

    public float offsetX = 100f;
    public float offsetY = 100f;

    private void Start()
    {
        offsetX = Random.Range(0f, 10000f);
        offsetY = Random.Range(0f, 10000f);
    }

    void Update()
    {
        Renderer renderer = GetComponent<Renderer>();
        renderer.material.mainTexture = GenerateTexture();
    }

    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;
    }

    Color CalculateColor(int x, int y)
    {
        float xCoord = (float)x / width * scale + offsetX;
        float yCoord = (float)y / height * scale + offsetY;
        
        float sample = Mathf.PerlinNoise(xCoord, yCoord);
        return new Color(sample, sample, sample);
    }
}

Problem is, i dont know how to approach this.

If you don’t want any seams and warping on your sphere texture, you will need to generate the texture from a 3D perlin noise.

The Sphere is mapped in a longitude/latitude way, so you can deduce the 3D coordinates from the UV (or 2d coords) and some trigonometry :

  • y = sin( UVy * pi - pi/2 )
  • x = cos( UVx * 2 * pi ) * cos( UVy * pi - pi/2 )
  • z = sin( UVx * 2 * pi ) * cos( UVy * pi - pi/2 )

x, y and z are now values in the range [-1;1]. You need to remap them to [0;1] by doing : value = value * 0.5 + 0.5.

Now you can get a 3D perlin noise value by chaining 2 2D perlin noise :

float sample = Mathf.PerlinNoise( Mathf.PerlinNoise(x, y),z);

I haven’t tried, but this should work.