Thinking Different




Terrain 18 - 큰 지형 렌더링



원문 : http://www.rastertek.com/tertut18.html


 지난 몇 년 동안 방대한 양의 지형을 렌더링하는 수많은 그래픽 엔진이 출시되었습니다. 가장 최근의 것들 중 일부는 현재 32km (20 마일) 이상 보이는 지형을 렌더링 중입니다. 이렇게 지형을 더 많이 볼 수 있게 렌더링 가능하도록 한 배경에는 빠르게 향상되어온 그래픽카드가 한 몫을 해주었습니다.



디테일의 정도


몇 킬로미터의 지형을 렌더링하려면 다양한 수준의 상세 (LOD) 기술 중 하나를 사용해야합니다. LOD는 먼 지형에서 폴리곤 수와 복잡한 쉐이더 사용을 줄이는 공통 목표를 공유하는 기술 그룹입니다. 많은 세부 사항을 줄이지 않고도 많은 지형을 렌더링하려고 시도하면 일반적인 경우 적정한 속도로 그래픽을 렌더링하지 못하고 버벅 거릴 수 있습니다. 하지만 LOD 구현을 통해 엄청난 양의 지형을 간단하게 그릴 수 있으며 동시에 안정적인 프레임 속도를 유지할 수 있습니다.


멀리 떨어진 지형의 세부 사항을 동적으로 줄이는 다양한 LOD 알고리즘이 있습니다. 그러나 그들 중 대부분은 먼 지형에 접근 할 때 눈이 너무 산만해지는 끔찍한 지형을 발생시킵니다. 또한 이 같은 동적 알고리즘은 일반적으로 지형 가장자리에 눈에 띄는 균열을 일으킴과 동시에 올바르게 정렬되지 않는 문제가 있습니다. 동적 LOD 알고리즘의 이러한 두 가지 공통적인 문제를 피하기 위해 이 문제가 없는 미리 빌드 된 지형을 사용하는 방법을 대신 다루겠습니다. 우리가 사용할 방법은 노드 기반 LOD입니다.



노드 기반 LOD


노드 기반 LOD는 전체 지형이 여러 노드로 균등하게 분할되는 방식입니다. 각 노드는 동일한 크기이며 128m x 128m와 같은 특정 거리를 포함합니다. 이제 이 방법에서 가장 중요한 점은 각 노드에 여러 품질 수준이 있다는 것입니다. 예를 들어, 노드는 지형 편집기에 미리 빌드된 (저, 중, 고) 품질 버전을 가질 수 있습니다. 그런 다음 그 노드를 렌더링 할 때 카메라와의 거리를 결정하고 렌더링 할 품질 버전을 선택합니다. 카메라에 가까울수록 고품질 버전을 렌더링합니다. 중간 품질을 조금 더 렌더링하면 특정 범위를 벗어나지만 최대 렌더링 거리 이내에 있는 경우 저품질 버전을 그립니다. 물론 원하는 수준의 품질을 유지할 수 있습니다.


노드 기반 LOD의 다음 부분은 카메라가 지형을 따라 이동할 때 백그라운드 스레드를 사용하여 노드를 로드 및 언로드 한다는 것입니다. 대부분의 비디오 카드는 수 킬로미터의 여러 지형 노드를 수용 할만큼 충분한 메모리가 없으므로 로딩 / 언 로딩이 필요합니다. 또한 프레임 속도를 중단시키지 않으려면 백그라운드 스레드를 사용하여 로드를 수행해야 합니다. 예를 들어 카메라가 중간 품질의 노드에 더 가깝게 이동하면 스레드의 고품질 버전으로 로드해야 합니다. 일단 로드되면 고품질 버전을 렌더링하도록 전환합니다. 마지막으로 이전에 사용했던 중간 품질 버전을 언로드합니다.


DirectX 11에서는 지형 노드 로드 및 언로드를 수행하기 위해 꼭지점 및 인덱스 버퍼를 만들고 릴리스하지 않아야 합니다. 이렇게하면 비디오 카드가 잠기고 메모리 스래싱이 발생합니다. 대신 각 품질 수준에 대해 사전 초기화된 동적 버텍스 버퍼 배열을 사용해야 합니다. 이 버퍼는 해제 및 재작성되지 않고 재사용됩니다. 각 품질 수준의 버퍼가 같은 크기이므로 Map 함수를 사용하여 이전 데이터를 덮어 쓸 수 있습니다. 예를 들어 9 개의 고품질 노드가 있는 경우 고품질 노드에만 전용으로 사용되는 10 개의 버텍스 및 인덱스 버퍼 배열이 있어야합니다. 새로운 고품질 노드를 로드해야 할 때 사용되지 않는 10 번째의 정점 / 인덱스 버퍼를 사용하고 지형 노드 데이터를 이 노드에 매핑하여 노드에 포인터를 지정합니다.


각 품질 수준마다 셰이더 (또는 여러 셰이더)가 있습니다. 가까운 지형을 위해 사용하는 복잡한 쉐이더는 먼 지형에 사용해서는 안됩니다. 또한 렌더링 할 때 셰이더별로 정렬하고 상수 버퍼 업데이트를 최소화하여 가능한 최상의 프레임 속도를 얻으려고 하여야 합니다.


노드 기반 LOD의 마지막 부분은 카메라의 위치에 따라 노드를 렌더링한다는 것입니다. 현재 카메라가 존재하는 노드와 주변의 8개 노드는 고품질로 렌더링되어야 합니다. 이를 통해 카메라를 둘러싸고 있는 영역을 항상 고품질로 유지할 수 있으며 카메라가 움직일 때 더 높은 품질의 노드를 로드 할 수있는 충분한 시간을 제공합니다. 정상적으로 매핑된 텍스처와 같은 효과는 거리에 나타나지 않으므로 고품질 지형의 노드를 9개 이상 수행할 필요가 없습니다.


9개의 고품질 노드를 둘러싸고 있는 다음 16개 노드는 중간 품질로 렌더링됩니다. 중간 정도의 품질로 16개 이상의 노드 (예: 16개 노드를 감싸고있는 다음 24개 노드)를 수행할 수도 있습니다. 그러나 이는 매우 유연하며 테스트를 거친 후에 결정할 것입니다.


마지막으로 그 이상으로 렌더링 된 노드의 나머지 부분은 낮은 품질로 처리됩니다. 특정 특수 노드의 예외가 있을 수 있지만 자세한 내용은 나중에 자세히 설명하겠습니다. 방금 설명한 내용을 보여주는 다이어그램은 다음과 같습니다.




이제 다이어그램에는 두 수준의 품질이 낮은 노드만 표시되지만 더 많은 작업을 수행해야 합니다. 하지만 먼저 얼마나 많은 지도를 그려야하는지 파악하기 위해 렌더링 비용을 결정해야 합니다. 예산에 관해서는 곧 논의 하겠지만 먼저 노드 컬링에 대해 이야기 해야 합니다.



노드 컬링


노드 기반 LOD를 사용하면 볼 수 없는 노드를 매우 쉽게 제거 할 수 있습니다. 각 노드는 특정 위치에서 특정 크기이므로 빠른 절두체 테스트를 다시 수행하여 노드가 빨리 렌더링되지 않게 할 수 있습니다. 더 빠른 속도로 컬링을 수행하는 쿼드 트리를 만들 수도 있습니다. 특정 카메라 위치에서 평균적으로 지형의 30% 이상을 보지 못합니다. 예를 들어, 아래 다이어그램은 위쪽으로 볼 때 가운데에 있는 경우 회색으로 컬링된 노드를 보여줍니다.




노드 컬링을 지금 말씀드리는 이유는 렌더링 비용과 크게 관련되어 있기 때문입니다. 추려진 주변 노드는 여전히 메모리에 로드되어야 하지만 우리 프레임 속도는 그 순간에 그리는 것만 반영합니다. 렌더링 비용을 작성할 때 이를 명심하십시오.




렌더링 비용


엄청난 양의 지형을 렌더링하기 전에 미리 계획을 세워야합니다.


목표 시스템 사양을 기반으로 렌더링 해야 하는 지형의 양을 최대한 가깝게 결정하려고 합니다. 그 외 무엇이 렌더링 될 것이며, 우리의 지형이 차지하는 비율을 고려해야 합니다. 다음은 렌더링 할 지형의 양을 결정하는데 도움이 되는 간단한 예입니다.



스트레스 폴리 예산 = 약 500,000 다각형.

메모리 예산 = 목표 사양이 1GB 비디오 카드라고 가정하면, 지형에는 약 500MB, 나무, 건물 등에 대해서는 약 500MB를 사용하십시오.

다른 문제가 나타날 경우를 대비하여 쿠션을 제공하기 위해 충분한 공간을 메모리 (약 10 %)에 남겨 둡니다.

이 거친 스펙을 염두에 두고 이제 노드 품질을 설정할 수 있습니다.


고품질 노드


풀 그래픽 : 일반 동적 조명과 텍스처 블렌딩의 4 개 레이어로 매핑됩니다.

128x128 * 2 삼각형 = 32,768 폴리선

메모리 : 32768 polys * 3 정점 * 64 바이트 (12 바이트 위치 * 8 바이트 tex * 12 바이트 일반 * 12 바이트 접두어 * 12 바이트 바이너리 * 8 바이트 tex) = 6144KB (6MB)

9 노드 = 54MB 메모리, 0-384 미터 지형 범위, 294,912 폴리선

텍스처 : 4 개의 지형 텍스처 512x512, 1-2 법선 맵 512x512, 1 블렌딩 텍스처 512x512

중간 품질 노드


Reduced Graphics : 동적 조명으로만 색상이 매핑됩니다.

64x64 * 2 삼각형 = 8,192 폴리

메모리 : 8192 polys * 3 정점 * 36 바이트 (12 바이트 위치 * 12 바이트 색상 * 12 바이트 일반) = 864KB (0.84MB)

16 노드 = 13.5 MB 메모리, 384 ~ 640 미터 지형 범위, 131,072 폴리

텍스처 : 없음

저품질 노드


Reduced Graphics : 동적 조명으로만 색상이 매핑됩니다.

16x16 * 2 삼각형 = 512 polys

메모리 : 512 polys * 3 정점 * 36 바이트 (12 바이트 위치 * 12 바이트 색상 * 12 바이트 일반) = 54KB (0.05MB)

24 노드 = 1.25 MB 메모리, 640 ~ 896 미터 지형 범위, 12,228 폴리

텍스처 : 없음

저품절 노드 (두 번째 계층)


Reduced Graphics : 동적 조명으로만 색상이 매핑됩니다.

16x16 * 2 삼각형 = 512 polys

메모리 : 512 polys * 3 정점 * 36 바이트 (12 바이트 위치 * 12 바이트 색상 * 12 바이트 일반) = 54KB (0.05MB)

32 노드 = 1.69 MB 메모리 - 896 ~ 1152 미터 지형 범위, 16,384 폴리

텍스처 : 없음

따라서 이 스펙은 이전에 다이어그램을 작성한 것과 동일한 지형을 제공합니다. 그러나 더 많은 거리를 커버하기 위해 더 낮은 품질의 노드를 추가하려고 합니다. 평균 폴리곤 수를 테스트하기 위해 필자는 평범한 색상의 노드를 렌더링하는 빠른 프로그램을 작성했지만 위에서 정의한 저, 중, 고품질 노드에 대해서는 여전히 정점 수를 사용합니다.




보시다시피 카메라는 더 높은 다각형 수 (파란색), 다각형 수 (녹색)의 절반을 가진 더 먼 중간 노드, 낮은 다각형 모드의 먼 노드 (빨간색)로 카메라가 끝난 노드를 렌더링 했습니다. 16x16 노드 지형 (2km)을 렌더링했을 때 평균 약 250k 다각형을 얻은 결과입니다. 노드 수를 25x25 (3km)로 늘리면 평균 375k 다각형을 얻었습니다. 또한 필자의 데스크톱 컴퓨터에서 1000fps를 넘었고 성능이 약한 노트북에서 100fps를 넘었습니다. 그래서 여기에서 정의한 현재 스펙과 노드 품질 설정으로 어느 정도 벗어날 수 있는지를 알 수 있었습니다.


이제는 프레임 속도가 너무 거칠다는 점에 유의하십시오. 실제로 대부분의 비디오 카드 프로세서는 절대적으로 필요한 경우를 제외하고는 메모리를 최대한으로 사용하지 않으므로 처리량을 절약 할 수 있습니다. 따라서 실제로 더 많은 노드를 렌더링 할 수 있고 프레임 속도가 더 낫다는 것을 알 수 있습니다. 다시 한번 이것은 시작하기 위해 내가 무엇을 목표로해야 하는지를 보여주는 스트레스 테스트 일뿐입니다. 그리고 항상 코드를 잘 작성하면 몇 가지 변수를 변경하고 더 많은 노드를 렌더링하거나 새로운 품질 수준을 추가하는 것이 간단해야 합니다. 품질 수준과 노드 수의 최종 상태를 결정하기 전에 이러한 모든 사항을 테스트해야 합니다.



지형 빌딩


좋은 지형을 구축하려면 일반적으로 자체 지형 편집기를 작성해야 합니다. 특히 각 지형 노드에 대해 여러 품질 수준을 내보내려는 계획이 있으므로 자동으로 이를 수행할 도구를 작성하는 것이 더 중요합니다.


구현을 위해 대부분의 지형 편집기는 Perlin 노이즈를 사용하여 프랙탈 지형을 생성한 다음 편집기에 다양한 도구 및 기타 알고리즘을 추가하여 지형을 특정 모양으로 수정합니다. 일부 지형 편집자는 생물학 알고리즘을 사용하여 식물, 나무, 강, 바위 등을 배치합니다.


지형 편집기를 작성할 때 일반적으로 Visual C ++와 같은 빠른 것을 사용하여 프로그램을 신속하게 프로토 타이핑하는 것이 좋습니다. 아티스트는 텍스트 및 숫자 입력 상자 대신 슬라이더 및 다이얼과 같은 것을 선호하며 Visual C ++에는 이미 내장된 것들이 있습니다.




지형 편집기는 자체적으로 거대한 프로젝트가 될 수 있지만 당분간은 perlin 노이즈를 생성하고 사용자 고유의 모델 형식으로 내보낼 수 있는 무언가를 만드는 것으로 충분합니다. 지형의 각 128x128 미터 섹션에 대해 세 가지 품질 수준을 내보내는 내보내기 기능을 빌드하십시오. 높은 품질은 높이지도의 129x129 부분입니다. 중간 품질은 65x65로 축소 된 동일한 129x129 섹션 (바람직하게는 가장자리 보존 재 샘플) 일 것입니다. 그리고 마지막으로 저품질 버전은 129x129 섹션에서 샘플링 한 17x17 높이 맵입니다.


염두에 두어야 할 점은 높이를 나타내기 위해 단지 8 비트를 사용하여 0에서 255까지의 범위를 제공하는 것이 일반적이라는 것입니다.이 정밀도가 매우 부족하여 큰 사실적인 지형을 만드는 데 유용하지 않습니다. 일반적으로 전체 16 비트 범위를 사용하지 않더라도 16 비트 높이 값을 사용하는 것이 좋습니다.



모델 적용


이제 특정 지형 모델 형식으로 내보낼 수 있는 간단한 지형 편집기가 생겼으므로 위에서 자세히 설명한대로 지형 노드 렌더링을 시작할 수 있습니다. 이전 지형 지도서는 이미 이 프로젝트를 직접 완료하는 데 필요한 모든 코드를 보여 주므로 이 듀토리얼에서 새로운 그래픽 코드가 필요하지 않습니다. 그러나 몇가지 확인되어야 하는 세부사항이 있습니다.


첫 번째로, 일부 노드는 원거리에서도 항상 최소한의 중간 품질 (예: 산)을 필요로 합니다. 그러므로 지형 렌더링 엔진에서 특정 노드 아래에 품질을 저하시키지 않도록 노드를 지정할 수 있는 방법이 있어야 합니다.


두 번째는 아마도 16km 만 렌더링 할 수 있는 한계를 발견했지만 32km 지형을 가질 수 있다는 것입니다. 이는 문제가 되지 않습니다. 왜냐하면 16km의 가시 거리에 들어서면서 더 낮은 품질의 노드를 로드한 다음 그 거리 밖에 있는 품질이 낮은 노드를 언로드하는 것이기 때문입니다. 품질이 낮은 노드의 경우에도 버텍스 및 인덱스 버퍼를 다시 사용하는 것을 다시 한번 기억하십시오.


또한 원거리 노드를 부드럽게 가져오는데 사용되는 트릭은 먼 거리에 로드될 때 보이지 않는 대신 먼 뷰 평면을 올바르게 설정하는 것입니다. 예를 들어 우리의 한계가 16km 가시 거리인 경우 원거리 시야 평면을 15.8km로 설정하십시오. 그런 다음 15.8km 거리에 도달하기 전에 16km 범위로 들어오는 로드 노드를 확인하십시오. 이제 노드가 렌더링되는 범위에 오면 먼 평면 컬링을 사용하여 다각형으로 부드럽게 그려집니다. 다시 한번 우리는 항상 전통적인 LOD 방법으로 발생한 팝핑을 제거하는 방법을 찾고 있습니다.


또한 컬러 맵을 중간 및 저품질 노드의 중요한 도구로 사용했기 때문에 어떻게 구축했는지 설명하고 싶습니다. 일반적으로 최상위 관점에서 높은 품질의 노드를 렌더링합니다. 먼저 지형을 평평하게 하고 빛을 똑바로 내려 놓습니다. 이 시점에서 스크린샷을 찍은 다음 중간 크기와 낮은 품질의 노드 크기를 컬러 맵으로 축소합니다.


마지막으로 추가하고자 하는 것은 고품질 거리 밖에 있는 노드의 쉐이더를 사용하여 세부 묘사를 표현하지 않는 것입니다. 중간 정도의 품질의 노드 옆에 고품질의 노드를 배치하면 보통 품질의 노드에서 조명이 부드럽게 보이는것 이외의 다른 효과는 보지 못할 것입니다. 그리고 건물, 나무 등으로 지형을 많이 차지할 것이라는 점을 감안하면 조명이 눈에 띄지 않게됩니다.




마치면서


이제 노드 기반 LOD 기반의 기초와 이를 구현하여 수 킬로미터의 지형을 그리는 방법을 이해하게 되었습니다. 엄청난 범위를 확보하기 위한 핵심은 테스트를 통해 품질이 낮은 노드 및 그 주변의 최적화를 사용하여 한계를 테스트하는 것입니다. 또한 이전 튜토리얼은 이미 DirectX 11을 사용하여 지형을 렌더링하는 데 필요한 모든 그래픽 기술을 다루었기 때문에 이 튜토리얼의 코드는 없습니다.



연습문제


1. 렌더링 비용을 작성합니다.


2. 지형 편집기를 작성하여 Perlin 노이즈 생성 지형을 세 가지 품질 수준의 지형 모델 형식으로 자동으로 내보냅니다.


3. 위와 같이 지형 렌더링 프로그램을 작성하십시오. 볼 수 있는 지형의 약 4km를 먼저 시도하십시오.


4. 볼 수 있는 지형 8km 이상과 볼 수 없는 8km를 렌더링하도록 프로그램을 업데이트하여 16km의 지형을 탐색해보세요.