두 번째 모델
지난번에 만들어 둔 3D 뷰어에 두 번째 모델을 올린다. TINA 로고 토큰이 박힌 위치 핀(POI) 마커 — 지도 위에 꽂히는 그 핀을 입체로 빚고, 40프레임 동안 한 바퀴 도는 애니메이션을 붙인 모델이다.
관문 1 — 작업 씬에서 히어로만 추려내기
.blend 파일은 완성작 하나가 아니라 작업실 전체였다. 오브젝트 100여 개 — 핀 바디 변형 일곱 종, 코인·토큰 실험, 투표/등록/완료 같은 용도별 변주가 카메라 밖에 좌르륵 흩어져 있었다. 통째로 내보내면 뷰어의 자동 프레이밍이 그 전부를 담으려고 카메라를 한없이 뒤로 뺀다.
답은 선택 내보내기. 카메라에 실제로 잡히는 히어로 핀의 계층(바디 → 토큰 → 로고, 5개 오브젝트)만 재귀적으로 선택해 use_selection=True로 내보냈다. 9.1MB 작업 파일이 320KB 웹 모델이 됐다.
def select_tree(o):
o.select_set(True)
for c in o.children:
select_tree(c)
select_tree(bpy.data.objects["POI_TINA.002"])
bpy.ops.export_scene.gltf(filepath=out, use_selection=True, ...)관문 2 — glTF에 실리지 않는 절차적 색
내보낸 모델을 열어 보니 전부 흰색이었다. 이 파일의 재질은 노이즈·램프 노드를 엮은 절차적(procedural) 셰이더인데, glTF는 노드 그래프를 이해하지 못한다. 이미지 텍스처가 아닌 색은 그냥 버려진다 — baseColorFactor조차 남지 않는다.
정석은 텍스처 베이킹이지만, 이 모델의 색은 사실상 면 단위 단색이다. 그래서 렌더에서 샘플한 대표색을 내보내기 직전에 Principled BSDF 소켓에 직접 심는 쪽을 택했다.
FLAT = {
"TINABlue": ((0.010, 0.045, 0.380, 1.0), 0.85, 0.30), # 딥블루 바디
"TINASKYBlue": ((0.080, 0.520, 0.950, 1.0), 0.60, 0.20), # 스카이블루 링
"TINAWhite": ((0.900, 0.900, 0.900, 1.0), 0.00, 0.35), # 화이트 코인
}
# Base Color 링크를 끊고 대표색·metallic·roughness를 default_value로 주입재질 이름에 색이 들어 있던 게 (TINABlue, TINASKYBlue…) 뜻밖의 구세주였다. 이름이 곧 스펙이 된 셈.
조명은 이번엔 스튜디오로
원본 씬의 조명은 AREA 라이트 여섯 개 — 그런데 glTF의 조명 확장(KHR_lights_punctual)은 point·spot·directional만 안다. 면광원은 아예 실리지 않는다. 지난번 Geo DiPin처럼 씬 조명을 살릴 수 없는 구조라, 이번엔 뷰어의 스튜디오 모드(중립 화이트 라이팅)에 밝은 배경을 깔아 원본 렌더의 화이트 제품샷 무드를 재현했다. 금속 질감은 환경맵 반사(envIntensity)가 마무리해 준다.
덧붙임 — V2 변형 둘
같은 POI 작업의 V2 파일에서 변형 두 개를 더 꺼내 올린다. 이번엔 오브젝트 이름을 하나하나 지정하는 대신 스크립트를 일반화했다 — 씬에서 켜져 있는(visible) 메시만 자동 선택. 작업 파일에서 변형을 고르는 기준이 곧 "지금 뷰포트에 보이는 것"이었기 때문에, 파일마다 다른 오브젝트가 켜져 있어도 같은 스크립트 하나로 처리된다. 색 팔레트도 재질 이름 사전(TINAWhite, TINA.Yellow, TINA.CompleteBlue…)으로 정리해서, 이제 어떤 변형이 와도 이름만 보고 입힌다.
투표(Vote) 핀 — 화이트 바디에 옐로 코인. 지도 위에서 "투표할 수 있는 곳"을 가리키는 변형.
완료(Complete) 핀 — 같은 바디에 블루 코인. 체크 심볼이 "완료된 위치"를 표시한다.
정리
같은 파이프라인, 다른 관문. 지난번이 "조명·유리·글로우를 어떻게 되살릴 것인가"였다면 이번엔 "무엇을 내보내고, 색을 어디서 구할 것인가"였다. 모델마다 관문이 다르니, 뷰어를 컴포넌트로 만들어 둔 보람이 쌓인다 — 이번에도 본문에 필요한 건 태그 한 줄이었다.