선생님: 오늘은 Unity의 머티리얼이 렌더링 성능에 미치는 영향에 대해 이야기해 보려고 해요. 우선 머티리얼이 무엇인지 알고 있나요?

학생 1: 머티리얼은 나무나 금속처럼 보이게 하기 위해 오브젝트에 입히는 텍스처 같은 건가요?

선생님: 네, 그거예요. Unity의 머티리얼은 셰이더를 둘러싼 컨테이너로, GPU가 들어오는 버텍스 및 텍스처 데이터를 렌더링하는 방법을 정의하는 프로그램이에요. 셰이더는 그 자체로는 가치 있는 작업을 수행하는 데 필요한 정보를 가지고 있지 않습니다. 따라서 디퓨즈 텍스처, 노멀 맵, 조명 정보와 같은 입력이 있어야 합니다. 그리고 입력된 데이터를 렌더링하기 위해서 어떤 렌더 상태(Render State) 변수를 설정해야 하는지를 지정해야 해요.

Unity의 셰이더란?

학생 2: 왜 셰이더라고 하나요?

선생님: 셰이더는 원래 오브젝트의 조명과 음영을 처리하기 위해 만들어진 것이지만, 그 이후로 그 용도가 엄청나게 확장되었고 지금은 보다 일반적인 목적으로 사용되고 있습니다.

학생 3: 그럼 모든 머티리얼에는 셰이더가 있어야 하나요?

선생님: 네, 모든 머티리얼에는 셰이더가 있어야 해요. 머티리얼이 할당되지 않은 채 씬에 새로 추가된 메시에도 기본(숨겨진) 머티리얼이 자동으로 할당되며, 기본 디퓨즈 셰이더와 흰색 색상을 갖게 돼요.

학생 4: 하나의 메시에서 다수의 셰이더를 사용할 수 있나요?

선생님: 아니요, 단일 머티리얼은 단일 셰이더만 지원할 수 있어요. 동일한 메시에서 여러 셰이더를 사용하려면 동일한 메시의 다른 부분에 별도의 머티리얼을 할당해야 해요.

셰이더의 목적은 원래보다 크게 확장되었다

머터리얼이 렌더링 성능에 미치는 영향

학생 5: 머티리얼은 렌더링 성능에 어떤 영향을 미치나요?

교사: 렌더링 상태가 변경되는 빈도를 최소화하려면 씬에서 사용하는 머티리얼의 수를 줄이면 돼요. 이렇게 하면 CPU가 각 프레임 동안 명령을 생성하고 GPU에 전송하는 데 소요되는 시간이 단축되고, 따라서 GPU가 상태 변경을 중지했다가 다시 동기화할 필요가 없어집니다.

학생 6: 예를 들어 설명해 주시겠어요?

선생님: 네, 큐브 4개와 구체 4개가 있는 단방향 조명이 있고 각 오브젝트에 고유한 머티리얼, 위치, 회전, 스케일이 있는 씬을 만들어 볼까요? 현재 씬을 렌더링하는 데 사용된 배치가 총 9개입니다. 이 뷰는 씬의 배경을 렌더링하기 위해 한 개의 배치(스카이박스 또는 단색으로 설정할 수 있죠)를 소비합니다. 나머지 8개의 배치는 8개의 오브젝트를 그리는 데 사용되어요. 각각의 오브젝트에는 고유한 머티리얼이 있고 각 오브젝트마다 서로 다른 렌더링 상태가 필요합니다. 따라서 각 오브젝트에는 각각 별도의 드로우 콜이 필요해요.

드로우 콜 횟수 줄이기

학생 7: 드로우 콜 횟수를 줄이려면 어떻게 해야 하나요?

선생님: 사용하는 머티리얼의 수를 줄이면 되겠지만 그렇다고 모든 오브젝트가 동일한 머티리얼을 사용하도록 설정하면 아무 소용이 없겠죠. 렌더링 파이프라인은 똑똑하지 않기 때문에 완전히 동일한 렌더 상태 값을 겹쳐쓰고 같은 메시를 반복해서 렌더링하도록 요청할 수 없습니다.

학생 8: 동적 배칭과 정적 배칭을 사용하면 효과가 있을까요?

선생님: 동적 배칭과 정적 배칭은 모두 현재 뷰의 모든 오브젝트를 렌더링하는 데 필요한 드로우 호출 횟수를 줄이는 방법입니다. 동적 배칭은 여러 개의 작은 메쉬를 큰 메쉬로 그룹화하여 한 번의 드로우 콜로 렌더링할 수 있도록 하는 런타임 최적화의 방법입니다. 정적 배칭은 작은 메시를 하나의 큰 메시로 구워 단일 드로우 콜에서 렌더링할 수 있도록 하는 에디터 타임 최적화입니다. 이에 대해서는 다음에 다시 살펴 보도록 하지요.

참고한 도서: Unity Game Optimization ,Third Edition

추천 학습 자료