탄젠트
고친 사람 github-actions[bot]
탄젠트는 3차원 모델의 표면 위에서 그림의 가로 방향이 어느 쪽인지 알려 줍니다. 표면에 수직인 법선과 짝을 이뤄, 그림에 담아 둔 요철에 빛이 맞게 맺히도록 돕습니다. 수학에서는 같은 이름으로 삼각함수 하나와 곡선에 닿는 직선을 부릅니다. 이 항목은 그래픽스의 뜻을 다룹니다.
쉽고 빠른 이해
탄젠트는 표면에 붙인 그림이 가로로 어느 쪽을 향해 누워 있는지 적어 둔 방향입니다. 벽돌 무늬를 입힌 벽이라면 벽돌이 가로로 줄지어 가는 쪽이 탄젠트입니다.
표면이 어느 쪽을 보는지만 알아서는 그림이 표면 위에서 얼마나 돌아가 있는지 모릅니다. 요철을 색으로 담아 둔 그림을 쓰려면 그 그림의 좌우와 위아래가 표면 위에서 어느 쪽인지 알아야 합니다. 이걸 모르면 빛이 엉뚱한 쪽에서 비친 것처럼 음영이 생깁니다.
어떻게 도나:
- 삼각형마다 꼭짓점 위치와 그림 좌표를 견줘 그림의 가로 방향을 구합니다
- 꼭짓점마다 이웃 삼각형들의 값을 모아 하나로 다듬습니다
- 그릴 때 탄젠트와 표면의 수직 방향으로 세 번째 방향을 만듭니다. 셋을 기준 삼아 그림 속 요철의 방향을 장면 전체의 방향으로 옮깁니다
대가는 꼭짓점마다 숫자 네 개, 곧 방향 셋과 부호 하나가 더 붙는다는 것입니다. 요철 그림을 쓰지 않는 모델이라면 탄젠트는 메모리만 차지합니다. 그림을 만든 도구와 그리는 프로그램이 탄젠트를 서로 다르게 구하면 이음매에 줄이 보입니다.
상세
바닥에 카펫을 깔았다고 해 봅시다. 카펫이 위를 향해 놓였다는 것만으로는 털이 어느 쪽으로 누웠는지 모릅니다. 결이 어느 쪽인지는 따로 알려 줘야 합니다.
탄젠트는 표면 위 한 점에서 표면에 닿은 채로 뻗는 방향입니다. 법선이 표면에서 곧게 서는 방향이라면, 탄젠트는 표면을 따라 눕는 방향입니다. 그래서 둘은 서로 직각을 이룹니다.
값으로는 실수 세 개짜리 벡터 하나입니다. 크기가 아니라 방향만 뜻하므로 길이를 1로 맞춰 씁니다. 길이를 1로 맞추는 일이 정규화입니다.
저장할 때는 부호 하나를 더 붙여 넷으로 적는 일이 많습니다. 까닭은 아래 「네 번째 값과 뒤집힌 그림」에서 봅니다.
3차원 모델은 삼각형을 이어 붙여 만듭니다. 그 꼭짓점 하나를 정점이라고 부릅니다.
탄젠트는 법선처럼 정점마다 하나씩 붙어 다닙니다. 이렇게 정점에 붙는 값을 정점 속성이라고 부릅니다.
여러 방향 가운데 하나를 고르는 기준
표면을 따라 눕는 방향은 하나가 아닙니다. 한 점에서 표면을 따라 사방으로 뻗을 수 있습니다. 그중 하나를 골라야 탄젠트가 정해집니다. 그 기준은 표면에 붙인 그림이 줍니다.
표면에 입히는 그림을 텍스처라고 부릅니다. 나무결이나 벽돌 무늬를 매끈한 삼각형 위에 입혀 실제 물건처럼 보이게 하는 데 씁니다.
그림의 어느 지점을 표면의 어느 지점에 붙일지는 텍스처 좌표라는 값 한 쌍이 정합니다. 가로축을 u, 세로축을 v 라고 부릅니다. 둘을 붙여 UV(UV coordinates, 두 축 이름을 붙여 부르는 말)라고도 합니다.
탄젠트는 표면 위에서 u 가 커지는 쪽을 가리킵니다. 벽돌 무늬를 입힌 벽이라면 벽돌이 가로로 줄지어 가는 쪽이 탄젠트입니다. 같은 벽에 그림을 90도 돌려 붙이면 탄젠트도 90도 돌아갑니다.
이름이 온 곳
수학에서 접선은 곡선의 한 점에 닿기만 하고 파고들지 않는 직선입니다. 영어로는 tangent 입니다. 「닿다」라는 뜻의 라틴어에서 왔습니다. 곡면으로 넓히면 한 점에 닿는 평면이 생깁니다. 그 평면 위의 방향을 접선 방향이라고 부릅니다.
그래픽스의 탄젠트는 이 접선 방향 가운데 u 가 커지는 쪽 하나입니다. 그래서 탄젠트 벡터나 접선 벡터라고도 부릅니다.
삼각함수의 탄젠트도 같은 낱말에서 이름을 얻었습니다. 각도를 넣으면 사인을 코사인으로 나눈 값, 곧 기울기가 나옵니다. 이름의 뿌리만 같고 쓰는 곳은 다릅니다.
노멀 맵이 탄젠트를 부른다
삼각형을 잘게 쪼개지 않고도 표면이 울퉁불퉁해 보이게 하는 방법이 있습니다. 표면 위 점마다 법선을 조금씩 기울여 두면 빛이 그 기울기대로 맺힙니다. 그러면 평평한 면에 벽돌 틈이나 긁힌 자국이 보입니다.
이 기울인 법선들을 그림 한 장에 담아 둔 것이 노멀 맵입니다. 그림의 빨강·초록·파랑 세 값이 법선의 세 성분을 뜻합니다.
노멀 맵의 법선은 장면 전체의 방향이 아니라 그 점의 표면을 기준으로 적혀 있습니다. 표면에서 곧게 서는 방향이 늘 파랑 축이 되게 적습니다. 그래서 같은 그림을 모델의 어느 면에 붙여도, 그 면이 어디를 향하든 쓸 수 있습니다.
조명은 장면 전체를 기준으로 계산합니다. 그 기준 좌표계를 월드 공간이라고 부릅니다. 노멀 맵의 값을 조명에 쓰려면 표면 기준의 방향을 월드 공간의 방향으로 옮겨야 합니다.
옮기려면 표면 기준의 세 축이 월드 공간에서 어느 쪽인지 알아야 합니다. 법선은 그중 파랑 축 하나만 알려 줍니다. 나머지 두 축은 법선을 중심으로 빙글 돌 수 있어서 법선만으로는 안 정해집니다.
탄젠트가 이 빈칸을 메웁니다. 탄젠트는 노멀 맵의 빨강 축이 표면 위에서 어느 쪽인지 알려 줍니다. 탄젠트가 틀리면 요철이 엉뚱한 쪽으로 기울어서, 빛이 반대편에서 비친 것처럼 음영이 생깁니다.
한 점에 세우는 세 축
세 번째 축은 바이탄젠트입니다. 법선과 탄젠트 둘 다에 직각인 방향입니다. 표면 위에서 v 가 커지는 쪽을 가리킵니다. 같은 축을 바이노멀(binormal)이라고 부르는 코드도 흔합니다.
바이탄젠트는 따로 저장하지 않고 계산으로 얻는 경우가 많습니다. 두 방향에 동시에 직각인 방향은 외적이라는 벡터 연산으로 구합니다. 법선과 탄젠트의 외적이 바이탄젠트가 됩니다.
탄젠트·바이탄젠트·법선 세 축이 한 점에 세운 작은 좌표계를 접선 공간이라고 부릅니다. 노멀 맵의 값은 이 좌표계로 적혀 있습니다.
세 축을 한데 묶은 3×3 행렬은 머리글자를 따 TBN(Tangent Bitangent Normal, 탄젠트·바이탄젠트·법선) 행렬이라고 부릅니다. 노멀 맵에서 읽은 법선에 TBN 행렬을 한 번 곱하면 월드 공간의 법선이 나옵니다.
flowchart TD
M["노멀 맵의 색"] --> L["노멀 맵이 적은 법선 · 표면 기준"]
N["정점의 법선"] --> B["바이탄젠트 · 외적으로 구한다"]
T["탄젠트"] --> B
N --> X["TBN 행렬"]
T --> X
B --> X
L --> W["월드 공간 법선 · 조명에 쓴다"]
X --> W
위 도해는 화면의 점 하나에서 벌어지는 일입니다. 정점에 실린 법선과 탄젠트는 삼각형 안쪽 점마다 세 꼭짓점의 값을 섞어 씁니다. 이렇게 사이값을 만드는 일을 보간이라고 부릅니다.
탄젠트를 구하는 계산
모델 파일에 탄젠트가 없으면 위치와 텍스처 좌표에서 계산해 냅니다. 삼각형 하나를 놓고, u 가 1 늘 때 표면 위에서 어느 쪽으로 얼마나 움직이는지를 구합니다. 그 움직임이 탄젠트입니다.
삼각형의 한 변은 3차원 공간의 이동이면서 UV 의 변화이기도 합니다. 그래서 변 하나를 「탄젠트 몇 배 더하기 바이탄젠트 몇 배」로 적을 수 있습니다. 그 몇 배가 그 변을 따라간 u 변화와 v 변화입니다.
변이 둘이므로 미지수가 둘인 연립방정식이 됩니다. 풀면 탄젠트와 바이탄젠트가 함께 나옵니다.
아래는 꼭짓점 p0·p1·p2 로 된 삼각형 하나입니다. 모델은 xy 평면에 놓인 삼각형입니다. 그림은 90도 돌려 붙였습니다.
| 꼭짓점 | 위치 | UV |
|---|---|---|
| p0 | (0, 0, 0) | (0, 1) |
| p1 | (2, 0, 0) | (0, 0) |
| p2 | (0, 2, 0) | (1, 1) |
p0 에서 p1 으로 가면 v 만 1 줍니다. p2 로 가면 u 만 1 늡니다.
아래 코드에서 e1·e2 는 두 변입니다. du·dv 는 그 변을 따라간 UV 변화입니다. r 은 연립방정식을 풀 때 나누는 수의 역수입니다. 나누는 대신 곱합니다.
e1 = p1 - p0 # (2, 0, 0)
e2 = p2 - p0 # (0, 2, 0)
du1, dv1 = 0, -1 # p0→p1
du2, dv2 = 1, 0 # p0→p2
r = 1 / (du1*dv2 - du2*dv1) # 1
T = (e1*dv2 - e2*dv1) * r # (0, 2, 0)
B = (e2*du1 - e1*du2) * r # (-2, 0, 0)
탄젠트 T 가 모델의 x 축이 아니라 y 축을 향합니다. 그림을 돌려 붙였기 때문입니다. 탄젠트는 모델의 축이 아니라 그림의 방향을 따라갑니다. 길이를 1로 맞추면 탄젠트는 (0, 1, 0) 이 됩니다.
정점마다 하나로 다듬기
정점 하나는 삼각형 여럿이 나눠 씁니다. 그래서 정점의 탄젠트는 그 정점에 붙은 삼각형들의 탄젠트를 더해 평균을 냅니다.
삼각형 하나에서 구한 탄젠트는 그 삼각형 면을 따라 눕습니다. 이웃 삼각형들은 기울기가 제각각입니다. 그래서 여러 면의 탄젠트를 평균 내면 정점의 법선과 딱 직각이 되지 않을 수 있습니다.
이를 바로잡으려고 탄젠트에 섞인 법선 방향의 몫을 빼고 길이를 다시 1로 맞춥니다. 그 몫의 크기는 내적으로 잽니다. 내적은 한 방향이 다른 방향 쪽으로 얼마나 향하는지를 재는 벡터 연산입니다. 이 다듬기를 그람-슈미트 과정이라고 부릅니다.
네 번째 값과 뒤집힌 그림
모델을 만들 때는 그림을 아끼려고 좌우가 대칭인 부분에 같은 그림을 뒤집어 붙이곤 합니다. 얼굴의 왼쪽 반과 오른쪽 반이 그림 한 조각을 나눠 쓰는 식입니다. 이런 배치를 UV 미러링이라고 부릅니다.
뒤집어 붙인 쪽에서는 u 가 거꾸로 갑니다. 그래서 탄젠트가 반대쪽을 가리킵니다. v 는 그대로라 실제 v 방향은 법선과 탄젠트의 외적이 내놓는 방향과 반대가 됩니다. 외적만으로는 그림이 뒤집혔는지 알 수 없습니다.
이 뒤집힘을 담으려고 탄젠트를 숫자 네 개로 적는 방식이 널리 쓰입니다. 앞의 셋 xyz 는 방향입니다. 넷째 w 는 +1 이나 -1 인 부호입니다. 바이탄젠트는 외적 결과에 w 를 곱해 얻습니다.
3차원 모델을 담는 파일 형식인 glTF(GL Transmission Format) 2.0 의 TANGENT 속성이 이 꼴입니다. 성분 네 개짜리 실수입니다. xyz 는 길이가 1입니다. w 는 부호입니다.
바이탄젠트는 아래 식으로 구합니다. cross 는 외적입니다.
cross(normal.xyz, tangent.xyz) * tangent.w
구하는 방식이 어긋날 때
노멀 맵은 대개 잘게 쪼갠 고해상도 모델에서 요철을 뽑아 만듭니다. 이 작업을 베이킹이라고 부릅니다. 베이킹하는 도구도 탄젠트를 구해 그 기준으로 법선을 적습니다.
그리는 프로그램이 다른 방식으로 탄젠트를 구하면 두 기준이 조금씩 어긋납니다. 평평한 면에서는 티가 덜 나지만, 이음매나 굽은 면에서 줄이나 얼룩이 보입니다.
그래서 도구끼리 같은 계산법을 맞춰 씁니다. glTF 2.0 파일에 탄젠트가 빠져 있으면 읽는 프로그램이 MikkTSpace라는 계산법으로 채우기를 권합니다(SHOULD).
탄젠트를 싣는 경우와 빼는 경우
탄젠트는 노멀 맵처럼 표면 기준의 방향을 그림에 담는 기법이 있을 때 쓸모가 있습니다. 조명을 정점의 법선만으로 계산하는 모델이라면 탄젠트는 메모리만 차지합니다.
정점 하나에 실수 네 개가 붙습니다. 흔히 쓰는 32비트 실수로 치면 16바이트입니다. 정점이 10만 개인 모델이면 정점 버퍼가 1.6MB 커집니다.
노멀 맵 말고도 결 방향이 필요한 조명이 탄젠트를 씁니다. 머리카락이나 결을 따라 깎은 금속은 빛이 결을 따라 길게 번집니다. 이런 반사를 이방성 반사라고 부릅니다. 결 방향은 탄젠트로 줍니다.
탄젠트를 정점에 싣지 않는 방법도 있습니다. 화면의 점 하나마다 색을 정하는 프로그램을 프래그먼트 셰이더라고 부릅니다. 이 프로그램이 이웃한 점 사이의 위치 변화와 UV 변화를 견줘 그때그때 탄젠트를 구합니다. 메모리를 아끼는 대신 그리는 동안 계산이 늘어납니다.
관련 항목
탄젠트와 함께 한 점의 좌표계를 이루는 축
법선 · 바이탄젠트 · 접선 공간 · 접선 기저 · TBN 행렬
탄젠트가 실려 다니는 정점 데이터
정점 · 정점 속성 · 정점 버퍼 · 텍스처 좌표 · UV 미러링 · glTF
탄젠트를 필요로 하는 셰이딩 기법
노멀 맵 · 범프 매핑 · 패럴랙스 매핑 · 이방성 반사 · 베이킹 · PBR
탄젠트 계산에 쓰는 연산과 알고리즘
벡터 · 외적 · 내적 · 정규화 · 그람-슈미트 과정 · 보간 · MikkTSpace
탄젠트를 읽는 셰이더 단계
셰이더 · 정점 셰이더 · 프래그먼트 셰이더 · 법선 행렬 · 렌더링 파이프라인
탄젠트가 쓰이는 좌표계
탄젠트가 속하는 상위 분류
탄젠트와 이름을 같이 쓰는 수학 개념
접선 · 접벡터 · 삼각함수 · 사인 · 코사인 · 미분
다른 이름: tangent · tangent vector · 탄젠트 벡터 · 접선 벡터