📒Level Of Detail (LOD)
📌What is Level Of Detail?
: 메시 모델링 데이터의 정밀도를 단계별로 조정하는 기술
- 가까우면 메시를 세밀하게, 멀면 단순하게 표현
- 렌더링 속도(Speed)와 질(Quality)의 밸런싱
- 실시간 렌더링 기술은 어느정도 퀄리티를 타협하더라도 빠른 렌더링이 중요함
- 가능한 좋은 퀄리티로(즉 타협을 덜 하면서) 빠르게 렌더링하기 위함
[LOD 타입]
📌Static LOD
: 여러개의 메시를 준비해 사용
- 카메라와 물체 간 거리를 측정해서 카메라와 가까운 거리에 있는 물체는 정밀한메시를 사용하고, 거리가 멀어질수록 낮은 단계의 메시를 사용
- 처음부터 메시의 정밀도가 정해져 있고, 이를 카메라와의 거리에 따라서 단계별로 바꿔가며 사용하는 것
- 장단
- 장: 간단하므로 속도가 빠름
- 단: 메모리 낭비, 거리에 따라서 메시가 급격히 변할 때 튀는 현상(popping) 발생
📌Dynamic LOD
: 카메라와 물체의 거리에 따라서 실시간으로 메시의 정밀도를 변화시킴
- 메시 분할과 메시 간략화 두 타입으로 나뉨
- 장단
- 장: 거리에 따라 LOD가 이루어지므로 튀는 현상(popping) 적음, 메모리 낭비 없음
- 단:
- 느린 속도: 메시 분할, 간략화 등에 추가 연산이 필요
- 잦은 Lock-Unlock: 레벨이 바뀌거나 정점데이터를 갱신할 때 정점 계산을 동적으로 수행
DirectX11과 Tesellation
DirectX 11 버전부터는 GPU가 LOD를 처리해줘서, 따로 구현하지 않아도 된다.
📒Dynamic LOD
📌LOD 계산
(1) 거리기반 LOD
: 시점 위치와 오브젝트의 거리를 이용해 단계 값을 구하는 방법
- 구현이 간단하고 부하가 적음
- 필요없는 부분이 세밀하게 보이거나 세밀하게 보여야 하는 부분이 단순하게 보일 수 있음
(2) 면적기반 LOD
: 오브젝트의 투영 면적에 따른 단계값을 구하는 방법
- 자연스럽게 표현됨
- 많은 CPU 연산량: 투영 면적이 달라질 때마다 다시 계산
📌(방법1) 메시 간략화
: 폴리곤의 수를 줄이는 방법
- 간략화할 기준을 세우고 모양을 최대한 유지한 상태에서 폴리곤의 수 제거
- 간략화 기준: 어느 폴리곤의 어느 꼭지점을 먼저 제거할 것인가 등
- 간략화 방법:
- 점 제거(Vertex Decimation)
- 점 합치기(Vertex Clustering)
- 면 줄이기(Edege Colapse)
📌(방법2) 메시 분할
: 하나 폴리곤을 여러 개의 폴리곤으로 분할하는 방법
📌균열 현상 (Crack)

하나의 단일 메시 속에 여러 단계의 패치가 존재할 때, 인접한 패치 간 분할 단계의 차이가 존재하는 경우 발생
- 패치 단위로 분할 level을 잡는다면 level이 변하는 경계면에선 틈이 생김 (들림)
[Crack이 생기지 않게 하기]
- 방법1: 인접한 두 패치 가 서로 level이 다르더라도, 더 낮은 level의 패치쪽에선 맞닿는 면의 레벨을 높여줘야(맞춰줘야) 함
- 방법2: 패치 단위가 아닌, 거리에 따라 분할 level을 잡으면 자연스럽게 mapping 가능
[발생한 Crack을 매꾸기]
: 추가 삼각형을 발생한 Crack에 끼워넣기
- 뗌질 삼각형을 LOD단계가 달라지는 모든 노드에 해서 상하좌우 네 가지 방향으로 만들어줌


📌poppiong 현상
: 거리에 따라 폴리곤 수가 갑작스럽게 줄어들거나 늘어나면 그래픽이 튀어보이는 현상
- 정적LOD사용시 급격한 레벨의 차이로 모양이 바뀌어 튀어보이는 현상
- 해결: 보간
- 낮은 레벨에서 높은 레벨로 갈 때 사라지는 정점의 위치값을 level 간 차이에 대한 보간값 t를 구해 보간
- 정적LOD에서의 해결 : 실시간으로 데이터를 계산할때 t값을 구하고, 그에 따라 보간
- 동적LOD에서의 해결 : 두 level에서의 버텍스 버퍼를 모두 stream source로 보내고, t값을 세팅하여 버텍스 셰이더에서 두 버텍스를 보간
[보간 예시]

: level0 (0, 0), (10, 15), (20, 5)과 level1(0, 0), (20, 5)으로 구성된 직선이 있을 때
level1에서 존재하지 않는 점 (10, 15)를 level1에서의 가상의점 (10, 2.5)와 보간해야 함
현재 level이 0이고 보간값 t가 0.5라면
중간점은 0.5 (10, 15) + 0.5 (10, 2.5) = (10, 8.75)
📒Tesellation과 Height map
: Height map을 참고해서 추가적으로 만든 정점들의 높이를 변경
- ex 지형텍스처가 표현하려고 했던 고해상도 지형 적용
📌Displacement Mapping
- nomal mapping: 근본적으로 geometry를 조작하지 못함
- tesellation: surfaces를 쪼개 만든 정점의 위치를 조작할 수 있음
📌Setting
[Mesh]
: Tesellation level의 차이를 주려면 patch를 필요한 값으로 세팅해줘야 함
즉, mesh를 새로 만들어 써야 함
[height map]
- 픽셀 포맷: R32
- shader
- UV: 전체 기준
- normal: shader에서 재계산 필요
📌normal 재계산
: height map을 그대로 적용시키면 height는 적용되지만,
모든 vertex의 normal은 여전히 같은 방향이므로 명암의 차이가 존재하지 않음
[Normal 구하기]
- 바로 주변 정점의 높이를 통해 현재 접하는 면의 Tangent와 Binormal을 도출 가능
- 이를 통해 Normal 구함
[변화량 도출]
- 정점 간 간격 변화량
- Inside Level로 정점 간 이동 간격 추측
정점 간 간격 변화량 = 1 / pathLevel.Inside
- 정점 간 UV 변화량
UV 간 변화량 = 1 / FaceXY * 정점 간 간격
- 계산 좌표계
- world에서 scale이 적용되면 높이가 변하므로, world 좌표계에서 계산해야 함
- (주의) 계산 후 WV matrix 곱하는 것과 결과 다름!!

📌LandScape
: height map으로 적용시킬 texture를 실시간으로 수정해서, 지형을 만드는 것
- height tex 수정
- albedo tex 수정
References
[1] LOD: https://blog.naver.com/ssod015/220272372528
[2] Height Map: https://victorbush.com/2015/01/tessellated-terrain/
[3] LandScape: https://victorbush.com/2015/01/tessellated-terrain/