[Unity] 렌더 큐

muchan
muchan
∙∙조회 13
[Unity] 렌더 큐

오늘의 일화

진행중인 프로젝트에서 배경으로 물 shader를 깔아두고 그 위에 소용돌이 오브젝트를 얹어놨는데, 특정 상황에서 소용돌이가 물 뒤로 쏙 가려지는 현상이 있었다. 분명 위에 있어야 하는데 특정 상황에선 물에 먹혀버린 것이다.

원래는 소용돌이 위에 마우스를 올리면 정보가 표시되는데

이런식으로 특정 상황에 소용돌이가 물 뒤로 가려져 안보이는 현상이 생겼다.(실제로는 소용돌이가 있어서 정보가 표시됨)

이것저것 만지다가 물 shader의 SubShader Tags를 이렇게 바꿨더니 해결됐다. (강사님이 해결해주셨습니다...)

shaderlab
Tags
{
    "RenderPipeline" = "Universal"
    "Queue" = "Transparent-100"
}

Transparent가 기본 2000+1000 = 3000인데, 여기에 -100을 붙여서 2900으로 당겼다. 즉 물을 다른 투명 오브젝트들보다 먼저 그리게 만들었고 그 뒤로 소용돌이가 안 가려지게 됐다

렌더 큐란?

유니티는 화면에 오브젝트들을 그릴 때 아무 순서로나 막 그리는 게 아니라 정해진 순서(큐)대로 그린다.
이 순서를 정하는 게 렌더 큐(Render Queue)라는 것이다.

큐는 정수값으로 표현되고 값이 작을수록 먼저 그린다. 유니티엔 이름 붙은 기본 큐들이 있다.

이름값용도
Background1000스카이박스 같은 제일 뒤 배경
Geometry2000일반 불투명(opaque) 오브젝트
AlphaTest2450알파 컷아웃(잎사귀, 풀 같은)
Transparent3000반투명 오브젝트 (유리, 물, 파티클)
Overlay4000렌즈 플레어, UI 등 제일 앞

값이 작은 것부터 Background → Geometry → AlphaTest → Transparent → Overlay 순서로 화면에 쌓여 그려진다.

불투명 vs 투명, 정렬 방식이 다르다

불투명(Geometry) 오브젝트는 그리는 순서가 화면 결과에 큰 영향을 안 준다. 왜냐면 깊이 버퍼(Depth Buffer, Z-Buffer) 로 픽셀 단위 앞뒤를 판정하기 때문이다. 각 픽셀마다 "지금까지 그려진 것 중 제일 앞에 있는 깊이값"을 기록해두고, 새로 그리려는 픽셀이 그보다 뒤면 버린다(ZTest). 그래서 순서 뒤죽박죽이어도 알아서 앞에 놈이 이긴다. 오히려 유니티는 성능을 위해 앞→뒤(front-to-back) 로 그려서 뒤에 가려질 픽셀 연산을 건너뛴다.

투명(Transparent) 오브젝트는 얘기가 다르다. 반투명은 뒤에 있는 색과 섞어야(blending) 하기 때문에, 뒤에 있는 게 먼저 그려져 있어야 제대로 섞인다. 그래서 투명 오브젝트는 보통 ZWrite Off로 깊이 기록을 끄고, 뒤→앞(back-to-front) 순서로 그린다. 이 정렬은 오브젝트의 중심점 기준 카메라 거리로 이뤄진다.

문제는 여기서 터진다. 투명 오브젝트끼리의 정렬은 픽셀 단위가 아니라 오브젝트(중심점) 단위라서, 두 투명 오브젝트가 서로 겹치거나 큰 평면이 얽히면 정렬이 애매해지고 앞뒤가 뒤집혀 보이는 현상이 생기는 것이다.

그래서 내 소용돌이가 왜 가려졌나

물이랑 소용돌이 둘 다 Transparent(3000)에 있었다. 둘이 같은 큐에 있으니 유니티는 카메라 거리로 누굴 먼저 그릴지 판단하는데, 이 판단이 오브젝트 중심점 기준이라 상황(카메라 각도, 두 오브젝트 위치 관계)에 따라 물이 소용돌이보다 뒤로 정렬돼버리는 순간이 생기는 것이었다. 그 순간 물이 나중에 그려지면서 소용돌이를 덮어버리고 특정 상황에 가려지는 현상이 발생하게 된 것이다.

Queue = "Transparent-100"으로 물을 2900으로 설정하니 물은 무조건 소용돌이(3000)보다 먼저 그려지게 했다. 큐 값 자체가 다르면 유니티는 거리 정렬 이전에 큐 순서를 우선하니까, 카메라 각도가 어떻든 물 → 소용돌이 순서가 고정된다.

정리하면:

  • 원래: 물, 소용돌이 둘 다 3000 → 거리 정렬에 맡김 → 불안정
  • 수정: 물 2900, 소용돌이 3000 → 순서 고정 → 안정

Transparent+N / Transparent-N 문법

큐 이름 뒤에 오프셋을 붙일 수 있다.

shaderlab
"Queue" = "Transparent-100"   // 3000 - 100 = 2900, 다른 투명보다 먼저
"Queue" = "Transparent+1"     // 3000 + 1 = 3001, 다른 투명보다 나중
"Queue" = "Geometry+1"        // 2001

머티리얼 인스펙터에서 renderQueue를 직접 숫자로 박아도 되고, 셰이더에 명시해도 된다.

참고로 큐 값이 2500 이하면 불투명 취급, 2501 이상이면 투명 취급으로 URP가 렌더링 경로를 분기함. 2900은 여전히 투명 구간이라 블렌딩/투명 처리는 그대로 유지됨.

배운 것 / 주의할 점

  • 투명 오브젝트 앞뒤가 상황 따라 뒤집힌다 → 큐 값을 명시적으로 분리해서 순서를 고정하는 게 정석 해법 중 하나.
  • 다만 큐 조정은 국소적 해결책임. 소용돌이가 다른 투명 오브젝트랑 또 겹치면 그놈이랑도 순서 정리를 해줘야 함. 씬에 투명이 많아지면 큐 설계를 아예 규칙으로 정해두는 게 편함.
  • 근본 원인이 "투명끼리 정렬은 오브젝트 단위"라는 한계라서, 큐로 못 잡는 케이스(하나의 투명 메시가 자기 자신과 겹치는 경우 등)는 ZWrite On + 별도 패스 같은 다른 처방이 필요함. 이번 건은 오브젝트가 분리돼 있어서 큐 하나로 깔끔하게 해결됐음.