기하학: n차원 공간에 대한 연구
컴퓨터 그래픽스에선 3차원 공간의 물체를 3D 오브젝트라 함
Vector Space
스칼라와 벡터로 이루어진 수학적 공간
스칼라-벡터 또는 벡터-벡터 연산이 가능
Vector: Basis Vector의 합 (Basis Vector: 좌표 축 상의 unit vector)
Affine Space
벡터 공간에 포인트 개념이 추가
벡터-포인트 또는 포인트-포인트 연산이 가능
Euclidean Space
어파인 공간에 거리 개념이 추가
p, q, r: 점
v: 벡터
p = q + αv (점 q에서 벡터 v방향으로 α만큼 이동한 점)
v = r - q (시작점 q에서 끝점 r로 향하는 벡터)
p = αr + (1-α)q [α: 0.0 ~ +1.0] (점 q와 점 r 사이의 선형 보간)
좌표계를 바꾸어 새로운 basis 벡터로 표현 가능

좌표 = 원점 + basis 벡터
p0: 원점
(보통 벡터에는 α, 좌표에는 λ를 사용)
4x4 행렬로 표현하고 빈 곳은 0으로 채움

4x4 행렬
호모지니어스 좌표계
4차원 좌표
(x, y, z, w)
w가 0인 경우 벡터 (α1,α2,α3,0)
w가 1인 경우 점 (λ1,λ2,λ3,1)

벡터와 좌표를 한번에 표현 가능하여 일반화된 좌표라고 불림
4차원 공간의 (x,y,z,w)
w가 0인 경우 3차원 공간의 벡터 (x,y,z)
w가 1인 경우 3차원 공간의 좌표 (x,y,z)
w가 0이 아닌 경우 (x/w,y/w,z/w,1) -> (x,y,z) 형태의 3차원 좌표로 표현
3D에서의 변환
3차원에서의 (x,y,z) 좌표는 0이 아닌 w에 대해서 4차원 좌표 (wx,wy,wz,w)에 대응
한 개의 3차원 좌표가 매우 많은 4차원 좌표에 대응됨
Primitive: 가장 단순한 요소
GL_POINTS / GL_LINES / GL_LINE_STRIP / GL_LINE_LOOP / GL_TRIANGLES ...
Triangle Fan
삼각형을 부채처럼 그리는 방식
vertex0을 고정하여 새로 들어오는 vertex 2개를 이어 삼각형을 그림 (가장 오래된 vertex 1개를 버림)
n+2개의 점으로 n개의 삼각형을 그릴 수 있어 기존 방식보다 3배 빠름
Triangle Strips
길고 납작하게 그리는 방식
새로 들어오는 vertex 3개를 이어 삼각형을 그림 (가장 오래된 vertex 1개를 버림)
마찬가지로 n+2개의 점으로 n개의 삼각형을 그릴 수 있음
Triangle Strips는 랜드스케이프와 같은 지형을 그리는데 유리함
지형은 사각형 격자 모양에서 높이가 다르게 되어있음
사각형 한 줄씩 Triangle Strips 방식으로 쭉 그리면 됨
사각형은 대각선으로 분할하면 삼각형 두개가 나옴
복잡한 물체를 삼각형 형태로 근사시키는 걸 삼각형 근사라고 함
deprecated 됨
사각형은 단일 평면 위에 존재해야 하여 불안정한 기능
대신 2개의 삼각형으로 설정
3차원 물체를 그리기 위해 3D 좌표계 설정 필요
OpenGL의 canonical view volume을 그대로 사용 (왼손 좌표계)
{ 0.0F, 0.5F, 0.0F, 1.0F }, // v0
{ 0.5F, -0.3F, 0.0F, 1.0F }, // v1
{ 0.0F, -0.3F, 0.5F, 1.0F }, // v2
{ -0.5F, -0.3F, 0.0F, 1.0F }, // v3
{ 0.0F, -0.3F, -0.5F, 1.0F }, // v4
glm::vec4 vertPos[] = { // 6 * 3 = 18 vertices
// face 0: v0-v1-v2
{ 0.0F, 0.5F, 0.0F, 1.0F }, // v0
{ 0.5F, -0.3F, 0.0F, 1.0F }, // v1
{ 0.0F, -0.3F, 0.5F, 1.0F }, // v2
// face 1: v0-v2-v3
{ 0.0F, 0.5F, 0.0F, 1.0F }, // v0
{ 0.0F, -0.3F, 0.5F, 1.0F }, // v2
{ -0.5F, -0.3F, 0.0F, 1.0F }, // v3
// face 2: v0-v3-v4
{ 0.0F, 0.5F, 0.0F, 1.0F }, // v0
{ -0.5F, -0.3F, 0.0F, 1.0F }, // v3
{ 0.0F, -0.3F, -0.5F, 1.0F }, // v4
// face 3: v0-v4-v1
{ 0.0F, 0.5F, 0.0F, 1.0F }, // v0
{ 0.0F, -0.3F, -0.5F, 1.0F }, // v4
{ 0.5F, -0.3F, 0.0F, 1.0F }, // v1
// face 4: v1-v4-v3
{ 0.5F, -0.3F, 0.0F, 1.0F }, // v1
{ 0.0F, -0.3F, -0.5F, 1.0F }, // v4
{ -0.5F, -0.3F, 0.0F, 1.0F }, // v3
// face 5: v1-v3-v2
{ 0.5F, -0.3F, 0.0F, 1.0F }, // v1
{ -0.5F, -0.3F, 0.0F, 1.0F }, // v3
{ 0.0F, -0.3F, 0.5F, 1.0F }, // v2
};
glm::vec4 vertColor[] = {
// face 0: red
{ 1.0F, 0.3F, 0.3F, 1.0F, },
{ 1.0F, 0.3F, 0.3F, 1.0F, },
{ 1.0F, 0.3F, 0.3F, 1.0F, },
// face 1: green
{ 0.3F, 1.0F, 0.3F, 1.0F, },
{ 0.3F, 1.0F, 0.3F, 1.0F, },
{ 0.3F, 1.0F, 0.3F, 1.0F, },
// face 2: blue
{ 0.3F, 0.3F, 1.0F, 1.0F, },
{ 0.3F, 0.3F, 1.0F, 1.0F, },
{ 0.3F, 0.3F, 1.0F, 1.0F, },
// face 3: yellow
{ 1.0F, 1.0F, 0.3F, 1.0F, },
{ 1.0F, 1.0F, 0.3F, 1.0F, },
{ 1.0F, 1.0F, 0.3F, 1.0F, },
// face 4: cyan
{ 0.3F, 1.0F, 1.0F, 1.0F, },
{ 0.3F, 1.0F, 1.0F, 1.0F, },
{ 0.3F, 1.0F, 1.0F, 1.0F, },
// face 5: cyan
{ 0.3F, 1.0F, 1.0F, 1.0F, },
{ 0.3F, 1.0F, 1.0F, 1.0F, },
{ 0.3F, 1.0F, 1.0F, 1.0F, },
};
void drawFunc(void) {
glEnable(GL_DEPTH_TEST);
glDepthRange(0.0F, 1.0F);
glClearDepthf(1.0F);
// clear in gray color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// provide the vertex attributes
GLuint locPos = glGetAttribLocation(prog, "aPos");
glEnableVertexAttribArray(locPos);
glVertexAttribPointer(locPos, 4, GL_FLOAT, GL_FALSE, 0, glm::value_ptr(vertPos[0]));
GLuint locColor = glGetAttribLocation(prog, "aColor");
glEnableVertexAttribArray(locColor);
glVertexAttribPointer(locColor, 4, GL_FLOAT, GL_FALSE, 0, glm::value_ptr(vertColor[0]));
// draw the pyramid
glDrawArrays(GL_TRIANGLES, 0, 18); // 18 vertices, 6개의 면
// done
glFinish();
}
앞쪽에 있는 면인 파란 면(face2)과 노란 면(face3)이 보임

면의 바깥쪽을 정의하는 방법
어떤 면이 주어지면 이 면의 바깥쪽이 어딘지 설정해야함
normal vector
법선 벡터
삼각형에 수직인 벡터로 바깥쪽을 향함
normal vector 방향 설정
오른손 법칙: CCW(Counter-Clockwise)
3D 물체는 모든 방향을 면으로 둘러쌈
back face는 front face가 덮어씀
Primitive Assembly 시, 뒷면은 파이프라인에서 축출 (cull)