블로그에서는 그래픽스와 관련한 공부를 DirectX로 진행하지만, 기본적인 개념은 openGL을 사용하기도 합니다. 이번 포스트에서는 기초적인 지식을 기록합니다.
이 포스트는 경희대학교 게임 그래픽 프로그래밍 수업자료를 바탕으로 합니다.
1. vertex 계산
컴퓨터에서는 mesh를 vertices로 나누어 계산하게 된다.
▪ vertices는 vertex array라는 이름의 메모리 공간에 열거된다.
▪ 세 꼭짓점을 선형 순서로 읽어 삼각형을 만든다.
▪ DirectX에서 vertex가 들어가는 순서는 LHS이다. (openGL의 경우 RHS)
▪ vertex array에 저장되는 데이터는 vertex 위치 뿐만 아니라, 추가적인 정보(색상, 법선 등)가 포함된다.
위와 같이 처리하면, vertex array에 중복으로 데이터가 포함되어 심각한 메모리 낭비를 가져온다
(위의 사진처럼 t1, t2, t3 세 개 단위로 끊어 삼각형을 만든다, 그러나 중복되는 데이터가 포함된다)
따라서, 컴퓨터는 조금 더 효율적인 index array를 사용하는 방법으로 vertex를 처리한다.
▪ vertex array에 정점을 넣고, index array라는 배열을 따로 만든다.
▪ 각 vertex는 vertex array에서 한 번만 저장되므로, 중복을 피할 수 있다.
▪ vertex를 참조하여 삼각형을 그릴 때는 index array를 보고 그리게 된다. 이렇게 하면 vertex array에는 중복이 일어나지 않는다.
코드의 예시는 아래와 같다.
DrawIndexPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2)순서대로 (타입, BaseVertexIndex, MinIndex, NumVertices, StartIndex, 그릴 삼각형 개수)
2. Surface Normals
▪ Normal은 주어진 점에서 접하는 표면에 수직인 벡터이다.
▪ 특정 지점에서 물체 표면의 밝기는 해당 지점의 법선(Normal)과 빛의 방향이 이루는 각도에 따라 달라진다. 서로 마주보면 매우 밝을 것이다. 각도가 같으면 빛이 닿지 않는 곳이다.
▪ Surface normals는 triangle normals과 vertex normals으로 분류된다.
Surface Normals - Triangle normal
▪ 주어진 삼각형(p1, p2, p3)에서 v1은 첫 번째 정점(p1)과 두 번째 정점(p2)을 연결하는 벡터라고 하자. 마찬가지로 첫 번째 정점(p1)과 세 번째 정점(p3)을 연결하는 벡터를 v2로 하자. 그러면 오른손 법칙에 따른 외적을 이용하여 삼각형 법선을 계산할 수 있다.
▪ 모든 normal vector는 기본적으로 unit vector로 만들어진다.
▪ p1, p2, p3는 시계 반대 방향(CCW)으로 정렬된다.
위 그림처럼 v1과 v2를 외적한 Normal의 방향을 알 수 있다.
Counter-clockwise(RHS) vs clockwise(LHS)
▪정점을 시계 방향(CW), 즉 (p1, p3, p2)로 정렬한다면
▪ normal은 반대 방향이다.
▪ 법선 방향은 꼭짓점 순서에 따라 다르기 때문에 이를 반드시 잘 확인해야 한다.
▪ 컴퓨터 그래픽에서 surface normal은 다면체를 가리켜야 한다. 이를 위해 verticies의 CCW 순서가 필요하다.
Surface Normals – Vertex normal
버텍스들이 어디를 보고 있는가는 어떻게 정의할까?
▪ triangle normals 보다 더 중요한 것이 vertex normal이다. vertex normal으로 정점이 샘플링하는 매끄러운 표면 점의 normal에 근접하도록 normal을 vertex에 할당할 수 있다.
▪ vertex normal은 vertex를 공유하는 모든 삼각형의 normal을 평균화하여 정의할 수 있다.
vertex normal은 vertex array의 필수 구성 요소임을 기억하자
위의 사진처럼 주변 삼각형 normal의 평균을 구해서 vertex normal을 구한다. 이 방식으로, 부드러운 surface를 구현할 수 있다.
다만 이처럼 vertex normal을 이용해서 brightness를 표현할 때, 오히려 각진 표현을 하지 못하는 단점이 있다. 이는 face 별로 각각 따로 normal 정보를 계산하여 각을 살리거나 면에 새로운 작은 면을 삽입하여 각을 주는 방식으로 해결 가능하다.