3D 메시의 각 버텍스에 2D 텍스처 좌표(U, V)를 할당하는 것이다.
3D 메시에 텍스처를 어떻게 입히는가?
- 지구본과 세계 지도로 비유가 가능하다
- 지구본 (3D 구) 껍데기를 잘라서 펼치면 평평한 세계 지도 (2D)
3D 메시 -> UV 언래핑 -> 2D UV 맵
각 버텍스에 UV 좌표 (U, V) 할당한다
U : 가로 방향 (0.0 ~ 1.0)
V : 세로 방향 (0.0 ~ 1.0)
텍스처의 어느 픽셀이 이 버텍스에 대응하는지 정의한다.
왜 U, V인가?
X, Y, Z는 이미 3D 공간 좌표에 쓰이고 있기에 겹치지 않게 하기 위해 U, V로 명명하였다
UV 좌표계 - API별 차이
OpenGL/ Vulkan / Metal
- (0, 0) = 왼쪽 아래, (1, 1) = 오른쪽 위이며 V축이 위로 향한다
DirectX / UE5 / Unity
- (0, 0) = 왼쪽 위, (1, 1) = 오른쪽 아래 V축이 아래로 향한다
이 차이가 텍스처가 뒤집히는 원인이다
Blender(OpenGL) -> UE5(DX) 임포트 시 V 채널 반전 필요한 경우가 생기는 이유이다.
UV 언래핑의 종류
박스 매핑 (Box/Cubic Mapping)
- 6방향에서 투영한다
- 단순한 박스형 오브젝트에 적합하다
- 이음새(Seam)이 많이 생긴다
원통형 매핑 (Cylindrical Mapping)
- 원통으로 감싸서 투영한다
- 기둥, 나무, 캐릭터 팔다리에 적합하다
구형 매핑 (Spherical Mapping)
- 구로 감싸서 투영한다
- 천체, 눈알, 구형 오브젝트에 적합하다
수동 언래핑 (Manual UV Unwrapping)
- 아티스트가 직접 골라서 펼치기에 가장 정교한 결과를 얻을 수 있다
- 캐릭터, 주요 프롭에 사용된다
- Blender, Maya, 3ds Max에서 작업된다
라이트맵 UV (Lightmap UV)
- 스태틱 라이팅 베이킹 전용 UV
- UV 채널 0: 텍스처용
- UV 채널 1: 라이트맵용 (겹치면 안된다)
- UE5에서는 반드시 분리해야한다
UV 언래핑의 핵심 규칙
1. 겹치지 않아야 한다 (Lightmap UV)
- UV 아일랜드가 겹치면 (텍스처 UV에서는 의도적으로 가능하다) 라이트맵 베이킹 시 겹친 부분 조명이 섞인다 -> 조명 아티팩트 발생
- UE5에서 Generate Lightmap UVs 옵션이 이를 자동으로 처리해준다
2. 이음새(Seam)를 눈에 안 보이는 곳에 적용한다
- 3D를 2D로 펼칠 때 반드시 어딘가를 잘라야 한다. (잘린 경계를 Seam이라 한다)
- 텍스처의 불연속점이 될 수 있다 -> 겨드랑이, 뒤쪽, 헤어라인 등 안보이는 곳에 배치한다.
3. 텍셀 밀도 균일하게 (Texel Density)
- UV 아일랜드 크기 = 텍스처 해상도 할당량이다
- 얼굴 UV가 작으면 얼굴 텍스처가 흐릿해진다
- UV 아일랜드 크기를 실제 메시 면적에 비례하게 한다.
4. 스트레칭 최소화
- UV를 너무 늘리면 텍스처가 늘어난 것처럼 보인다.
- Checker 텍스처로 검증 가능하다
- 정사각형 체커가 찌그러지면 스트레칭 발생했다는 것이다.
버텍스 데이터에서 GPU까지의 흐름
// UV가 GPU에서 전달되는 과정
// 메시 버텍스 데이터 (CPU)
struct Vertex {
float3 position; // 3D 위치
float3 normal; // 법선
float2 uv0; // UV 채널 0 (텍스처용)
float2 uv1; // UV 채널 1 (라이트맵용)
};
// VBO로 GPU 메모리에 업로드. 각 버텍스의 UV 좌표가 GPU로 전달된다
// 버텍스 셰이더 - UV를 픽셀 셰이더로 전달
PixelInput VS(VertexInput input){
PixelInput output;
output.position = mul(float4(input.position,1), mvp);
output.uv0 = input.uv0; // 보간되어 픽셀 셰이더로
output.uv1 = input.uv1;
return output;
}
// 픽셀 셰이더 - UV로 텍스처 샘플링
float4 PS(PixelInput input) : SV_TARGET {
// UV 좌표로 텍스처에서 색상 읽기
float4 color = AlbedoTex.Sample(Samp, input.uv0);
float3 normal = NormalTex.Sample(Samp, input.uv0).rgb;
float4 light = LightMap.Sample(Samp, input.uv1);
return color * light;
}
// 버텍스 사이의 UV는 래스터화 단계에서 보간된다.
// 버텍스 3개의 UV -> 삼각형 내부 픽셀의 UV 자동 계산된다
UV 타일링과 오프셋
UV 범위가 0~1을 벗어날 경우
- 기본 동작: Repeat (타일링)
- UV = 1.5 -> 0.5와 동일 , UV = 2.3 -> 0.3과 동일 ( 반복 )
- 작은 텍스처를 반복해서 넓은 바닥 표현이 가능하다
바닥 텍스처 UV 스케일 조정
- UVScale = 10.0
- TexCoord * 10 -> 텍스처가 10x10으로 타일링된다.
- 작은 텍스처로 넓은 바닥을 커버할 수 있다.
클램프 (Clamp) 모드
- UV = 1.5 -> 1.0으로 고정한다.
- 반복 없이 가장자리 색상을 늘린다.
UE5 머터리얼
- TextureCoordinate 노드: UV 스케일/오프셋 조정
- Texture Sample -> UV 핀에 연결
- Tiling 방식은 Texture Asset의 X/Y Tiling 설정
UV 채널 (UE5에서 자주 생기는 문제)
채널 0 (UV0) : 기본 텍스처 UV
- Albedo, Normal, Roughness 등이 있다
- 타일링이 가능하고 겹쳐도 된다
채널 1 (UV1) : 라이트맵 UV
- Static Lighting 베이킹용으로 반드시 겹치면 안된다.
- 0 ~ 1 범위 안에 전부 들어와야 한다.
채널 2+ : 특수 용도
- 텍스처 레이어링
- 데칼 UV
- 버텍스 색상 대체
UE5에서 Lightmap UV 생성
- Static Mesh Editor -> Build Settings -> Generate Lightmap UVs : ON -> Min Lightmap Resolution 설정 -> 자동으로 UV1 생성.
문제 상황
- "Overlapping UVs" 경고 -> UV1 채널에 겹친 아일랜드가 있다. -> Static Lighting 품질 저하 -> 자동 생성 또는 수동 언래핑을 통해 해결한다.
Blender -> UE5 UV 임포트 워크플로
Blender에서 UV 설정
UV Editor에서 언래핑
- UV Map 0: "UVMap" (텍스처용)
- UV Map 1: "LightmapUV" (베이킹용)
FBX 익스포트 설정
- Apply Modifiers : ON
- UV Maps 내보내기 선택
UE5 임포트 설정
- Generate Lightmap UVs : 이미 Blender에서 만든 경우 OFF, 없으면 ON (자동 생성)
일반적으로 생기는 문제들
- 텍스처가 뒤집힌다.
-> OpenGL(Blender) vs DX(UE5) V축 차이
-> Blender에서 V 반전 후 익스포트
- UV 스케일이 달라진다.
-> Blender 단위와 UE5 단위 차이
-> Scale 적용(Ctrl + A) 후 익스포트
- 라이트맵 이음새에 빛 새는 현상
-> UV1 아일랜드 간격 부족
-> Light Map Resolution 높이기
연결되는 단어들
- 텍셀 밀도 (Texel Density) : 메시 표면 단위 면적당 텍스처 픽셀 수. 균일해야 해상도가 일관된게 보인다.
- UV 아일랜드 (UV Island) : UV 공간에서 연결된 UV 조각. 이음새로 분리된 각 조각이 하나의 아일랜드다.
- 이음새 (Seam) : 3D 메시를 2D로 펼칠 때 잘리는 경계선. 텍스처 불연속이 생길 수 있어서 안보이는 곳에 배치한다.
- UDIM : UV 공간을 여러 타일로 확장하는 방식으로 고 해상도 캐릭터 텍스처에서 사용한다. UE5에서 지원한다.
'Word' 카테고리의 다른 글
| 텍스처 샘플링 (Texture Sampling) (0) | 2026.07.28 |
|---|---|
| 오버드로우 (Overdraw) (0) | 2026.07.27 |
| 노멀 맵 (Normal Map) (0) | 2026.07.21 |
| 컴퓨트 셰이더 ( Compute Shader ) (0) | 2026.07.20 |
| HLSL/GLSL (0) | 2026.07.16 |
