수학평면에서 곡선 위의 한 점을 지나고, 이 점에서의 곡선에 대한 접선에 수직인 직선. 또는 곡면 위의 한 점을 지나고, 이 점에서의 곡면에 대한 접평면에 수직인 직선.
이걸 왜 구하냐?
➡️ 3D 그래픽에서 조명 효과를 계산하려면 물체 표면의 모든 점에서 '표면 법선(Surface Normal)'이라는 방향 정보가 필요하다.이를 통해 빛이 물체 표면에 도달하는 각도를 계산하여 빛을 계산할 수 있게 해준다.
➕ 3D 공간 좌표계의 "위쪽⬆️ 축"으로 볼 수 있기 때문에, 앞 뒤 구분도 할 수 있게 된다.
즉, 3D 모델링에서 노말 벡터는: 1) 표면의 방향을 정의 2) 빛이 표면에 어떻게 반사될지 결정 3) 셰이딩 계산에 필수적인 요소
그렇다면 노멀 벡터는 어떻게 계산하지?
➡️ 외적(Cross Product)이라는 수학 도구를 사용하면 된다.
*외적이란? 두 벡터를 가지고 만드는 새로운 벡터로, 두 벡터 모두에 수직인 방향을 가리킨다.
삼각형 모양의 평면이 있다고 생각해보자:
삼각형의 세 점을 a, b, c로 생각 (각 점은 x,y,z 좌표를 가짐)
두 개의 선(벡터)을 만든다: 점 좌표끼리 빼면 점 사이의 거리(Distance)가 나온다.
첫 번째 선: a에서 b로 가는 선 (side1) : 벡터1 = B - A
두 번째 선: a에서 c로 가는 선 (side2) : 벡터2 = C - A
이 두 선의 외적(cross product)을 구하면 노멀 벡터가 나온다! : 노멀 벡터 = 벡터1 X 벡터2
방향을 유의하자! 두 벡터의 외적을 구할 때 순서에 따라 노멀 벡터의 방향이 반대가 될 수 있다. 오른손 법칙을 이용해본다면 알 수 있다. 엄지 손가락이 가리키는 방향이 노멀 벡터이다. (플레밍의 왼손법칙 같은 느낌인가보다)
마지막으로 계산된 노멀 벡터를 정규화(normalize)한다 ➡️ 정규화된 노말 벡터 = 노말 벡터 / |노말 벡터|
정규화는 뭐고, 왜 해야 하는 거야?
일단, 정규화란 노멀 벡터의 길이를 1로 만드는 것. 방향 정보는 그대로 유지하면서 크기만 1로 맞추는 것이다.
1. 방향 정보만 필요할 때: 3D 그래픽 계산에서는 벡터의 크기보다 방향이 더 중요하다. 2. 빛 반사 계산: 3D 물체가 얼마나 밝게 보일지 계산할 때, 빛의 방향과 표면의 노멀 벡터 사이의 각도를 계산한다. 이때 두 벡터가 모두 정규화되어 있으면 두 벡터의 내적(dot product)이 바로 코사인 값이 되어 계산이 훨씬 간단해진다. 즉, 성능 향상이 된다. 정규화된 벡터를 사용하면 반복되는 계산에서 매번 벡터의 길이를 고려할 필요가 없어 컴퓨터 자원을 절약할 수 있다.
쉽게 비유하자면, 정규화는 "나침반의 역할"과 같다. 나침반은 화살표의 길이가 아니라 방향이 중요한 것처럼.
2) 탄젠트 벡터 Tangent Vector
탄젠트 벡터는 표면 위의 한 점에서 표면에 닿아있는(접하는) 방향을 가리키는 벡터. 이 벡터는 표면 위에 놓여있으며, 그 점에서 표면을 따라 움직이는 방향을 나타낸다.
탄젠트 벡터의 용도는 뭘까?
텍스처 매핑: 3D 모델에 이미지 텍스처를 입히려면, 모델 표면의 각 지점에서 텍스처의 어느 부분을 사용할지 결정해야 한다. 탄젠트 벡터는 텍스처의 가로 방향(U 좌표)을 결정하는 데 사용된다.
🤔여기서 궁금증... : 그러면 텍스처의 세로 방향인 V좌표는 어디다가 팔아 먹은걸까? ➡️ 바이탄젠트 벡터(아래 참고!)
노멀 매핑: 실제로 표면 형태를 변형하지 않고도 울퉁불퉁한 느낌을 주는 기법에서 쓰인다. 이때 탄젠트, 바이탄젠트(비탄젠트), 노멀 벡터로 구성된 "탄젠트 공간(Tangent Space)"이 필요하다. (밑에서 알아보자)
애니메이션과 시뮬레이션: 곡선이나 표면을 따라 움직이는 물체의 방향을 결정할 때 사용다.
탄젠트 벡터 계산 방법
노멀 벡터를 구한다.
임의의 방향 벡터를 정한다 ➡️ 임의 방향 벡터를 U값을 기준으로 잡고 해야 한다.
(노멀 벡터와 탄젠트 벡터의 외적을 구해 바이탄젠트를 얻는다)
더 정확한 방법은 UV 텍스처 좌표와 3D 모델의 위치 정보를 함께 사용해 계산하는 것이다.
탄젠트 벡터, 바이탄젠트 벡터, 노멀 벡터는 함께 "TNB 프레임" 또는 "탄젠트 공간(Tangent Space)"이라 불리는 좌표계를 형성한다. 이 세 벡터는 각각 서로 직각을 이루며, 3D 그래픽에서 표면의 특성을 완전히 표현하는 데 사용된다.
3) 비탄젠트 벡터 Bitangent Vector
탄젠트 벡터는 텍스처의 U좌표(가로 방향)를 담당하지만, V좌표(세로 방향)도 필요하다. 이를 위해 "바이탄젠트(bitangent)" 또는 "비노멀(binormal)"라고 부르는 또 다른 벡터를 사용한다.
➡️ 바이탄젠트 벡터는 노멀 벡터와 탄젠트 벡터 모두에 수직인 세 번째 벡터...! 이 벡터는 텍스처의 V좌표(세로 방향)를 결정하는 데 사용된다.
왜 필요하지? 노말 맵은 텍스쳐 좌표 (UV) 기준으로 저장되고, 실제 조명 계산은 월드 좌표계 기준으로 진행되기 때문에, 노말 맵을 올바르게 적용하려면 <UV공간 → 월드 공간> 변환해야 한다. 따라서 완전한 3D 좌표계인 "TBN 좌표계(아래에서 더 자세히 설명)"가 필요하다. 비노멀이 없으면 노말 맵의 Y(V)축 방향을 변환할 수 없어서 조명이 이상하게 나온다.
변환 공식
비탄젠트 벡터 계산 방법 탄젠트 계산하는 방법과 동일하다. ➡️비탄젠트 벡터(B) = 노멀 벡터(N) X 탄젠트 벡터(T)
2. UVW, 탄젠트 스페이스, 텍스쳐 맵핑에 대해서 조사하고 원리 알아보기
1) UVW
UVW 좌표는 3D 그래픽에서 텍스처를 물체 표면에 올바르게 입히기 위해 사용하는 좌표계. (일반적으로 0~1의 값을 가진)
U, V 좌표: 텍스처 이미지의 가로(U)와 세로(V) 위치. 예를 들어, 텍스처의 어느 부분을 물체에 입힐지 결정할 때 사용.
W 좌표: 때로는 텍스처 매핑을 더 세밀하게 조정하거나, 3D 효과를 주기 위해 추가되는 좌표. 꼭 필요하지는 않지만, 복잡한 텍스처링 작업에서 유용하다.
✨XYZ와의 차이점 XYZ는 전체 3D 공간에서의 절대적인 위치를 정의하는 데 사용되고, UVW는 주로 객체 표면 위의 상대적 위치를 정의하는 데 사용된다.
XYZ는 전역 원점을 기준으로 하지만, UVW는 일반적으로 특정 객체나 표면을 기준으로 합니다
XYZ는 무한한 범위를 가질 수 있지만, UVW는 종종 0과 1 사이의 값으로 정규화됩니다(특히 텍스처 매핑에서)
2) 탄젠트 스페이스 Tangent Space
앞서 탄젠트 벡터에 대해서 알아볼 때, 탄젠트 스페이스에 대한 언급이 나왔다.
탄젠트 스페이스는:
한 점의 노말(법선) 벡터, 탄젠트(접선) 벡터, 그 둘을 외적한 바이노멀(비탄젠트) 벡터를 축으로 하는 공간
오브젝트의 어떤 점 Normal을 수직 축으로 하는 공간 ➡️ 표면 공간이라고 불리는 이유!
삼각비의 정의
이게 왜 필요하지?
노멀 맵이나 디스플레이스먼트 맵(텍스처의 질감이라고 생각하자)같은 텍스처를 사용할 때, 그 텍스처 속에는 "이 표면이 어느 방향으로 기울어져 보이면 좋겠다"라는 정보가 들어가 있다고 한다. 이 정보, 즉 벡터를 3D 공간에서 계산하려면 그 표면의 작은 점에서의 탄젠트 스페이스가 필요한 것이다! ▶ 텍스처 픽셀에서 얻은 정보(탄젠트 스페이스를 기준으로 기울어진 방향)를 ▶ 월드 스페이스 방향으로 변환한 다음, ▶ 빛을 계산해서 "빛이 어느 정도 세기로 반사가 되고! 그림자가 어떻게 지고 있는가!"를 구하게 한다.
좀 더 자세하게 설명을 해보자면,
3D 물체를 2차원의 모니터 스크린 상에 표현하기 위해! 3차원으로 보이도록 하기 위한 정보가 필요한데,
이 정보가 셰이딩(음영)이다. ➡️ 이 정보를 계산하기 위해서 각 폴리곤 평면에서의 법선(노멀)으로 폴리곤의 기울기를 만들고, 나머지 두 접선 축(탄젠트, 비탄젠트)으로 어느 방향으로 기울었는지를 알아내는 것이다. 그리고 다시 한번 얘기하면 이 세개의 축이 존재하는 공간을 탄젠트 스페이스라고 한다...!
폴리곤은 3개 이상의 꼭짓점과 변으로 이루어진 평면 도형. 주로 삼각형 폴리곤이 사용. 폴리곤의 개수가 많을수록 모델의 정밀도가 높아진다!
폴리곤 관련 용어
정점(Vertex): 폴리곤의 꼭짓점
변(Edge): 폴리곤의 변
면(Face): 폴리곤의 면
폴리곤 메시(Polygon Mesh): 폴리곤들의 집합으로 이루어진 3D 모델
🤔만약 법선(노멀)에 대한 데이터가 없다면? 평면의 모니터 스크린에서 이게 3D 물체인지 2D 물체인지 구분을 할 수 없게 된다.
3) 텍스쳐 맵핑 Texture Mapping
2차원 이미지(텍스처)를 3차원 물체표면에 입히는 기법!
왜 필요하지? ➡️ 모델링만으로 디테일을 구현하려면 폴리곤이 많아져 성능 저하로 이어진다. 따라서 텍스처 맵핑을 이용해서 비교적 적은 폴리고으로도 디테일을 구현할 수 있다! (텍스처: 색, 무늬, 질감 정보 등) ➡️ 로우 폴리곤(저해상도) 모델에 고해상도 모델의 표면 디테일을 '속이는' 방법으로 텍스처 매핑을 사용하는 것이다.
텍스처 맵핑의 기본원리: 1. 래스터화 : 3D 모델을 컴퓨터(GPU)가 화면에 그릴 때 화면 픽셀마다 "어느 폴리곤(삼각형)의 어디(UV)"인지를 계산한다. 2. UVW 좌표 : 3D 모델의 각 버텍스(Vertex)마다 2D 이미지에서 위치를 나타내는 UV 좌표를 매핑. 3. 삼각형 보간 : 3D 모델을 컴퓨터가 화면에 그릴 때, 모델을 폴리곤(삼각형) 단위로 나눈 다음 삼각형의 각 꼭짓점을 찾아서 UV 좌표가 정해지면, 나머지 내부의 점들은 자동으로 보간을 통해 계산되어 진다. (삼각형 꼭짓점 정보를 통해 삼각형 내부 픽셀에 걸쳐서 부드럽게 이어주는 과정)
여러 가지 텍스처 맵핑 기법 1. 컬러 맵핑(디퓨즈 맵) : 물체 표면의 색을 표현. 예를 들어 나무 무늬, 벽돌 무늬 등 2. 노멀 맵핑(Normal Mapping) : 표면의 미세한 굴곡(울퉁불퉁함)을 가짜로 표현. 모델의 형태가 변하는 것이 아니고, 빛이 반사되는 방향을 조정해 울퉁불퉁해 보이게 만드는 거다. 3. 범프 맵핑(Bump Mapping) : 노멀 맵핑과 유사하지만, 더 단순한 방식으로 표면의 굴곡을 흉내낸다. 4. 디스플레이스먼트 맵핑(Displacement Mapping) :가짜로 모델의 표면을 변형시켜서 울퉁불퉁하게 만는다. 노멀 맵핑보다 더 사실적인 표현이 가능하지만, 계산 비용이 많이 들기 때문에 고품질 렌더링(영화, 광고 등)에 쓰인다. (렌더링 파이프라인을 공부해야 더 이해가 될 수 있다) 5. PBR(물리 기반 렌더링) 맵 : 최근 그래픽에서는 PBR 기법을 사용해 반사도(Metalness), 거칠기(Roughness), AO(Ambient Occlusion) 등 다양한 맵을 합쳐 사실적인 재질 표현을 한다고 한다. (이후에 알아보자)
🤔노멀 맵과 범프 맵은 뭐가 다르지? 범프 맵(Bump Map) : 흑백 이미지를 사용하여 표면의 높낮이 정보를 표현하는 기법. 픽셀의 밝기에 따라 가짜 깊이를 적용하여 명암 효과를 줌. ➡️ 단점: 법선 방향을 직접 수정하지 않기 때문에, 입체감을 표현하는 데 한계가 있음
노멀 맵(Normal Map) RGB 값을 이용해 법선 벡터를 조작하여 입체감을 더 정확하게 표현. 범프 맵보다 더 정밀한 조명 효과를 줄 수 있음.
즉, 범프 맵이 단순한 높이 정보라면, 노멀 맵은 실제 표면의 방향을 직접 수정하는 것에 가까움
3. 텍스쳐 채널 RGBA의 "쓰임새"와 "데이터 측면"에서 조사하기
1) 텍스쳐 채널 RGBA의 쓰임새
R (Red), G (Green), B (Blue) : 색상 표현, 조합을 통한 다양한 색상
A (Alpha) :
투명도 제어: 알파 채널은 해당 픽셀의 투명도(불투명도)를 나타낸다.
혼합 효과: 알파 값을 이용해 이미지와 이미지, 혹은 3D 모델의 표면을 자연스럽게 혼합(블렌딩)할 수 있다.
B(파랑) 채널이 높을수록(밝을수록) 법선 벡터가 더 원래의 표면 방향을 유지하는 경향이 있다.
R (Red)
X축 방향 (좌우)
G (Green)
Y축 방향 (상하)
B (Blue)
Z축 방향 (깊이, 화면에서 튀어나오거나 들어가는 방향)
3) TBN 행렬(Tangent-Bitangent-Normal Matrix)
TBN 행렬은 노멀 맵이 저장된 텍스처 좌표(UV 공간)에서의 법선 벡터를 월드(혹은 로컬) 좌표계로 변환하기 위해 필요하다. 즉, 노멀 맵의 정보를 실제 3D 공간에서 올바르게 사용할 수 있도록 변환하는 역할을 한다.
왜냐하면 조명 계산은 텍스처가 아니라 실제 3D 공간(월드 공간 또는 로컬 공간)에서 이루어지기 때문이다.
TBN 행렬
>> 노멀 맵 벡터 변환 과정
1) 노멀 맵은 UV 좌표를 기준으로 노멀 정보를 저장하므로, 처음에는 "탄젠트 스페이스(텍스처 공간)"에서 노멀 벡터가 정의됨.
예를 들어, 기본 노멀 맵은 (R=0.5, G=0.5, B=1.0) → 변환 후 (X=0, Y=0, Z=1) (정규화)
2) 하지만 실제 조명은 3D 월드 공간에서 계산됨.
즉, 텍스처에 저장된 법선 방향을 월드(혹은 로컬) 좌표계로 변환해야 함.
➡️이 변환을 수행하는 것이 TBN 행렬이며, 이를 통해 텍스처 공간에서 월드(혹은 로컬) 공간으로 법선 방향을 변환할 수 있음.
🤔왜 TBN 행렬 없이 계산할 수 없을까? : UV 좌표와 3D 모델의 방향이 다를 수 있다. UV가 모델의 표면을 펼친 형태로 저장되므로, UV 기준의 X(Y), Y(Z) 방향이 실제 월드에서의 방향과 일치하지 않을 경우가 발생할 수 있다. 예를 들어, UV 공간에서의 "오른쪽"이 실제 모델의 "왼쪽"이 될 수도 있다. 혹은 모델이 회전하거나 변형될 경우, 노멀 방향이 잘못된다면 노멀 맵이 올바르게 적용되지 않아 빛 표현이 깨지게 된다.
따라서, 텍스처 공간에서 월드(또는 로컬) 공간으로 변환이 필요하며, 이를 위해 TBN 행렬이 필수적이다!