
AI 3D 텍스처 생성 툴로 구현하는 동적 UV 맵핑: Unity 셰이더 실전 가이드
AI 3D 텍스처 생성 툴에서 만든 PBR 맵을 Unity URP 셰이더에 연결하고 트라이플래너·마스크·월드 좌표 기반 동적 UV 맵핑으로 반복과 이음새를 줄이는 방법을 정리합니다.
핵심 요약
AI 3D 텍스처 생성 툴은 Base Color, Normal, Roughness, Height 같은 PBR 맵을 빠르게 만들지만 모델 UV의 반복과 이음새까지 자동으로 해결하지는 않는다. Unity URP에서는 메시 UV, 월드 좌표, 마스크를 함께 사용해 영역별 타일링을 바꾸고 트라이플래너 투영을 적용하면 적은 셰이더 비용으로 표면 반복을 크게 줄일 수 있다.
AI 생성 PBR 텍스처와 UV 맵은 무엇이 다른가?
AI 텍스처 생성 툴은 보통 재질 이미지를 만들거나 텍스트 프롬프트로 PBR 채널을 추정한다. 반면 UV 맵은 3D 메시의 표면 좌표를 2D 텍스처 좌표에 대응시키는 데이터다. 따라서 AI가 만든 고품질 텍스처도 UV 배치가 나쁘거나 타일링이 과하면 같은 무늬가 반복되어 보인다.
| 요소 | 역할 | 흔한 문제 | 대응 방법 |
|---|---|---|---|
| Base Color | 색상과 알베도 | 동일 무늬 반복 | UV 오프셋, 마스크 혼합 |
| Normal | 미세 법선 변화 | 투영 축 전환 시 방향 오류 | 축별 법선 재구성 |
| Roughness | 반사 흐림 정도 | 채널 해석 불일치 | 툴 내보내기 설정 확인 |
| Height | 높이 정보 | 과한 패럴랙스 비용 | 근접 오브젝트에만 사용 |
| UV0 | 메시 기본 좌표 | 이음새와 늘어짐 | 트라이플래너 보조 투영 |
AI 생성 결과를 바로 게임에 넣기 전에 색 공간도 확인해야 한다. Unity에서는 Base Color는 sRGB, Normal·Roughness·Mask·Height는 Linear로 가져온다. Normal Map은 Texture Import Settings에서 Texture Type: Normal map으로 지정한다.

동적 UV 맵핑은 왜 필요한가?
정적인 UV는 아티스트가 언랩한 좌표를 그대로 사용한다. 이는 베이크 텍스처와 고유 디테일에 적합하지만 넓은 벽·지형·절차적 메시에는 반복 패턴과 UV 이음새가 눈에 띈다.
동적 UV 맵핑은 셰이더에서 좌표를 변환하거나 선택하는 방식이다. 대표적으로 다음 세 가지를 조합한다.
UV0에 타일링과 오프셋을 적용한다.- 월드 좌표를 사용해 큰 스케일의 보조 텍스처를 섞는다.
- 법선 방향에 따라 XY, XZ, YZ 평면으로 투영하는 트라이플래너 맵핑을 적용한다.
기본 UV 변환은 다음 식으로 표현할 수 있다.
여기서 는 타일링, 는 오프셋이다. 오프셋을 오브젝트별 난수로 바꾸면 같은 머티리얼을 공유해도 반복 위치가 덜 드러난다.
Unity URP에서 동적 UV 맵핑을 어떻게 구현할까?
Step 1. AI 텍스처를 게임용 PBR 입력으로 정리한다
먼저 텍스처 생성 툴에서 같은 재질군으로 출력한 맵을 준비한다. 해상도는 카메라 거리와 플랫폼 예산에 맞추고 무조건 4K를 쓰지 않는다. 일반적인 소품은 1K~2K로 시작해 프로파일링 후 올리는 편이 안전하다.
- Base Color: 알파가 필요하지 않으면 압축 포맷을 우선 적용한다.
- Normal: 압축 후 세부가 뭉개지는지 확인한다.
- Roughness: Unity의 Smoothness 입력은 일반적으로 Roughness와 반대 방향이다.
- Mask: 눈·먼지·마모 영역을 제어할 흑백 마스크를 별도로 둔다.
URP Lit 셰이더를 Shader Graph로 확장할 수 있지만 좌표 계산을 명확히 검증하려면 먼저 작은 HLSL 함수로 시작하는 편이 좋다.
Step 2. 월드 좌표 트라이플래너 가중치를 계산한다
트라이플래너는 표면 법선의 절댓값을 이용해 각 투영축의 비중을 구한다. 예를 들어 위를 향한 면은 XZ 투영을 더 많이 사용한다.
은 월드 공간 법선이고 는 축 경계를 얼마나 또렷하게 만들지 정하는 blendSharpness다. 값이 높을수록 경계가 선명하지만 부드러운 전환은 줄어든다. 보통 2~8 범위에서 시작하면 된다.
float3 TriplanarWeights(float3 normalWS, float blendSharpness)
{
float3 weights = pow(abs(normalWS), blendSharpness);
return weights / max(weights.x + weights.y + weights.z, 0.0001);
}
float3 SampleTriplanarBaseColor(
TEXTURE2D_PARAM(baseMap, samplerBaseMap),
float3 positionWS,
float3 normalWS,
float tiling,
float blendSharpness)
{
float3 weights = TriplanarWeights(normalWS, blendSharpness);
float2 uvX = positionWS.zy * tiling;
float2 uvY = positionWS.xz * tiling;
float2 uvZ = positionWS.xy * tiling;
float3 x = SAMPLE_TEXTURE2D(baseMap, samplerBaseMap, uvX).rgb;
float3 y = SAMPLE_TEXTURE2D(baseMap, samplerBaseMap, uvY).rgb;
float3 z = SAMPLE_TEXTURE2D(baseMap, samplerBaseMap, uvZ).rgb;
return x * weights.x + y * weights.y + z * weights.z;
}
이 코드는 색상 맵용 최소 예시다. Normal Map까지 트라이플래너로 처리할 때는 각 축의 탄젠트 공간 법선을 월드 공간으로 재구성해야 한다. Base Color 샘플처럼 단순 혼합하면 조명 방향이 틀어질 수 있다.

Step 3. 마스크로 기본 UV와 트라이플래너를 제한한다
트라이플래너를 모델 전체에 적용하면 비용이 늘고 의도적으로 그린 데칼이나 고유 UV 디테일도 흐려질 수 있다. Mask Map 또는 버텍스 컬러를 사용해 필요한 영역에서만 혼합한다.
float mask = SAMPLE_TEXTURE2D(_DynamicUVMask, sampler_DynamicUVMask, input.uv).r;
float3 regularColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv * _UVTiling).rgb;
float3 triplanarColor = SampleTriplanarBaseColor(
TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap),
input.positionWS,
input.normalWS,
_WorldTiling,
_BlendSharpness);
float3 finalColor = lerp(regularColor, triplanarColor, mask);
이 방식은 캐릭터 얼굴처럼 UV가 중요한 영역에는 기존 텍스처를 유지하고 갑옷의 넓은 금속판이나 바위 표면처럼 반복이 드러나는 곳만 동적 투영으로 보완하기 좋다.
flowchart LR
A[AI 생성 PBR 맵] --> B[Unity Import 설정]
B --> C[UV0 기본 샘플]
B --> D[월드 좌표 트라이플래너 샘플]
E[마스크 또는 버텍스 컬러] --> F[lerp 혼합]
C --> F
D --> F
F --> G[URP Lit 조명 계산]
UV 반복을 줄이는 실전 조정값
| 파라미터 | 시작값 | 조정 효과 | 주의점 |
|---|---|---|---|
_UVTiling | 1.0 | 기존 UV 반복 밀도 | 너무 높으면 모아레 발생 |
_WorldTiling | 0.1~1.0 | 월드 투영 재질 크기 | 오브젝트 스케일과 함께 확인 |
_BlendSharpness | 4.0 | 축 전환의 선명도 | 과하면 투영 경계가 보임 |
mask | 0.0~1.0 | 동적 UV 적용 범위 | 페더링으로 경계 완화 |
| Macro Texture Tiling | 기본 타일링의 1/4 | 큰 색 변화 추가 | 디테일 맵과 대비 유지 |
반복을 더 숨기고 싶다면 큰 스케일의 저주파 Macro Color 텍스처를 추가로 곱하거나 혼합한다. 이때 Macro 텍스처는 세부 재질을 대체하는 용도가 아니라 넓은 면의 색 변화를 만드는 용도다.
성능과 품질은 어떻게 균형을 맞출까?
트라이플래너는 일반 UV 샘플보다 기본적으로 세 축의 텍스처 샘플이 필요하다. Base Color, Normal, Mask를 모두 트라이플래너로 샘플하면 프래그먼트 비용이 빠르게 증가한다.
| 상황 | 권장 방식 |
|---|---|
| 모바일 또는 대량 배치 소품 | UV0 타일링 + 오브젝트별 오프셋 |
| 중거리 환경 에셋 | Base Color만 트라이플래너, Normal은 UV0 |
| 근거리 영웅 환경 에셋 | Base Color와 Normal 트라이플래너 + 마스크 제한 |
| 지형 | 엔진 지형 시스템 또는 레이어드 셰이더 우선 검토 |
먼저 Frame Debugger와 GPU Profiler로 해당 머티리얼의 드로우콜과 프래그먼트 비용을 확인한다. 품질 문제가 없는 플랫폼에서는 blendSharpness를 올리는 것보다 마스크 범위를 줄이는 편이 더 효율적인 경우가 많다.
자주 묻는 질문 (FAQ)
AI 생성 텍스처만으로 UV 언랩을 생략할 수 있나?
대부분의 게임 에셋에서는 어렵다. 트라이플래너는 넓은 표면의 반복과 이음새를 보완하지만 베이크 AO, 고유 문양, 데칼, 캐릭터 얼굴에는 정교한 UV가 여전히 필요하다.
트라이플래너 Normal Map이 이상하게 보이는 이유는 무엇인가?
Normal Map은 탄젠트 공간 기준 데이터이기 때문이다. 각 투영축의 방향에 맞춰 월드 공간 법선으로 변환한 뒤 혼합해야 한다. 단순 RGB 혼합은 색상 맵에는 가능하지만 법선 맵에는 부정확하다.
오브젝트가 움직이면 월드 좌표 텍스처도 미끄러지나?
그렇다. 월드 좌표를 그대로 쓰면 오브젝트가 이동할 때 텍스처가 공간에 고정된 것처럼 보인다. 이동 오브젝트에는 오브젝트 공간 좌표를 사용하거나 필요한 경우에만 월드 좌표를 선택한다.
정리
AI 3D 텍스처 생성 툴은 재질 제작 시간을 줄여 주지만 최종 품질은 UV와 셰이더 좌표 처리에서 결정된다. 기본 UV를 버리지 말고 마스크로 필요한 영역에만 월드 좌표 트라이플래너를 섞으면 이음새와 반복을 줄이면서도 머티리얼 비용을 관리할 수 있다.


