Quick Comparison
| 방식 | shader가 고르는 값 | 강점 | 제작 제약 |
|---|---|---|---|
| Texture atlas | 재계산한 atlas UV 사각형 | 제각각인 크기의 이미지 packing | padding, rotation, trim, mip bleeding 관리 |
| Texture array | UV + 정수 layer index | layer 사이 filtering이 섞이지 않고 material index가 단순 | 모든 layer의 width, height, format, mip 구성이 같아야 함 |
| 개별 texture | resource binding | streaming과 독립 품질 관리가 단순 | binding/descriptor와 batch 분할 증가 |
atlas:
one texture, many UV rectangles
array:
one texture object, many layersUV와 layer 계약
Texture atlas는 여러 작은 이미지를 하나의 큰 texture에 넣고, 각 sprite나 material이 자기 영역의 UV만 사용하도록 만드는 방식입니다. 같은 atlas를 쓰는 객체는 texture binding을 바꾸지 않아도 되므로 batching에 유리합니다.
atlas uv
u = rect.x + localU * rect.width
v = rect.y + localV * rect.heightTexture array는 여러 이미지를 같은 크기와 포맷의 layer로 저장합니다. shader는 UV와 함께 layer index를 넘겨 특정 slice를 샘플링합니다. atlas처럼 UV rectangle을 다시 계산하지 않아도 되지만, 모든 layer가 같은 해상도, format, mip 수 조건을 맞춰야 합니다. layer는 연속적인 3D 좌표처럼 이웃 layer와 bilinear filtering되지 않으므로, tile ID를 layer index로 두기 좋습니다.
mipmap과 bleeding
Atlas의 가장 흔한 문제는 경계 bleeding입니다. mipmap이나 bilinear filtering이 인접한 sprite의 픽셀을 섞어 읽으면 가장자리에 다른 이미지 색이 번집니다. 이를 줄이려면 padding, extrude border, UV inset을 사용합니다. padding은 base mip 한두 texel만의 문제가 아닙니다. 축소된 mip에서도 경계가 섞일 수 있으므로 atlas 전체의 mip chain을 생성하는 방식과 최대 sampling footprint에 맞춰 여유를 둡니다.
sprite padding
-> 가장자리 픽셀을 바깥으로 복제
-> mipmap에서 이웃 sprite 색이 섞이는 문제 완화Texture array는 layer끼리 filtering이 섞이지 않으므로 atlas bleeding이 덜합니다. 대신 서로 다른 크기의 이미지를 효율적으로 packing하는 데는 atlas가 더 유리할 수 있습니다. atlas packing이 sprite를 회전하거나 trim했다면 UV transform뿐 아니라 tangent 방향, nine-slice 경계, 원본 pivot도 asset metadata로 같이 전달해야 합니다.
선택과 batch 조건
| 상황 | 선택 |
|---|---|
| 2D sprite를 많이 그림 | texture atlas |
| 같은 크기 tile이 많음 | texture array |
| material별 이미지 크기가 제각각 | atlas 또는 개별 texture |
| mip bleeding이 문제 | padding 또는 texture array |
| draw call을 줄이고 싶음 | atlas/array로 binding 통합 |
| runtime streaming이 중요 | 개별 texture 또는 streaming 단위를 분리한 array/atlas 검토 |
Atlas와 array는 texture binding 비용을 줄이는 장치입니다. fragment shader의 샘플 수나 texture bandwidth 자체를 없애지는 않습니다. 또한 texture를 하나로 합쳐도 shader, blend/depth state, render target, per-object data가 달라지면 여전히 같은 draw로 묶을 수 없습니다.
| asset 특성 | 먼저 정할 것 | 선택 기준 |
|---|---|---|
| UI/sprite가 다양한 크기 | packing 크기, padding, rotation 허용 | atlas가 공간 효율이 좋음 |
| terrain tile 또는 decal이 균일한 크기 | layer 수와 고정 resolution | array가 UV와 mip 관리에 유리 |
| 하나만 매우 큰 4K image | 전체 layer resolution 낭비 | 별도 texture 또는 다른 group |
| tile가 자주 교체됨 | resource update와 streaming lifetime | 전체 atlas 재packing 비용을 측정 |
확인할 오류
Texture atlas를 쓰면 UV가 원본 이미지 기준이 아니라 atlas 영역 기준으로 바뀝니다. sprite trim, rotation packing, padding이 섞이면 UV 생성과 shader sampling 규칙을 함께 관리해야 합니다. Texture array는 layer 크기와 format이 같아야 하므로 다양한 해상도의 아트 리소스를 그대로 넣기 어렵습니다.
| 증상 | 먼저 확인할 값 |
|---|---|
| 멀리서 다른 sprite 색이 가장자리에 번짐 | atlas padding, extruded border, generated mip, UV inset |
| 일부 sprite가 회전되거나 잘림 | packing rotation/trim metadata와 UV transform |
| array 생성이 실패하거나 layer가 검게 보임 | layer width/height/format/mip count와 index 범위 |
| batch가 기대만큼 안 줄음 | texture 외 PSO, blend, depth, mesh, instance data 분할 |
참고 링크
2 sources