Upload
ki-hyunwoo
View
1.127
Download
7
Embed Size (px)
Citation preview
UNREAL SUMMIT 2016
프로젝트 A1의
구형 월드 라이팅 기술
기 현 우리드 그래픽스 프로그래머
UNREAL SUMMIT 2016
A1
• 넥슨의 새로운 IP의 게임 프로젝트
– 타겟: PC 플랫폼 / AAA급 그래픽을 목표로
– 장르: MOBA / 스페이스 오페라
– 엔진: UE4 + @@@
– 아직 개발 중 / 변경 가능성 있음
• 지난 NDC 2016에서 처음으로 개발 소식 공개
UNREAL SUMMIT 2016
A1
• 지난 NDC 2016에서는 캐릭터 렌더링 기술 발표
• 이번 발표에는 월드 라이팅 기술 발표
– 발표에 사용된 월드는 개발 테스트 용
– 실제 게임 월드 아님!
UNREAL SUMMIT 2016
A1의 월드
• 구(球)형 행성
• 실시간 낮/밤 변화
• 부분적인 환경 요소 파괴
– 나무, 건물 등
• 부분적인 지형 변형
– 크레이터 등
UNREAL SUMMIT 2016
A1의 라이팅 요구 사항
• 구형 좌표계
• 경도에 따라 다른 시간
• 시간에 따른 변화
• 다이나믹
– 움직이는 태양
– 환경 파괴와 지형 변형
– 기타…
UNREAL SUMMIT 2016
우리의 접근 방법
• 가능한 “fully dynamic” 라이팅 사용
– 섀도우 맵, SSAO, SSR, SSIS Screen Space Inner Shadows 등
• 일부 전처리와 리라이팅
– 글로벌 일루미네이션, 스카이 라이팅 및 리플렉션 인바이런먼트의시간 변화
UNREAL SUMMIT 2016
구형이라서 달라지는 점 1
• 하늘 방향이 구 표면 상의 위치에 따라 달라짐
– 일반적인 월드: (0, 0, 1)
– 구형 월드: normalize(WorldPosition)
• (0, 0, 0)이 월드 중심이라는 가정
• 편의상 ‘행성 노멀’이라고 부르자
UNREAL SUMMIT 2016
구형이라서 달라지는 점 2
• 구 표면 상의 위치에 따라 시각이 달라짐
– GMT라고 보면 됨
– 기준 시각(GMT+0)으로부터 태양 방향과 행성 노멀 간의 각도에 따라 결정
float ComputeGMTFromWorldPosition(float3 WorldPosition){
float Longitude = atan2(WorldPosition.y, WorldPosition.x) / PI * 0.5f + 0.5f; // [0, 1]float NormalizedGMT = frac(Frame.NormalizedDayTime – Longitude); // East to Westreturn abs(NormalizedGMT);
}
* 노트: Frame.NormalizedDayTime = 태양을 사용한 기준 시각 (GMT+0) = [0. 1)
UNREAL SUMMIT 2016
발표 목차
• 디렉셔널 라이트
• 글로벌 일루미네이션
• 스카이 라이트
• 리플렉션 인바이런먼트
UNREAL SUMMIT 2016
디렉셔널 라이트
Directional Light
UNREAL SUMMIT 2016
디렉셔널 라이트
• 2개를 대칭 배치
– 태양과 달
• 모두 무버블 속성 사용
– 다이나믹 씬을 지원해야 하기 때문
– 다이렉트 라이팅을 실시간 계산
• 디퍼드 라이팅: 불투명 머티리얼
• 포워드+ 라이팅: 반투명 머티리얼
UNREAL SUMMIT 2016
2개의 디렉셔널 라이트
• 태양:
– 게임의 주된 광원
• 달:
– 어두운 밤 지역을 밝힘
– 다이렉트 스페큘러 표현을 위함 (스카이/GI만으로는 아쉬움)
UNREAL SUMMIT 2016
2개의 디렉셔널 라이트
• 문제점:
– 디렉셔널 라이트는 원래 화면 전체에 영향을 주도록 구현
– 잘못된 결과
• 예: 낮 지역에 달 빛
• 느린 성능 (2배)
• 해결책:
– 라이트 기준으로 행성 뒷면을 컬링
– 경계에서는 부드럽게 감쇠
UNREAL SUMMIT 2016
시간 변화 라이팅
• 픽셀마다 다른 시간: 특히 줌아웃 뷰
– 라이트 컴포넌트의 컬러로 조절 불가
• 셰이더에서 미리 만든 텍스처로 라이트 컬러 조절
• GI, 스카이 라이트, 리플렉션 인바이런먼트는 각각 다른 방식을 사용
– 뒷부분에 자세히
UNREAL SUMMIT 2016
태양의 그림자
• 그림자는 게임 플레이에서 현재 시간을 인지하기 위한 요소 중 하나
• 지난 NDC 2016에서 언급
– 기본적으로 UE4 방식을 그대로 사용
• CSM + PCF
– 개량된 PCSS를 혼합
• 시각에 따른 부드러운 그림자 표현을 위함: 0, 1 케스케이드 전용
• 섀도우 노멀 오프셋: 큰 블러 커널에 의한 피터 패닝 방지
• 템포럴 리프로젝션: 느린 공전에 의한 플리커링 방지
UNREAL SUMMIT 2016
타이트한 그림자 바운드
• 성능과 품질 모두를 위해
– CSM은 기본적으로 설정한 최대 거리까지로 바운드를 생성
• 거의 월드 전체를 커버할 수준으로 큼
• 타이트한 그림자 바운드 설정
– 가정: 화면에서 많이 멀어서 안 보이는 오브젝트는 그림자에도 영향을 주지 않는다
– 행성 뒷면 컬링 + 행성 뷰 프러스텀 컬링 바운드보다 좀 더 크게
• 행성 뷰 프러스텀 컬링은 카메라 위치와 각도에 따라 자동 계산
– 1.5배 이상 개선
UNREAL SUMMIT 2016
행성 뷰 프러스텀 컬링
• 카메라에서 행성 중심까지의 거리로Far Plane을 제한
– 행성 뒷면은 안 보인다는 전제
• 카메라가 행성 표면에 가까워질수록Far Plane을 짧게
– 행성 중심에서 측면 Plane까지의 거리와행성 반지름 간의 비례식
UNREAL SUMMIT 2016
최적화 전
행성 뒷면 컬링
행성 뒷면 컬링+ 뷰 프러스텀 컬링
UNREAL SUMMIT 2016
글로벌 일루미네이션
Global Illumination
UNREAL SUMMIT 2016
가능한 솔루션 (UE4)
• 라이트맵 (X)
– 정적, 높은 메모리
• LPV (X)
– 느림, 낮은 품질
• DFGI (X)
– 느림, 스켈레탈 메시 미지원, 지형 변형 미지원
• 간접광 캐시
– 가능성이 있음!
UNREAL SUMMIT 2016
UE4 간접광 캐시 Indirect Lighting Cache; ILC
• SH 이래디언스 볼륨 Spherical Harmonics Irradiance Volume
• 프리미티브(UE4에서의 드로우 단위)마다 캐싱
– 5x5 볼륨 -> 글로벌 볼륨 텍스처 아틀라스에 저장
– 무버블 컴포넌트용 / 위치 이동 시 업데이트
• “볼륨 ILC를 모든 타입의 프리미티브에 적용해볼까?”
– 스태틱 컴포넌트, 지형 등을 포함
UNREAL SUMMIT 2016
볼륨 ILC의 결함
• 인접 프리미티브와 라이팅 불연속성 seam
• 프리미티브의 크기가 크면 밀도 부족
– 월드에 균등 거리로 샘플링하면 완화
– 너무 많은 메모리 소모 및 캐시 업데이트 느림
• 높은 CPU 비용
– 각 프리미티브 단위의 연산
– 라이팅 변경 또는 프리미티브이동 시 업데이트 필요
• 우리 게임에는 부적합
UNREAL SUMMIT 2016
새로운 방식의 필요
• SH 이래디언스 볼륨 컨셉은 유지
• 더 효율적인 자료 구조
– 낭비 없는 메모리 공간과 빠른 어드레싱
• 심리스
– 분할된 지형 컴포넌트끼리, 연속 배치된 스태틱 메시 , 캐릭터와 배경 사이 등
• 빠른 업데이트 (or 업데이트 없는 방식)
– 다수의 액터가 동시에 움직일 때
– 크기가 큰 액터: 배경 오브젝트나 지형
UNREAL SUMMIT 2016
새로운 방식의 필요
• 시간 변화 라이팅 기능의 필요
UNREAL SUMMIT 2016
다른 게임 사례
• 파 크라이 3 & 4
• 어쌔신 크리드 4
• 퀀텀 브레이크
• 더 디비전
• …
UNREAL SUMMIT 2016
디퍼드 큐빅 이래디언스 캐싱 Deferred Cubic Irradiance Caching
• ‘디퍼드’:
– 포스트 프로세싱 방식: 오버 드로우 방지
– 빠른 개발 이터레이션: 빠른 셰이더 리컴파일
– 단, 반투명은 여전히 포워드 렌더링(베이스 패스) 사용
• ‘큐빅’:
– 큐브맵에 캐싱: GPU에서 구를 사상하기에 좋은 자료 구조
– 액터가 아닌 월드 공간 상에 캐시를 저장: 심리스 효과
– 빠른 어드레싱: 큐브 좌표 = 행성 노멀 = normalize(WorldPosition)
UNREAL SUMMIT 2016
UNREAL SUMMIT 2016
UNREAL SUMMIT 2016
시간 변화 라이팅 처리
• 하루 종일 라이트
– 모든 시간에 영향을 주는 라이트
• 시간 변화 라이트
– 특정 시간대에만 영향을 주는 라이트
– 하루를 12단계로: 0, 2, 4, …, 20, 22시
• 12개의 SH 이래디언스 볼륨
– GMT에 가까운 2개의 캐시에서 라이팅 보간
– 런타임 캐시 업데이트는 없음!
UNREAL SUMMIT 2016
처리 과정 개요
• 오프라인
– 이래디언스 캐시 배치
– 포톤 이미션
– 이래디언스와 오클루전 계산
• 런타임
– 큐브맵 캐싱
– SH 라이팅
UNREAL SUMMIT 2016
오프라인: 이래디언스 캐시 배치
• 큐브맵 텍셀
– N x N x 6
– XY 평면 약 50 cm 간격
– Z는 레이 캐스팅으로 지표면을 검출
UNREAL SUMMIT 2016
오프라인: 이래디언스 캐시 배치
• 캐시마다 고정 높이
– 지형 표면에 약간 띄워서 배치
– 현재 게임 설정 상 월드에 복층 구조나 실내가 없음
– 캐릭터 키가 크거나 공중에 떠 있는 경우에 잘못된 계산
• 멀티플 레이어?
– 높이에 따른 변화를 주기 위한 대안
– 아직 계획 없음: 성능과 메모리 문제
UNREAL SUMMIT 2016
오프라인: 포톤 이미션
• 라이트매스: 포톤 매핑 사용
• 발사한 포톤에 시간 변화 라이트 인덱스를 추가로 저장
• 나머진 변화 없음
class FIrradiancePhotonData{protected:
FVector4 PositionAndDirectContribution;FVector4 SurfaceNormalAndIrradiance;
int32 TimeOfDayLightIndex;};
UNREAL SUMMIT 2016
오프라인: 이래디언스 및 오클루전 계산
• 12개의 SH 이래디언스 볼륨
– 포지션, 벤트노멀 및 스카이 오클루전은 공유
– 이래디언스만 다름
• 시간별 이래디언스 계산
– 인다이렉트 포톤 파이널 개더링
• 하루 종일 라이트: 항상 포함
• 시간 변화 라이트: 현재 계산하는 시간에 해당하는 라이트에서 발산된 포톤만 필터링
• 글로벌 스카이 오클루전과 벤트 노멀 계산
UNREAL SUMMIT 2016
UNREAL SUMMIT 2016
런타임: 큐브맵 캐싱
• 로딩 시 1번만 수행
• CPU 이래디언스 캐시 -> GPU 큐브맵
– half4 텍스처 큐브 어레이
• 2nd Order SH: 3장의 텍스처에 인코딩 (RGB)
• 12단계 시간 * 3장 = 36개의 엘리먼트
• 기타:
– 벤트 노멀과 스카이 오클루전: 1장
– 이래디언스 평균 색과 디렉셔널 섀도잉: 12장 – 리플렉션 인바이런먼트에 사용
UNREAL SUMMIT 2016
런타임: SH 라이팅
• 매 프레임 수행
• 텍스처 어드레싱
– 좌표: 행성 노멀 = normalize(WorldPosition)
– 어레이 인덱스: 시각 당 3회 (RGB) = 시간 변화 라이트 인덱스 + 12 * {0|1|2}
• SH2 디퓨즈 라이팅
– 가까운 2개의 시간에서 라이팅 보간
• 총 6회의 텍스처 큐브 어레이 읽기
UNREAL SUMMIT 2016
런타임: SH 라이팅
UNREAL SUMMIT 2016
퍼포먼스
• 라이트 빌드
– 씬에 따라 다름
– 라이트맵보다는 훨씬 빠르지만, 12번의 파이널 개더링의 부담
• 렌더링
– 씬과 무관하게 거의 동일한 비용
• 약 0.4 ms: GTX970 1080p 기준 / 반투명 제외
• 안정된 비주얼
– 심이나 플리커링이 없음
– 캐릭터와 배경에 일관된 룩
UNREAL SUMMIT 2016
스카이 라이트
Sky Light
UNREAL SUMMIT 2016
구형 월드 좌표계로 변환
• 구형에선 하늘 벡터가 달라짐
– (0, 0, 1) 아님
– 행성 노멀 = normalize(WorldPosition)
• 행성 노멀을 (0, 0, 1) 하늘로 로테이션
– 비싼 ALUfloat3 TransformVectorToLandsphereSpace(float3 InVector, float3 WorldPosition){
float3 PlanetNormal = normalize(WorldPosition);float3 SkyUp = float3(0, 0, 1);float3 RotationAxis = normalize(cross(PlanetNormal, SkyUp));float RotationAngle = acos(dot(SkyUp, PlanetNormal));float3x3 Rotator = RotationMatrixAxisAngle(RotationAxis, RotationAngle);return mul(Rotator, InVector);
}
UNREAL SUMMIT 2016
시간 변화 라이팅
• 아티스트가 손으로 만든 여러 장의 스카이 큐브맵 사용
• 역시 12 단계
• 보간된 라이팅
UNREAL SUMMIT 2016
스카이 오클루전과 벤트 노멀
• 무버블 스카이 라이트를 쓰되 섀도우 표현 위함
– RGB: 벤트 노멀
– A: 스카이 오클루전
– 시간 변화 없음: R8G8B8A8 1장
• 디퓨즈 라이팅
– 더 넓고 약하게: sqrt
• 스페큘러 라이팅
– 더 좁고 강하게: Square
Sky Occlusion + Bent Normal
UNREAL SUMMIT 2016
그림자 안의 그림자
• GI와 스카이 라이팅에 사용
• 태양의 그림자 영역 안에 캐릭터가 있을 때의 룩을 개선하기 위함
– 캡슐 섀도우와 비슷한 목적
• SSR 스타일의 레이 마칭
– 씬 뎁스 기반 트레이싱
– SSAO에 비해 방향성이 있는 그림자
– 전처리나 애셋 세팅 불필요
– NDC 2016 발표 참고
UNREAL SUMMIT 2016
리플렉션 인바이런먼트
Reflection Environment
UNREAL SUMMIT 2016
리플렉션 캡쳐 프로브의 배치
• 구 표면 상에 자동으로 균일하게 배치
– 골든 스파이럴
• 수동으로 필요한 곳에 더 배치
UNREAL SUMMIT 2016
시간 변화 라이팅
• 모든 시간대를 미리 캡쳐 및 필터링하기보다는 리라이팅
– 라이팅없이 장면을캡쳐
– 런타임에꼼수로리라이팅
• 리라이팅
– 지오메트릭프로퍼티
• 리라이팅 포지션 = 월드 포지션 + (리플렉션 방향 * 캡쳐 범위 * 스페큘러 오클루전)
• 리라이팅 노멀 = normailze(리라이팅 포지션)
– 다이렉트라이팅:태양과 SH2 디퓨즈스카이라이팅
– 인다이렉트라이팅: 디퍼드큐빅 이래디언스캐싱
• RGB: 이래디언스 = GI의 평균 컬러
• A: 디렉셔널 섀도잉 = 다이렉트 라이팅 섀도우 테스트
UNREAL SUMMIT 2016
UNREAL SUMMIT 2016
볼류메트릭 라이팅
• GI 평균 컬러(이래디언스)는
볼류메트릭 라이팅에도 적용
• 레이 마칭 중에 반영 (고옵)
or 마지막에 반영 (저옵)
UNREAL SUMMIT 2016
요약
• A1은 구형 월드
– 부분적으로 다이나믹
– 시간 변화 라이팅
• 라이팅 요소별 다른 처리
– 디퍼드 큐빅 이래디언스 캐싱
– 리라이팅
UNREAL SUMMIT 2016
향후 작업
• GI 품질 개선 및 활용
– 2nd Order SH -> 3th Order SH
– 레이어드 큐브맵 사용
• GI와 스카이 오클루전에 높이에 따른 변화 반영
– 볼류메트릭 라이팅에 반영
UNREAL SUMMIT 2016
향후 작업
• 환경 파괴와 변형을 반영
– 여러 버전의 이래디언스 캐시
• 파괴된 버전에 대해 미리 라이트 빌드
• 런타임에 존 단위로 업데이트
• 퀀텀 브레이크와 유사
– 지형 변형을 GI에 반영하지 못하는 한계
• SSGI?
– 리플렉션 캡쳐는 부분적으로 리캡쳐
UNREAL SUMMIT 2016
감사합니다
WE ARE HIRING!