마인크래프트 짭겜 개발노트 #6 "노이즈"

개발노트

2018. 10. 28. 19:27

지형생성을 이야기할 때 빠지지 않는 것이 노이즈 함수이다.


자연스러운 지형을 만들려면 연속적인 패턴이 있는 난수가 필요한데

그렇게 패턴이 있는 난수를 뽑는 함수가 노이즈 함수이기 때문에 지형생성에 노이즈 함수는 아주 유용하다.

노이즈 함수는 입력값이 좌표이고 출력값이 임의의 실수인 함수이다.



이미 다양한 노이즈 함수들이 연구되어 있으니 적당한 노이즈 라이브러리를 가져다 쓰면 된다.

유니티에서도 Mathf.PerlinNoise 유틸리티를 제공하고있고 이걸 이용한 지형생성 예제도 구글링 하면 많이 나온다.

하지만 함수가 하나밖에 없고 그마저도 너무 단순하기 때문에 본격적인 지형생성에 쓰기는 곤란하다는 단점이 있다.


FastNoise Unity
이 라이브러리는 싸게 구할 수 있는 것들 중에서 제일 쓸만하다. 

대표적인 노이즈 함수 대부분을 제공하고, 파라미터를 조절해서 원하는 모양의 노이즈 패턴을 만들 수도 있다.

다양한 노이즈로 다양한 지형을 생성하는 예제씬도 있긴 한데 코드가 너무 난잡해서 개인적으로 별로 참고는 못됐다.


노이즈로 지형을 만드는 가장 간단한 방법은 노이즈를 height map 으로 보는 것이다.

즉, 노이즈 값이 크면 클 수록 해당 좌표의 높이를 높게 하는 것이다.

노이즈를 height map 으로 사용해서 지형을 생성하는 예제는 엄청나게 많다. 사실 그것밖에 없다는 게 문제다.

그런데 이 방법으로 만든 지형은 이것저것 변조를 한다고 해도 너무 단조롭고 그 한계가 명확하다. 

height map 으로는 만족스러운 지형을 얻을 수 없다.


Terrain generation, Part 1 - The Word of Notch

노치는 본인 블로그에서 지형생성을 어떻게 했었는지 구체적으로 알려주진 않고 힌트를 하나 던져주고 있다.

바로 노이즈 값을 '밀도(Density)' 로 보는 것이다.


흔히 노이즈를 표현할 때 2차원 이미지로 나타내기 때문에 간과할 수 있는 것이 하나 있는데

노이즈 함수는 3차원 좌표를 입력값으로 받을 수도 있다는 것이다.

그리고 2차원(height map) 보다는 3차원 정보를 활용하는 편이 분명 더 나은 지형을 만들 수 있을 것이다.

아이디어는 다음과 같다.


density = noise(x, y, z) → density 값 변조 → density > threshold 이면 그 좌표에 블록을 배치


해당 좌표의 노이즈 값이 임계값보다 크면 블록을 배치하는 것이다.

노이즈 값을 그대로 사용할 수도 있겠지만 보통은 자신이 만들고자 하는 지형을 얻기 위해서 변조를 해야한다.

이 부분은 구체적인 구현의 레벨이기 때문에 구글에서도 명확히 설명된 자료는 얻기가 쉽지 않다.

그나마 마인크래프트는 소스가 공개되어 있기 때문에 예시가 필요하다면 Biome 코드들을 읽어보는 것도 한 방법이다.


그렇게 구글링 해도 안 나오는, 그토록 내가 찾고싶었던, 그리고 검색으로 이 블로그를 찾아온 누군가도 알고싶었던,

실험의 실험 끝에 나름대로 찾아낸 터레인 일반 공식은 다음과 같다.


density = (noise + cliff) * scale + offset - y

cliff = (noise * 0.5 + 0.5) * cliffScale

사용한 노이즈 함수 : Simplex noise

noise : 노이즈 함수 값. Noise(x, y, z)

cliffScale : 지형 굴곡

scale : 수치를 키우기 위한 임의의 값

offset : 터레인의 최소높이

y : 현재 y좌표


1. density > 0 이면 그 위치에 블록을 놓는다.

2. scale 값은 직접 테스트하면서 적당한 것을 찾아야하는 실험값이다.

    scale 이 너무 작으면 0보다 작은 값이 많아지므로 터레인에 블록이 너무 적게 배치된다.

    반대로 너무 크면 0보다 큰 값이 많아지므로 터레인에 블록이 너무 많이 배치된다.

3. cliffScale 이 클 수록 지형의 굴곡이 심해진다.

    FastNoise 라이브러리의 노이즈 함수 값의 범위가 [-1, 1] 이기때문에 식에서 이것을 [0, 1] 로 보정해 주고 있다.

4. 마지막에 y를 빼 줌으로써 지형이 중력의 영향을 받게 한다. y 좌표가 클 수록 블록이 배치될 확률이 낮아진다.


생성된 지형의 모습. 

비교할 스크린샷이 없어서 보여주긴 어렵지만 height map 방식보다 확실히 지형이 다채로워 짐을 느낄 수 있다.

오른쪽은 cliff 값을 매우 크게 주었을 때의 결과이다.