odyssey

#6 odyssey 개발일지 : perline noise로 지형 생성

san10 2023. 3. 26. 21:02

저번에 베지어곡선으로 지형을 생성했다.

원래 생각대로라면 런타임중에 베지어곡선으로 지형을 생성하려 했는데...

맵 생성 알고리즘을 찾아보다가 noise로 지형을 생성할 수 있다는 걸 알게되었다!

 

perline noise

펄린 노이즈는 Ken Perline이 영화 '트론'을 제작중에 개발한 노이즈 함수이다.

유기적인 모양의 노이즈를 생성한다.

 

생성원리

임의의 점 x,y은 항상 그리드 안에 위치한다.

점 (x,y)을 둘러싼 그리드의 꼭지점부터 gradient 벡터를 생성한다.

이때 gradient 는 크기가 1인 벡터이고, 이는 유사 난수라고 하는데

왜냐하면 그리드당 랜덤한 벡터값을 부여하기 때문이다.

 

다음으로 그리드의 꼭짓점부터 점 (x,y)로 향하는 거리벡터를 계산한다.

위에서 구한 gradient 벡터와 거리벡터를 내적하면 영향력 값이 나온다.

여기에서 구한 영향력의 값은 불연속적이기 때문에

보간을 통해 부드럽게 만든다.

위의 결과로 -1~1 사이의 값이 나올텐데

그럼 이렇게 생긴 노이즈가 생성된다.

 

 

위의 노이즈는 2차원 펄린 노이즈이고,

위의 생성과정을 1차원으로 하강시키면...

대충 이렇게 생긴 노이즈를 얻을 수 있다!

이러한 1차원 펄린 노이즈를 통해 지형을 생성하려고 한다.

 

유니티에서 구현

유니티에서 Mathf.PerlinNoise() 함수를 제공하기 때문에 쉽게 구현할 수 있었다.

public int numPoints = 100;
public Vector3[] points;
public float scale = 1.0f;
public float xScale;
public float yScale;
public GameObject pointOBJ;
    
public void CreateTerrainpoints()
{
    for (int i = 0; i < numPoints; i++)
    {
        float x = (float)i / (numPoints - 1);
        float y = Mathf.PerlinNoise(x * scale , 0.0f);
        points[i] = new Vector3(x * xScale, y * yScale, 0.0f);
        Instantiate(pointOBJ, points[i], Quaternion.identity);
    }
}

대충 이런 곡선이 만들어졌다..

 

그런데 실제로 구현해보니 지형을 생성하는데 쓰기는 좀 애매하다는 생각이 들었다.

내가 원하는 형태의 지형을 만들기 힘들기도하고..

구현은 해봤지만 아마 펄린 노이즈로 직접적으로 지형 생성을 하진 않을것 같다.

지형 생성에 대해서는 좀더 고민을 해봐야 할 것 같다