본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 15. 04:08

로컬 3D 생성의 패권 교체? Hunyuan3D를 포기하고 Microsoft의 「Trellis.2 4B」로 갈아탄 이야기

요약

게임 캐릭터 제작을 위해 Hunyuan3D 대신 Microsoft의 Trellis.2 4B 모델을 도입하여 3D 생성 파이프라인을 개선한 사례를 다룹니다. 기존 모델의 메쉬 융합 및 텍스처 품질 문제를 분석하고, 새로운 모델을 통한 해결 과정을 설명합니다.

핵심 포인트

  • Hunyuan3D의 메쉬 융합 문제로 인한 리깅 및 파츠 분할의 어려움 분석
  • Microsoft Trellis.2 4B 모델을 통한 고품질 3D 생성 결과 확인
  • ARM 환경에서의 모델 이식 및 텍스처 베이크 공정 최적화 시도

[!IMPORTANT]

이 기사는 AI(Antigravity / Gemini가 초안 작성, Claude Code가 가필 및 기술 검증)에 의해 작성되었으며, Qiita API를 통해 자동 게시되었습니다. 기재된 오류나 코드는 실제 작업 로그에서 전재하였습니다.

개인 개발 중인 게임(Lost Historia)에서 AI를 사용한 「이미지 한 장으로부터 적 캐릭터를 3D화하는 파이프라인」을 구축하고 있습니다.

지난 기사에서는 「2D 이미지 상태로 부위를 분할하여 Spine으로 움직이는 접근 방식은 실패했기 때문에, Hunyuan3D를 사용하여 3D 메쉬(Mesh)화로 방침을 전환했다」는 이야기를 정리했습니다.

하지만 실제로 Hunyuan3D를 사용하여 본격적인 파이프라인(자동 리깅(Rigging), 텍스처의 멀티뷰(Multi-view)화, 파츠 분할 등)을 구축한 결과, 품질의 벽에 부딪혔습니다. 대증요법을 거듭하여 「멀리서 보면 고블린」 수준까지는 도달했으나, 제품 레벨에는 미치지 못했습니다.

그러던 중 시도해 본 Microsoft의 최신 오픈 모델 **「Trellis.2 (4B)」**가 지금까지의 고생을 단번에 과거로 만들어버릴 정도의 품질이었습니다. 이번에는 Hunyuan3D에서 직면했던 과제, ARM 환경(DGX Spark 계열)으로의 Trellis.2 이식 전투의 실록, 그리고 실제 생성 결과를 정리합니다.

소재는 시종일관 이 이미지 한 장입니다. 게임의 적 캐릭터 「고블린」의 컨셉 아트(투명 PNG)를 각 모델에 동일한 조건으로 입력하고 있습니다.

Hunyuan3D-2는 강력한 모델이지만, 게임의 양산 파이프라인에組み込으려 했을 때 「3가지 문제」가 드러났습니다. 중요한 점은, 모두 생성 직후가 아니라 「움직이려고 시도하는 순간」에 발각된다는 것입니다.

Hunyuan3D가 생성하는 모델은 팔·무기·몸통이 물리적으로 융합된 1개의 메쉬입니다. 여기에 Blender의 자동 웨이트(Bone Heat)를 시도하면, 메쉬의 상태에 따라 모든 본(Bone)에서 실패합니다 (제 환경에서는 UV 전개로 정점(Vertex)을 분할한 메쉬에 대해 웨이트 부여 수가 0/15915라는 완패 로그가 남아 있습니다).

거리 기반의 결정론적 웨이트를 직접 제작하여 매달렸지만, 이번에는 「무기가 그립 부분에서 꺾인다」, 「무기의 포착 범위가 허벅지를 포함하여 다리가 굽는다」라는 또 다른 파탄이 발생합니다. 강체(Rigid body)여야 하는 무기에 느슨한 웨이트 구배를 주어서는 안 된다, 무기와 다리의 깊이를 게이트로 분리한다 등 대처법은 쌓여가지만, 이는 부위가 나누어져 있지 않은 것에 대한 대증요법일 뿐이었습니다.

「융합되어 있다면, 2D 부위 마스크(SAM 계열로 작성 완료)를 사용하여 3D 메쉬를 복셀(Voxel) 단위로 부위 분할하면 된다」고 생각했습니다. 라벨링 자체는 작동했지만, 생성된 무구한 입체를 잘라내면 각 파츠는 **단면이 평탄한 「퍼즐 조각 같은 파편」**이 됩니다. 그 자체로 완결된 형태(완전한 머리, 완전한 팔)가 아니기 때문에, 관절을 굽히는 순간 절단면이 노출됩니다.

Hunyuan3D의 텍스처 생성(Paint)은 커스텀 CUDA 확장(custom_rasterizer)의 빌드가 필요하며, 제 ARM 환경에서는 빌드할 수 없어 원화를 정면에서 평면 투영하여 베이크(Bake)하는 방식으로 대신하고 있었습니다. 정면은 원화와 일치하여 깨끗한 반면, 모션에서 노출되는 측면·배면·안쪽 다리에는 「정면 그림의 늘어남」밖에 남지 않습니다.

멀티뷰 이미지를 생성하여 텍스처를 블렌딩(Blending)하는 공정(ControlNet depth 구속으로 측면·배면 뷰를 안정적으로 생성 → 법선 가중치로 구워내기)까지 직접 제작하여 개선은 했지만, 공정이 점점 길어졌습니다.

참고로 직접 제작한 멀티뷰 공정은 다음과 같은 구성이었습니다. 러프 메쉬의 depth를 ControlNet의 구속으로 설정함으로써 「방향 오류·다른 캐릭터화」는 0으로 만들 수 있었습니다 (13장을 생성하여 전승). 하지만 이것을 적 캐릭터 전 종에 대해 돌릴 것인가... 하는 양산 비용이 무겁게 다가옵니다.

그러던 중 이 기사를 통해 Microsoft의 **Trellis.2 (4B)**가 로컬 image-to-3D의 새로운 최고봉이라는 것을 알게 되었습니다. Hunyuan3D의 최신 버전이 클로즈드(Closed)화되어 가는 가운데, 오픈으로 사용할 수 있는 대형 모델입니다.

리포지토리:microsoft/TRELLIS.2

/ 모델:microsoft/TRELLIS.2-4B

(Hugging Face) -
O-Voxel 구조: 구멍이 뚫린 형상, 복잡한 토폴로지(Topology), 날카로운 에지(Edge) 재현에 강한 표현력 -
PBR 마테리얼 일괄 생성: BaseColor뿐만 아니라 Metallic/Roughness까지 출력 -
40억 파라미터 + Sparse 3D VAE: 고해상도·고디테일

공식 동작 요구 사항은 VRAM 24GB 권장(기사에서는 16GB GPU에서도 512 해상도로 동작 보고 있음)입니다. Python 3.12 / PyTorch 2.9+ / 커스텀 CUDA 확장 빌드가 포함된 구성입니다.

이번에는 ComfyUI가 아니라, NVIDIA GB10(DGX Spark 계열, aarch64 + 통합 메모리) Linux 머신에 순수 Python으로 도입했습니다. 세상의 동작 보고는 대부분 x86/WSL2이므로, ARM에서의 도입 기록은 꽤 희귀할 것입니다. 겪었던 장애와 대처법을 모두 적겠습니다.

setup.sh는 확장 기능마다 플래그가 나누어져 있습니다. flash-attn은 ARM 빌드 리스크가 높기 때문에, 우선 제외하고 시작했습니다.

export TORCH_CUDA_ARCH_LIST="12.1" # GPU의 실제 아키텍처(GB10)를 명시
export MAX_JOBS=16
source setup.sh --basic --o-voxel --cumesh --flexgemm --nvdiffrast

결과적으로 cumesh / flexgemm / nvdiffrast한 번에 빌드 성공. 3D 계열의 CUDA 확장이 ARM에서 순조롭게 통과되는 것은 솔직히 놀라웠습니다.

참고로 glcontext(X11 헤더 부족)와 pillow-simd(x86 SIMD 전제)는 실패하지만, GLB 익스포트 경로에는 불필요하므로 무시해도 OK입니다.

fatal error: Eigen/Dense: No such file or directory

apt install libeigen3-dev를 할 수 없는 환경이라도, Eigen은 헤더 온리(Header-only) 라이브러리이므로 sudo 없이 해결할 수 있습니다.

curl -sL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz | tar xz -C ~
export CPLUS_INCLUDE_PATH="$HOME/eigen-3.4.0:${CPLUS_INCLUDE_PATH:-}"
pip install ./o-voxel # 성공

실행하면 이미지 인코더 다운로드에서 멈춥니다.

huggingface_hub.errors.GatedRepoError: 401 Client Error.
(facebook/dinov3-vitl16-pretrain-lvd1689m)

Trellis.2는 이미지 인코더에 Meta의 DINOv3를 사용하고 있으며, 이것이 게이트형 리포지토리 (Gated Repository) (라이선스 동의를 한 사람만 DL 가능)입니다. 빠지기 쉬운 함정은 2단계가 있다는 점입니다.

401 = 토큰이 없음 → Read 토큰을 생성하여 설정 -
403 = 토큰은 있지만 해당 모델에 대한 액세스 권한이 없음 → 모델 페이지에서 「Agree and access repository」를 전송

토큰은 계정 공통이지만, 동의는 모델마다 필요합니다. SAM3 등 다른 Meta 제작 모델은 게이트 없이 사용할 수 있었기에, 여기서 처음으로 HF 계정이 필요해졌습니다.

다음으로 배경 제거 모델에서 다시 403 발생.

OSError: You are trying to access a gated repo.
(briaai/RMBG-2.0)

이것은 동의해서 사용하기 전에 주의가 필요합니다. RMBG-2.0은 상업적 이용에 유상 라이선스가 필요한 모델로, 상업용 게임 개발 파이프라인에 포함시키면 지뢰가 됩니다.

다행히 파이프라인 소스를 읽어보니 preprocess_image()입력 이미지에 알파 채널(Alpha Channel)이 있으면 배경 제거를 호출하지 않는 설계였습니다. 문제는 "사용하지 않는데도 구축 시 무조건 모델을 DL하는" 구현뿐입니다. 따라서 구축을 no-op으로 교체합니다.

# 입력이 투명 PNG이므로 배경 제거(Background Removal)는 불필요. 구축(Construction)만 무효화한다
import trellis2.pipelines.trellis2_image_to_3d as _t2mod
class _NoRembg:
...

이렇게 하면 라이선스 문제까지 완전히 회피할 수 있습니다. 게임 에셋 제작 시에는 입력을 투명 PNG로 통일해 두는 것을 추천합니다.

AttributeError: 'DINOv3ViTModel' object has no attribute 'layer'

Trellis.2의 특징 추출기(Feature Extractor)는 transformers 4.x 시대의 내부 구조(model.layer)에 직접 접근하지만, 5.x 계열에서는 레이어 리스트가 Encoder 서브모듈(model.model.layer)로 이동했습니다. 한 줄의 폴백(Fallback) 코드로 양쪽 모두 대응할 수 있습니다.

# transformers 4.x: model.layer / 5.x: model.model.layer
_layers = getattr(self.model, 'layer', None)
if _layers is None:
...
ModuleNotFoundError: No module named 'flash_attn'

Trellis.2의 어텐션(Attention)은 환경 변수로 백엔드(Backend)를 전환할 수 있습니다.

  • 밀집 어텐션 (Dense Attention): ATTN_BACKEND=sdpa (PyTorch 내장. 추가 빌드 불필요)
  • 희소 어텐션 (Sparse Attention): sdpa 미지원 시 ['xformers', 'flash_attn', 'flash_attn_3']만 사용 가능

flash-attn의 ARM 빌드는 시간이 오래 걸리고 실패할 위험이 있기 때문에, xformers를 소스 빌드(cutlass 기반으로 새로운 ARM 아키텍처 대응이 빠름)하여 회피했습니다.

TORCH_CUDA_ARCH_LIST="12.1" MAX_JOBS=16 pip install --no-build-isolation xformers
# 실행 시:
ATTN_BACKEND=sdpa SPARSE_ATTN_BACKEND=xformers python generate.py

생성 코드는 공식 example.py를 기반으로 하며, 게임용으로 폴리곤 수(Face count)와 텍스처 크기를 지정했습니다.

pipeline = Trellis2ImageTo3DPipeline.from_pretrained("microsoft/TRELLIS.2-4B")
pipeline.cuda()
mesh = pipeline.run(Image.open("enemy_forest_goblin.png"))[0] # 투명 PNG
...

그리고 결과입니다. 단 한 장의 이미지로 즉시 생성했는데, 이 결과가 나왔습니다.

솔직히 차원이 달랐습니다. 주목할 포인트:

  • 측면과 배면의 텍스처 붕괴가 없음. §1③에서 끊임없이 싸웠던 문제가 존재하지 않음.
  • 팔이 몸통에서 분리된 자연스러운 스탠딩 포즈로 생성됨. §1①의 유착(Adhesion) 문제도 대폭 경감되어 그대로 리깅(Rigging)하기에 적합함.
  • 출력물은 29만 면 + PBR 텍스처(BaseColor / Metallic-Roughness 각 2048px).

텍스처를 제거한 메쉬(클레이 뷰)를 보면 품질 차이의 본질을 알 수 있습니다. 얼굴의 굴곡, 손가락, 옷 주름까지 조형으로서 들어가 있습니다.

정면 샷을 나란히 비교하면 다음과 같습니다. 왼쪽(Hunyuan + 자체 보정)은 원본 이미지를 그대로 투영하기 때문에 정면의 '이미지 일치도' 면에서는 앞서지만, 이는 몇 주간의 자체 공정을 거친 결과입니다. 오른쪽(Trellis.2)은 단 한 번의 생성만으로, 그것도 이 품질이 측면과 배면까지 일관되게 유지됩니다.

관점Hunyuan3D-2 (+자작 보정)Trellis.2 4B
정면 외관◎ (원화 투영으로 인해 일치)
...
  • Hunyuan3D 기반의 파이프라인은 「움직이려고 시도한 순간」에 과제가 분출되어, 대증요법적인 자작 공정이 계속 늘어났다.
  • Trellis.2 4B는 ARM 환경(GB10/DGX Spark 계열)에서도 모든 의존성(dependency)을 빌드하여 구동할 수 있었다. 삽질할 만한 지점은 Eigen / HF 게이트(gate) × 2 / transformers 5.x / flash-attn 대체 등 5가지였으며, 모두 본 기사의 절차로 회피 가능하다. - RMBG-2.0의 게이트는 동의하지 않고 회피하는 것을 추천한다 (상업적 라이선스 문제까지 함께 사라진다). - 생성 품질은 차원이 다르다. 측면 텍스처와 유착되는 문제 등 Hunyuan 시대의 2대 과제가 (적어도 이번 소체에서는) 발생하지 않았다.

다음 회차에서는 이 모델을 게임 엔진(Axmol) 측의 파이프라인 — 부위 분할, 리깅 (Rigging), 스프라이트 시트 (Sprite sheet)화 — 에 연결하여, 실제로 게임 내에서 움직이는 단계까지 리포트하겠습니다.

개인 개발을 하며 3D 생성 AI에 휘둘리고 계신 분들께 참고가 되기를 바랍니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0