사례 연구 - 혼합 현실에서 은하계 만들기

Microsoft HoloLens 출시되기 전에 개발자 커뮤니티에 새 디바이스에 대한 숙련된 내부 팀 빌드를 보고 싶은 앱 종류를 물었습니다. 5,000개 이상의 아이디어가 공유되었고, 24시간 동안 트위터 여론조사를 실시한 후 우승자는 갤럭시 Explorer이라는 아이디어였습니다.

프로젝트의 아트 리더인 앤디 지빗과 팀의 그래픽 엔지니어인 카림 루신(Karim Luccin)은 Explorer 은하계의 은하수를 정확하고 대화형으로 표현하기 위한 예술과 엔지니어링 간의 협력 노력에 대해 이야기합니다.

더 테크

두 명의 디자이너, 3명의 개발자, 4명의 아티스트, 프로듀서, 1명의 테스터로 구성된 우리 팀은 6주 동안 사람들이 은하수 은하계의 광대함과 아름다움을 배우고 탐구할 수 있는 완전한 기능 앱을 빌드했습니다.

HoloLens가 생활 공간에서 직접 3D 개체를 렌더링하는 기능을 최대한 활용하고 싶었기 때문에 사람들이 가까이에서 확대하고 개별 별을 볼 수 있는 현실적인 은하계를 만들고 싶었습니다.

개발 첫 주에 은하수 은하계를 표현하기 위한 몇 가지 목표를 세웠습니다. 은하의 모양을 만드는 데 도움이 되는 별들이 가득한 깊이와 움직임, 볼륨감이 필요했습니다.

수십억 개의 별을 가진 애니메이션 은하를 만드는 문제는 업데이트가 필요한 단일 요소의 수가 프레임당 너무 커서 HoloLens가 CPU를 사용하여 애니메이션 효과를 줄 수 없다는 것이었습니다. 우리의 솔루션은 예술과 과학의 복잡한 혼합을 포함했다.

배후 상황

사람들이 개별 별을 탐험할 수 있도록 하기 위해 첫 번째 단계는 한 번에 렌더링할 수 있는 입자 수를 파악하는 것이었습니다.

파티클 렌더링

현재 CPU는 직렬 작업과 최대 몇 개의 병렬 작업을 한 번에 처리하는 데 적합하지만(코어 수에 따라) GPU는 수천 개의 작업을 병렬로 처리하는 데 훨씬 더 효과적입니다. 그러나 일반적으로 CPU와 동일한 메모리를 공유하지 않으므로 CPU<>GPU 간에 데이터를 교환하면 병목 현상이 빠르게 발생할 수 있습니다. 우리의 해결책은 GPU에서 은하를 만드는 것이었고, GPU에서 완전히 살아야했습니다.

우리는 다양한 패턴으로 수천 개의 점 입자로 스트레스 테스트를 시작했습니다. 이를 통해 HoloLens의 은하계를 통해 무엇이 효과가 있었는지, 무엇이 효과가 있었는지 볼 수 있습니다.

별의 위치 만들기

팀 구성원 중 한 명이 이미 초기 위치에서 별을 생성하는 C# 코드를 작성했습니다. 별은 타원에 있으며 그 위치는 (curveOffset, ellipseSize, elevation)로 설명 할 수 있습니다. 여기서 curveOffset은 타원을 따라 star 각도이며, ellipseSize는 X와 Z를 따라 타원의 차원이며, 은하 내의 star 적절한 고도를 상승합니다. 따라서 각 star 특성으로 초기화될 버퍼(Unity의 ComputeBuffer)를 만들고 나머지 환경에서 사용할 GPU에 보낼 수 있습니다. 이 버퍼를 그리기 위해 Unity의 DrawProcedural 을 사용하여 은하계를 나타내는 실제 메시 없이 임의의 점 집합에서 셰이더(GPU의 코드)를 실행할 수 있습니다.

Cpu:

GraphicsDrawProcedural(MeshTopology.Points, starCount, 1);

Gpu:

v2g vert (uint index : SV_VertexID)
{

 // _Stars is the buffer we created that contains the initial state of the system
 StarDescriptor star = _Stars[index];
 …

}

우리는 수천 개의 입자로 원시 원형 패턴으로 시작했습니다. 이것은 우리가 많은 입자를 관리하고 성능 빠른 속도로 실행할 수 있다는 증거를 제공하지만, 우리는 은하의 전반적인 모양에 만족하지 않았다. 모양을 개선하기 위해 회전을 통해 다양한 패턴과 파티클 시스템을 시도했습니다. 입자와 성능의 수가 일관되게 유지되었기 때문에 처음에는 유망했지만, 모양이 중앙 근처에서 고장났고 별들이 바깥쪽으로 방출되어 현실적이지 않았습니다. 우리는 시간을 조작하고 입자가 은하계의 중심에 점점 더 가까워지도록 현실적으로 움직일 수 있는 방출이 필요했습니다.

이와 같이 회전하는 다양한 패턴과 입자 시스템을 시도했습니다.

이와 같이 회전하는 다양한 패턴과 입자 시스템을 시도했습니다.

우리 팀은 은하가 작동하는 방식에 대한 몇 가지 연구를 했고, 우리는 은하의 팔이 더 높은 밀도의 영역이지만 교통 체증과 같은 일정한 유동적인 영역이라고 이론화하는 "밀도파 이론"에 따라 타원에서 입자를 이동할 수 있도록 은하를 위해 특별히 사용자 지정 입자 시스템을 만들었습니다. 안정적이고 단단한 것처럼 보이지만, 별들은 각각의 타원을 따라 움직일 때 실제로 팔 안팎으로 움직이고 있습니다. 시스템에서 파티클은 CPU에 존재하지 않습니다. 카드를 생성하고 GPU에서 모두 방향을 지정하므로 전체 시스템은 단순히 초기 상태 + 시간입니다. 다음과 같이 진행되었습니다.

GPU 렌더링을 사용하여 파티클 시스템의 진행

GPU 렌더링을 사용하여 파티클 시스템의 진행

충분한 타원을 추가하고 회전하도록 설정되면, 은하들은 별의 움직임이 수렴 "팔"을 형성하기 시작했다. 각 타원형 경로를 따라 별의 간격은 몇 가지 임의성을 부여하고, 각 star 위치 임의의 추가의 비트를 얻었다. 이것은 star 움직임과 팔 모양의 훨씬 더 자연스러운 분포를 만들었습니다. 마지막으로 중심에서의 거리에 따라 색을 구동하는 기능을 추가했습니다.

별의 동작 만들기

일반적인 star 동작에 애니메이션 효과를 주려면 각 프레임에 일정한 각도를 추가하고 별들이 일정한 방사형 속도로 타원을 따라 움직이도록 해야 했습니다. 이것이 curveOffset을 사용하는 주된 이유입니다. 별들이 타원의 긴 면을 따라 더 빨리 움직일 것이기 때문에 기술적으로 는 정확하지 않지만 일반적인 움직임은 기분이 좋았습니다.

별은 긴 호에서 더 빨리 움직이고 가장자리는 느립니다.

별은 긴 호에서 더 빨리 움직이고 가장자리는 느립니다.

이를 통해 각 star (curveOffset, ellipseSize, elevation, Age)로 완전히 설명됩니다. 여기서 Age는 장면이 로드된 이후 경과된 총 시간의 누적입니다.

float3 ComputeStarPosition(StarDescriptor star)
{

  float curveOffset = star.curveOffset + Age;
  
  // this will be coded as a “sincos” on the hardware which will compute both sides
  float x = cos(curveOffset) * star.xRadii;
  float z = sin(curveOffset) * star.zRadii;
   
  return float3(x, star.elevation, z);
  
}

이를 통해 애플리케이션 시작 시 수만 개의 별을 한 번 생성한 다음, 설정된 곡선을 따라 단일 별 집합에 애니메이션을 적용했습니다. 모든 것이 GPU에 있으므로 시스템은 CPU에 대한 비용 없이 모든 별을 병렬로 애니메이션할 수 있습니다.

흰색 쿼드를 그릴 때의 모양은 다음과 같습니다.

흰색 쿼드를 그릴 때의 모양은 다음과 같습니다.

각 쿼드가 카메라를 향하게 하기 위해 기하 도형 셰이더를 사용하여 각 star 위치를 star 텍스처를 포함하는 화면의 2D 사각형으로 변환했습니다.

쿼드 대신 다이아몬드.

쿼드 대신 다이아몬드.

오버드라우(픽셀이 처리되는 횟수)를 최대한 제한하고 싶었기 때문에 쿼드가 겹치지 않도록 쿼드를 회전했습니다.

클라우드 추가

볼륨 내부에서 광선이 행진하는 것부터 클라우드를 시뮬레이션하기 위해 가능한 한 많은 입자를 그리는 것까지 입자로 볼륨 느낌을 얻는 방법에는 여러 가지가 있습니다. 실시간 광선 행진은 너무 비싸고 작성하기 어려웠기 때문에 먼저 게임에서 포리스트를 렌더링하는 방법을 사용하여 사기꾼 시스템을 구축하려고 했으며, 카메라를 향한 나무의 2D 이미지가 많이 있습니다. 게임에서 이 작업을 수행할 때 카메라에서 렌더링된 트리의 텍스처가 회전하고, 모든 이미지를 저장하고, 런타임에 각 광고판 카드 보기 방향과 일치하는 이미지를 선택할 수 있습니다. 이미지가 홀로그램일 때도 작동하지 않습니다. 왼쪽 눈과 오른쪽 눈의 차이는 훨씬 더 높은 해상도가 필요하거나 평평하거나 별칭이 있거나 반복적으로 보입니다.

두 번째 시도에서 우리는 가능한 한 많은 입자를 갖기 위해 노력했습니다. 가장 좋은 시각적 개체는 입자를 추가하기 전에 입자를 가산해서 흐리게 표시할 때 달성되었습니다. 이러한 접근 방식의 일반적인 문제는 한 번에 그릴 수 있는 입자 수와 60fps를 유지하면서 덮은 화면 영역의 양과 관련이 있습니다. 이 클라우드 느낌을 얻기 위해 결과 이미지를 흐리게 하는 것은 일반적으로 매우 비용이 많이 드는 작업이었습니다.

텍스처가 없으면 클라우드가 2% 불투명도로 표시됩니다.

텍스처가 없으면 클라우드가 2% 불투명도로 표시됩니다.

가산적이고 많은 것을 갖는 것은 우리가 반복적으로 같은 픽셀을 음영, 서로의 상단에 여러 쿼드가 있다는 것을 의미합니다. 은하계 의 중심에, 같은 픽셀은 서로의 상단에 쿼드의 수백을 가지고 있으며, 이것은 전체 화면을 수행 할 때 엄청난 비용을 했다.

전체 화면 클라우드를 수행하고 흐리게 하려고 하는 것은 나쁜 생각이었을 것이므로 하드웨어가 우리를 위해 작업을 수행하도록 하기로 결정했습니다.

먼저 약간의 컨텍스트

게임에서 텍스처를 사용하는 경우 텍스처 크기는 사용하려는 영역과 거의 일치하지 않지만 다양한 종류의 텍스처 필터링을 사용하여 그래픽 카드 가져와 텍스처의 픽셀에서 원하는 색을 보간할 수 있습니다(텍스처 필터링). 관심 있는 필터링은 가장 가까운 4개의 인접 항목을 사용하여 픽셀의 값을 계산하는 쌍선형 필터링 입니다.

필터링 전 원본

필터링 후 결과

이 속성을 사용하면 텍스처를 두 배 큰 영역으로 그리려고 할 때마다 결과가 흐리게 표시됩니다.

전체 화면으로 렌더링하고 다른 항목에 지출할 수 있는 귀중한 밀리초를 잃는 대신 화면의 작은 버전으로 렌더링합니다. 그런 다음, 이 텍스처를 복사하고 2배씩 확장하면 프로세스의 콘텐츠를 흐리게 표시하면서 전체 화면으로 돌아갑니다.

x3 다시 전체 해상도로 스케일 업스케일링합니다.

x3 다시 전체 해상도로 스케일 업스케일링합니다.

이를 통해 원래 비용의 일부만 사용하여 클라우드 부분을 가져올 수 있습니다. 전체 해상도에 클라우드를 추가하는 대신 픽셀의 1/64번째만 칠하고 텍스처를 다시 전체 해상도로 늘입니다.

왼쪽, 1/8에서 전체 해상도로 업스케일 사용; 및 오른쪽, 2의 힘을 사용하여 3 업스케일로.

왼쪽, 1/8에서 전체 해상도로 업스케일 사용; 및 오른쪽, 2의 힘을 사용하여 3 업스케일로.

그래픽 카드 설정에서 4픽셀을 사용하여 더 큰 영역을 음영 처리하고 아티팩트가 나타나기 시작하므로 크기의 1/64에서 전체 크기로 이동하려고 하면 완전히 다르게 보일 수 있습니다.

그런 다음, 더 작은 카드로 전체 해상도 별을 추가하면 전체 은하계를 얻습니다.

전체 해상도 별을 사용하여 은하계 렌더링의 거의 최종 결과

셰이프가 있는 올바른 트랙에 있으면 구름 레이어를 추가하고, 임시 점을 포토샵에 그린 점과 교환하고, 색을 추가했습니다. 그 결과 은하수 갤럭시의 예술 및 엔지니어링 팀은 모두 기분이 좋았으며 CPU에 대한 부담 없이 깊이, 볼륨 및 모션이라는 목표를 달성했습니다.

우리의 마지막 은하수 은하 3D.

우리의 마지막 은하수 은하 3D.

자세히 알아보기

Galaxy Explorer 앱에 대한 코드를 오픈 소스로 제공하고 개발자가 빌드할 수 있도록 GitHub에서 사용할 수 있도록 했습니다.

Galaxy Explorer 개발 프로세스에 대해 자세히 알아보고 싶나요? Microsoft HoloLens YouTube 채널에서 이전 프로젝트 업데이트를 모두 확인하세요.

작성자 정보

책상에 있는 카림 루신의 사진 카림 루크신 은 소프트웨어 엔지니어이자 멋진 비주얼 애호가입니다. 그는 갤럭시 Explorer 그래픽 엔지니어였습니다.
예술 리드 앤디 지빗의 사진 Andy Zibits는 갤럭시 Explorer 3D 모델링 팀을 관리하고 더 많은 입자를 위해 싸웠던 아트 리드 및 우주 애호가입니다.

추가 정보