스킨 가중치
고친 사람 github-actions[bot]
스킨 가중치는 3차원 모형의 꼭짓점마다 어느 뼈를 얼마나 따라 움직일지 정해 줍니다. 뼈대가 움직이면 꼭짓점은 이 비율대로 여러 뼈의 움직임을 나눠 받습니다. 팔을 굽힐 때 팔꿈치 둘레가 꺾이지 않고 둥글게 접히는 것이 이 비율 덕분입니다.
쉽고 빠른 이해
스킨 가중치는 꼭짓점 하나가 뼈 하나를 얼마나 따라갈지 적어 둔 0 과 1 사이의 수입니다. 팔꿈치 꼭짓점에 위팔 뼈 0.5, 아래팔 뼈 0.5 를 적어 두면 그 꼭짓점은 두 뼈가 움직인 위치의 한가운데로 갑니다.
이게 없으면 꼭짓점마다 뼈 하나만 따라갈 수 있습니다. 그러면 팔을 굽힐 때 위팔 쪽 겉면과 아래팔 쪽 겉면이 따로 놀아 관절에서 면이 찢어지듯 늘어나거나 서로 파고듭니다.
돌아가는 방식은 이렇습니다.
- 모형을 만들 때 꼭짓점마다 따라갈 뼈와 가중치를 적어 둡니다
- 화면을 한 장 그릴 때마다 뼈 하나하나를 따라 옮긴 꼭짓점 위치를 구합니다
- 그 위치들을 가중치만큼씩 더해 최종 위치를 냅니다
대가는 손이 많이 간다는 것입니다. 가중치는 사람이 관절마다 붓으로 칠하듯 다듬어야 합니다. 꼭짓점마다 뼈 번호와 가중치를 함께 실어야 해서 모형 데이터도 그만큼 커집니다.
뼈대를 따라 휘는 겉면에 씁니다. 얼굴 표정, 바람에 날리는 옷자락, 휘지 않는 물체에는 다른 수단을 씁니다.
상세
아이가 엄마와 아빠 손을 하나씩 잡고 걷습니다. 엄마 손을 더 꽉 잡고 있으면 엄마가 방향을 틀 때 그쪽으로 많이 끌려갑니다. 아빠가 방향을 틀면 조금만 끌려갑니다.
스킨 가중치는 3차원 모형의 꼭짓점 하나가 뼈 하나를 얼마나 따라갈지 적은 수입니다. 0 이면 그 뼈가 움직여도 꼼짝하지 않습니다. 1 이면 그 뼈를 고스란히 따라갑니다. 0.5 면 그 뼈를 절반만 따라갑니다.
이 절은 뼈대와 겉면이 무엇인지부터 짚습니다. 이어서 가중치가 없으면 무엇이 곤란한지를 팔꿈치 하나로 봅니다. 그다음 가중치를 꼭짓점에 어떻게 적고 어떻게 섞어 쓰는지를 숫자로 따라갑니다. 끝으로 가중치를 누가 정하는지와 틀렸을 때 어떤 모습이 되는지를 봅니다.
뼈대와 겉면
3차원 캐릭터는 대개 두 겹으로 만듭니다. 바깥 겹은 눈에 보이는 겉면입니다. 겉면은 수천에서 수만 개의 꼭짓점과 그 꼭짓점을 이은 삼각형으로 이루어집니다. 꼭짓점은 정점이라고도 합니다. 삼각형 묶음 전체는 메시입니다.
안쪽 겹은 화면에 그리지 않는 뼈대입니다. 뼈대는 위팔·아래팔·손처럼 이어 붙은 뼈 수십 개로 이루어집니다. 실무에서는 뼈를 본(bone)이나 조인트라고도 부릅니다.
움직임을 만드는 사람은 뼈대만 움직입니다. 겉면의 꼭짓점을 뼈대에 맞춰 옮기는 계산은 따로 있습니다. 그 계산이 스키닝입니다. 겉면을 살갗(skin)에 빗댄 이름입니다. 스킨 가중치는 스키닝이 읽는 입력 가운데 하나입니다.
뼈 하나만 따를 때 생기는 틈
가중치 없이도 겉면을 움직일 수는 있습니다. 꼭짓점마다 뼈를 딱 하나씩 정해 두고 그 뼈만 따라가게 하면 됩니다. 위팔을 덮은 꼭짓점은 위팔 뼈를, 아래팔을 덮은 꼭짓점은 아래팔 뼈를 따라갑니다.
문제는 두 무리가 만나는 팔꿈치입니다. 팔을 90 도 굽히면 위팔 쪽 꼭짓점은 제 위치에 있고 아래팔 쪽 꼭짓점만 통째로 돌아갑니다. 그 경계를 잇던 삼각형은 바깥쪽에서 길게 늘어납니다. 안쪽에서는 겉면끼리 서로 파고듭니다. 관절이 종이를 접은 듯 날카롭게 꺾입니다.
사람 팔은 그렇게 접히지 않습니다. 팔꿈치 둘레의 살갗은 두 뼈에 다 끌려서 그 중간쯤으로 둥글게 휩니다. 이 「중간쯤」을 숫자로 적는 것이 스킨 가중치입니다.
꼭짓점마다 적는 수
꼭짓점 하나에는 따라갈 뼈와 그 뼈의 가중치가 짝으로 붙습니다. 관절에서 먼 꼭짓점은 뼈 하나에서 1 을 받습니다. 관절에 가까운 꼭짓점은 양쪽 뼈에서 조금씩 나눠 받습니다.
flowchart TD
subgraph 뼈대
U["위팔 뼈"]
L["아래팔 뼈"]
end
subgraph 겉면["팔을 덮은 꼭짓점 셋"]
A["위팔 가운데 꼭짓점"]
B["팔꿈치 꼭짓점"]
C["아래팔 가운데 꼭짓점"]
end
U -->|1.0| A
U -->|0.5| B
L -->|0.5| B
L -->|1.0| C
화살표에 붙은 수가 가중치입니다. 위팔 가운데 꼭짓점은 위팔 뼈 하나만 따라갑니다. 팔꿈치 꼭짓점은 두 뼈를 반씩 따라갑니다. 그림에 화살표가 없는 짝, 예를 들어 위팔 가운데 꼭짓점과 아래팔 뼈 사이는 가중치가 0 입니다.
꼭짓점마다 따로 붙어 다니는 이런 값이 정점 속성입니다. 위치·색과 같은 방식으로 꼭짓점 목록에 함께 실립니다. 가중치는 모형을 만들 때 한 번 정합니다. 캐릭터가 움직이는 동안에는 바뀌지 않습니다. 화면을 한 장 그릴 때마다 바뀌는 것은 뼈대의 자세뿐입니다.
가중치로 섞는 계산
꼭짓점 위치는 모형을 만들 때 정해진 한 자세를 기준으로 적혀 있습니다. 팔을 양옆으로 벌린 T 자 자세처럼 뼈대에 겉면을 처음 붙인 때의 자세가 바인드 포즈입니다.
한 장을 그릴 때마다 스키닝은 꼭짓점을 뼈 하나씩 따라 옮겨 봅니다. 「이 꼭짓점이 위팔 뼈만 따랐다면 어디에 있을까」, 「아래팔 뼈만 따랐다면 어디에 있을까」를 각각 구하는 것입니다. 그다음 그 위치들을 가중치만큼씩 곱해 더합니다.
숫자를 넣어 봅니다. 팔꿈치 관절의 중심을 원점 (0, 0) 으로 잡습니다. 팔꿈치 둘레의 한 꼭짓점이 위팔 뼈만 따르면 (1.0, 0.0) 에, 아래팔 뼈만 따르면 (0.0, 1.0) 에 간다고 합시다. 두 위치 모두 관절 중심에서 1 만큼 떨어져 있습니다. 아래 그림은 두 가중치가 0.5 씩일 때의 계산입니다.
flowchart TD
P["바인드 포즈의 꼭짓점 위치"] --> U2["위팔 뼈만 따라 옮긴 위치<br/>(1.0, 0.0)"]
P --> L2["아래팔 뼈만 따라 옮긴 위치<br/>(0.0, 1.0)"]
U2 -->|"위팔 가중치 0.5 를 곱한다"| S["더한다"]
L2 -->|"아래팔 가중치 0.5 를 곱한다"| S
S --> F["최종 위치<br/>(0.5, 0.5)"]
가중치를 바꿔 가며 최종 위치를 구하면 아래 표가 나옵니다.
| 위팔 가중치 | 아래팔 가중치 | 최종 위치 |
|---|---|---|
| 1.0 | 0.0 | (1.0, 0.0) |
| 0.5 | 0.5 | (0.5, 0.5) |
| 0.2 | 0.8 | (0.2, 0.8) |
| 0.0 | 1.0 | (0.0, 1.0) |
가중치가 한쪽으로 기울수록 최종 위치도 그 뼈가 보낸 위치 쪽으로 다가갑니다. 그런데 표의 네 점은 모두 (1.0, 0.0) 과 (0.0, 1.0) 을 이은 직선 위에 있습니다. 위치를 직선으로 섞기 때문입니다.
이 직선은 관절 쪽으로 들어가 있습니다. 양 끝은 관절 중심에서 1 만큼 떨어져 있는데, 한가운데 (0.5, 0.5) 는 약 0.71 만큼만 떨어져 있습니다. 두 뼈를 반씩 따르는 꼭짓점은 관절 안쪽으로 조금 끌려 들어갑니다.
둥근 굽이는 꼭짓점 하나가 아니라 여러 꼭짓점이 모여서 만듭니다. 관절에서 멀어질수록 가중치를 조금씩 한쪽으로 옮겨 둡니다. 그러면 위팔 쪽 꼭짓점은 위팔 뼈를 더, 아래팔 쪽 꼭짓점은 아래팔 뼈를 더 따라갑니다. 비율이 1 에서 0 으로 한 번에 끊기지 않으므로 겉면도 한 번에 꺾이지 않고 완만하게 휩니다.
이렇게 뼈마다 옮긴 위치를 가중치로 더하는 방식을 선형 블렌드 스키닝이라고 부릅니다. 영어 이름은 Linear Blend Skinning 입니다.
겉면에는 위치 말고도 함께 휘어야 하는 값이 있습니다. 법선은 겉면의 한 점이 어느 쪽을 향하는지 나타내는 화살표입니다. 빛이 겉면에 얼마나 비스듬히 닿는지를 이 화살표로 계산합니다. 겉면이 휘면 향하는 쪽도 바뀌므로 법선도 같은 뼈와 같은 가중치로 섞습니다.
이 계산은 대개 GPU(Graphics Processing Unit, 그래픽 처리 장치)에서 돕니다. 꼭짓점 하나마다 한 번씩 도는 작은 프로그램인 정점 셰이더가 가중치를 읽어 섞습니다.
합을 1 로 맞추는 정규화
한 꼭짓점의 가중치는 다 더해 1 이 되도록 맞춥니다. 1 이 아니면 뼈대가 가만히 있어도 겉면이 제 위치를 벗어납니다.
뼈가 하나도 안 움직였다면 뼈마다 옮긴 위치는 전부 원래 위치와 같습니다. 그 위치들을 가중치로 더하면 원래 위치에 가중치의 합을 곱한 값이 나옵니다. 꼭짓점 좌표는 모형의 원점을 기준으로 적혀 있습니다. 그래서 합 0.8 을 곱하면 꼭짓점이 원점 쪽으로 끌려옵니다. 원점이 발밑에 있다면 높이 10 에 있던 꼭짓점이 8 로 내려앉습니다.
p = 10.0 # 제자리 높이
w = [0.5, 0.3] # 합 0.8
sum(x*p for x in w) # 8.0
뼈가 안 움직였어도 꼭짓점이 두 칸 내려왔습니다. 합이 1 보다 크면 거꾸로 원점에서 멀어지는 쪽으로 부풀어 오릅니다. 그래서 가중치를 다 정한 뒤에는 각 값을 합으로 나눠 합이 1 이 되게 다시 맞춥니다. 이 일이 정규화입니다.
w = [0.5, 0.3]
s = sum(w) # 0.8
w = [x / s for x in w] # [0.625, 0.375]
나눈 뒤에도 두 뼈의 비율은 5 대 3 그대로입니다. 바뀐 것은 합뿐입니다. 이제 합이 1 입니다.
꼭짓점당 뼈 수의 상한
한 꼭짓점이 따라갈 뼈의 수는 몇 개까지로 묶어 둡니다. 실시간으로 그리는 쪽에서는 흔히 넷까지로 묶습니다. 꼭짓점마다 칸 수가 같아야 정점 셰이더가 모든 꼭짓점을 같은 방식으로 읽을 수 있기 때문입니다.
그래서 꼭짓점마다 칸이 두 줄 붙습니다. 한 줄에는 따라갈 뼈의 번호를 넷 적습니다. 이 번호를 본 인덱스라고 부릅니다. 다른 줄에는 같은 순서로 가중치 넷을 적습니다. 따라갈 뼈가 둘뿐인 꼭짓점은 남은 두 칸의 가중치를 0 으로 둡니다.
만든 사람이 다섯 뼈에 가중치를 줬다면 가장 작은 것을 버리고 다시 정규화합니다. 버린 만큼 합이 줄어들기 때문입니다.
| 뼈 | 처음 | 다섯째를 버린 뒤 | 다시 정규화한 뒤 |
|---|---|---|---|
| 뼈 1 | 0.40 | 0.40 | 0.421 |
| 뼈 2 | 0.30 | 0.30 | 0.316 |
| 뼈 3 | 0.15 | 0.15 | 0.158 |
| 뼈 4 | 0.10 | 0.10 | 0.105 |
| 뼈 5 | 0.05 | 버림 | 버림 |
| 합 | 1.00 | 0.95 | 1.000 |
버린 뼈가 맡던 0.05 는 남은 넷이 제 몫의 비율대로 나눠 가집니다. 작은 값을 버렸으므로 모양은 거의 안 바뀝니다.
가중치를 정하는 작업
뼈대를 만들고 겉면을 거기에 붙이는 일을 통틀어 리깅이라고 부릅니다. 가중치를 정하는 것은 그 가운데서도 손이 가장 많이 가는 단계입니다.
모델링 도구는 대개 뼈와 꼭짓점 사이의 거리를 보고 처음 가중치를 계산해 줍니다. 가까운 뼈일수록 큰 값을 받습니다. 거리만으로는 겨드랑이나 손가락 사이처럼 뼈가 몰린 곳이 잘 안 맞습니다.
그래서 사람이 다듬습니다. 뼈 하나를 고르고 겉면 위에 붓으로 칠하듯 가중치를 그려 넣습니다. 진하게 칠한 곳이 그 뼈를 많이 따라갑니다. 이 작업이 웨이트 페인팅입니다.
관절 둘레를 넓게 칠하면 굽이가 넓고 완만해집니다. 좁게 칠하면 굽이가 짧고 또렷해집니다. 팔꿈치는 넓게, 손가락 마디는 좁게 칠하는 식으로 관절마다 폭을 고릅니다.
가중치가 틀어졌을 때의 모습
가중치가 잘못되면 캐릭터가 움직일 때 겉면이 엉뚱하게 늘어나거나 딸려 갑니다. 자주 보이는 모습과 그 원인은 이렇습니다.
| 보이는 모습 | 가중치에서 생긴 원인 |
|---|---|
| 가만히 서 있어도 겉면 일부가 쪼그라들거나 부푼다 | 합이 1 이 아니다 |
| 팔을 들면 옆구리 살이 따라 올라간다 | 옆구리 꼭짓점에 팔 뼈의 작은 가중치가 남아 있다 |
| 관절이 종이 접듯 날카롭게 꺾인다 | 관절 둘레가 1 에서 0 으로 한 번에 끊긴다 |
| 크게 굽힌 관절이 가늘게 쪼그라든다 | 두 뼈를 반씩 따르는 관절 꼭짓점이 큰 각도에서 안쪽으로 몰린다 |
앞의 셋은 가중치를 고치면 낫습니다. 마지막은 가중치만으로는 다 못 고칩니다. 「가중치로 섞는 계산」의 표에서 한가운데 (0.5, 0.5) 가 관절 쪽으로 끌려 들어간 것과 같은 일이기 때문입니다. 위치를 직선으로 섞는 선형 블렌드 스키닝의 성질이라 굽히는 각도가 클수록 더 깊이 파고듭니다.
이 경우에는 섞는 방식을 바꾸거나 뼈를 더 둡니다. 앞에서 섞은 것은 뼈마다 옮긴 위치였습니다. 듀얼 쿼터니언 스키닝은 위치 대신 뼈가 돈 회전 자체를 가중치로 섞습니다. 섞은 회전으로 꼭짓점을 돌리므로 한가운데 꼭짓점도 관절 중심에서 같은 거리를 지킨 채 돕니다.
다른 갈래는 관절 둘레에 보조 뼈를 더 두는 것입니다. 뼈가 늘면 뼈 하나가 맡는 회전 각도가 줄어듭니다. 각도가 작으면 한가운데가 파고드는 깊이도 줄어듭니다. 어느 쪽이든 꼭짓점마다 적은 가중치는 그대로 입력으로 씁니다.
가중치로 움직이지 않는 것
스킨 가중치는 뼈대가 있는 겉면을 휘게 할 때 씁니다. 뼈대로 나타내기 어려운 움직임에는 다른 수단을 씁니다.
얼굴 표정은 뼈 몇 개로 잡기 어렵습니다. 웃는 얼굴·찡그린 얼굴처럼 겉면 모양을 여러 벌 만들어 두고 그 사이를 섞는 모프 타깃을 흔히 씁니다. 바람에 날리는 옷자락은 뼈대 없이 물리 계산으로 꼭짓점을 직접 옮깁니다.
휘지 않는 물체도 가중치가 필요 없습니다. 로봇 팔의 금속판이나 손에 든 칼은 뼈 하나를 통째로 따라가면 됩니다. 모든 꼭짓점이 그 뼈에서 1 을 받는 것과 같으므로, 물체 전체를 그 뼈에 매달아 함께 옮깁니다.
관련 항목
스킨 가중치를 입력으로 읽는 계산
스키닝 · 선형 블렌드 스키닝 · 듀얼 쿼터니언 스키닝 · 스키닝 행렬 · 스켈레탈 애니메이션 · 정점 셰이더
스킨 가중치와 나란히 꼭짓점에 실리는 값
본 인덱스 · 정점 속성 · 정점 위치 · 법선 · 탄젠트 · 정점 색 · 텍스처 좌표
스킨 가중치가 가리키는 뼈대 구성 요소
스켈레톤 · 조인트 · 스킨 조인트 · 바인드 포즈 · 역바인드 행렬 · 변환 행렬 · 계층 변환
스킨 가중치를 만들고 다듬는 작업
리깅 · 웨이트 페인팅 · 자동 가중치 · 가중치 정규화 · 가중치 스무딩 · 스킨 바인딩
스킨 가중치 대신 겉면을 움직이는 수단
모프 타깃 · 블렌드 셰이프 · 천 시뮬레이션 · 정점 애니메이션 텍스처 · 리지드 바인딩
스킨 가중치를 담아 나르는 저장 구조
가중치 섞기에서 터지는 변형 문제
캔디 래퍼 현상 · 볼륨 손실 · 가중치 스며듦 · 보조 뼈 · 교차 관통
다른 이름: skin weight · skin weights · skinning weight · 스키닝 가중치 · 스킨 웨이트 · 웨이트