Vector
셰이더에서는 물체의 재질 등을 표현하기 위해 여러 연산이 자주 발생하기 때문에 수학적 지식이 많이 동반됩니다.
특히 수학적 연산이 많이 소요되는 분야는 라이팅 관련 분야인데, 표면과 그에 비추는 빛만 해도 표면 벡터(Surface)와 조명 벡터(Directional Light)의 방향 및 크기가 계산에 이용됩니다.
앞서 말한 벡터는 셰이더 및 그래픽스 분야에서 중요한 개념 중 하나이며, 벡터 자체는 크기와 방향만을 가지고 있는데, 이를 통해 위치, 방향, 속도, 색상, UV 등을 표현할 수 있는 범용성을 가지고 있습니다.
벡터의 길이는 흔히 알려져 있는 피타고라스의 정리를 이용하여 구할 수 있는데
이러한 성질을 이용하여 여러 벡터의 길이를 1이라는 고정된 길이로 조정하는 단위화(Normalize)를 수행할 수 있습니다.
이러한 단위화가 중요한 이유는, 벡터의 길이를 1로 고정해서 얻을 수 있는 이점들이 많기 때문입니다. 예를 들어, 물체 사이의 거리로만 표현되던 벡터들이 단위화를 거치면 모두 고정된 길이가 되기 때문에, 물체의 방향을 가리킬 수 있게 됩니다.
또한, 벡터는 여러 연산을 통해서 새로운 정보들을 도출해낼 수 있는데, 덧셈과 뺄셈 이외에도 중요한 내적과 외적이 존재합니다.
벡터의 내적(Inner Product or Dot Product)
내적은 벡터 대수학에서 정의하는 두 가지 곱셈 중 하나이며, 연산이지만 내적의 결과는 벡터가 아닌 스칼라 값이 됩니다.
벡터의 내적을 구하는 공식은 다음과 같습니다.
①은 두 벡터의 각은 모르고 벡터의 성분만을 알고 있을 경우 사용할 수 있는 공식이며, ②는 두 벡터의 각과 크기를 알고 있을 경우 사용할 수 있는 공식입니다. 하지만 벡터의 내적만이 필요할 경우, 삼각함수는 연산이 많이 들기 때문에 ①의 공식을 많이 씁니다.
이러한 내적의 성질을 활용하여 다음과 같은 것들을 알 수 있습니다.
1. 두 벡터의 사이각을 내적을 통해 구할 수 있습니다.
두 벡터의 성분을 알고 있다면, 크기를 알 수 있고, 내적 계산과 를 통해 구할 수 있습니다.
2. 어떤 벡터에서 다른 벡터에 수직으로 내린 길이(투영 길이)를 구할 수 있습니다.
투영 길이를 통해 벡터 a가 벡터 b의 방향으로 얼마만큼 뻗어있는지 알 수 있습니다.
3. '나'의 방향 벡터기가 있을 때, 적이 '나'의 앞에 있는지 뒤에 있는지 판단할 수 있습니다.
적과 '나' 사이의
하지만 이는 적이 나의 앞에 있냐, 뒤에 있냐를 알 수 있을뿐, 적의 왼쪽 앞인지 오른쪽 앞인지는 알 수 없습니다.
이는 뒤에 나올 벡터의 외적을 이용하여 알 수 있습니다.
4. 적이 '나'의 시야각 안에 들어와 있는지 판단할 수 있습니다.
'나'의 시야각을 θ라고 한다면, 적과의 내적을 통해 나오는 각도가 θ/2를 넘지 않아야 시야각 내에 존재한다는 것을 알 수 있습니다.
5. 점과 평면 간의 최단 거리를 구할 수 있습니다.
벡터 BA와 평면의 법선 벡터(Normal Vector)의 내적을 구하면, ||BA|| * ||Normal Vector|| * cosθ가 됩니다.
여기서 법선 벡터가 단위화된 벡터라면, 위의 값이 곧 최단거리가 됨을 알 수 있습니다.
벡터의 외적(Outer Product or Cross Product)
벡터 수학이 정의하는 두번째 형식은 외적입니다. 스칼라로 계산되는 내적과는 달리, 외적의 결과는 또 다른 벡터입니다. 두 벡터를 외적하여 나오는 다른 벡터의 가장 큰 특징은 앞의 두 벡터와 서로 직각을 이룬다는 것입니다.
벡터의 외적을 구하는 공식은 다음과 같습니다.
A x B 외적 벡터의 방향은 수학에서는 오른손 좌표계를 사용하며, 게임은 엔진이 사용하는 좌표계에 따라 다르다고 합니다. (OpenGL에서는 오른손 좌표계, Unity나 Unreal에서는 왼손 좌표계)
여기서 외적인 C의 방향을 알려면, 먼저 A 방향으로 손바닥을 놓고 B의 방향으로 손바닥을 구부릴 때의 엄지의 방향이라고 생각하면 편합니다.
여기서 왼손 좌표계면, A(검지)를 X축, B(중지)를 Y축, C(엄지)를 Z축이라고 생각해도 편할것 같습니다. (그림은 오른손 좌표계)
이러한 외적의 성질을 활용하여 다음과 같은 것들을 알 수 있습니다.
1. 평면의 법선 벡터를 구할 수 있습니다.
두 벡터가 같은 평면에 있다고 가정하면, 두 벡터의 외적은 자연스럽게 평면의 법선 벡터가 됩니다.
2. 평면이 앞면인지, 뒷면인지를 알 수 있고, 이를 컬링(Culling)할 때 사용할 수 있습니다.
앞서 말한대로 외적을 통해 평면의 법선벡터를 구할 수 있으면, 이와 카메라 방향 벡터와의 내적으로 구한 cosθ을 통해 평면이 카메라를 기준으로 앞면인지, 뒷면인지를 알 수 있습니다.
위의 그림대로, 보이는 앞면이면 cosθ가 음수가 되고, 보이지 않는 뒷면이면 cosθ가 양수가 됩니다. 이를 통해 보이지 않는 뒷면을 렌더링에서 제외시키는 것을 백페이스 컬링(Backface Culling)이라고 합니다.
3. 적이 '나'의 왼쪽에 있는지, 오른쪽에 있는지 판별할 수 있습니다.
내적이 두 벡터의 cosθ 값을 구할수 있었다면, 외적은 위의 공식을 통해 sinθ 값을 구할 수 있습니다. 그리고 sinθ는θ가 양수일 때는 같이 양수, 음수일 때는 같이 음수이므로 이를 통해 적이 왼쪽에 있는지, 오른쪽에 있는지를 판단할 수 있습니다.
자료 출처
1. https://www.youtube.com/watch?v=r_eatgPFQYg&t=6848s
2. https://hellowoori.tistory.com/46