모든 점과 선분은 항상 front facing
triangle은 front/back face 구분
카메라가 물체 안으로 들어가면 normal vector를 뒤집어야함
CCW -> CW로 전환
꼭짓점의 순서는 그대로지만 법선 벡터가 반대로 향함
glFrontFace(mode)
법선 벡터의 방향을 지정
mode: GL_CCW/GL_CW
glCullFace(mode)
어느 면을 컬링할지 지정
mode: GL_BACK/GL_FRONT
glEnable(GL_CULL_FACE) / glDisable(GL_CULL_FACE)
페이스 컬링 활성화/비활성화
Tringle Strips
모든 삼각형의 법선 벡터가 균일하게 나오도록 번갈아서 vertex 순서를 반대로 그림
일관되게 CCW 방향 유지
OpenGL의 canonical view volume은 왼손 좌표계
카메라로부터 멀어지는 위치로 Z 증가

좌표계 충돌 현상
오른손 좌표계의 좌표를 OpenGL에 그리면 법선 벡터가 CW로 설정되는 문제 발생
모든 z좌표를 negate하여 CCW 유지
혹은 모델링 단계부터 왼손 좌표게를 사용 (DirectX)
vertex shader 프로그램
OpenGL에선 오른손 좌표계의 물체를 받아 z좌표를 negate하는 방식으로 주로 처리
#version 330 core
in vec4 aPos; // vertex position: attribute
in vec4 aColor; // vertex color: attribute
out vec4 vColor; // varying color: varying
void main(void) {
gl_Position = aPos;
gl_Position.z *= -1.0F; // negation
vColor = aColor;
}
y축을 중심으로 물체를 회전
y축을 기준으로 좌표계를 보면 zx 평면에 대하여 2차원 회전을 적용하는 것과 같음
#version 330 core
in vec4 aPos; // vertex position: attribute
in vec4 aColor; // vertex color: attribute
out vec4 vColor; // varying color: varying
uniform float uTheta; // rotation angle: uniform
void main(void) {
// zx 평면에 대하여 회전 연산
gl_Position.z = aPos.z * cos(uTheta) - aPos.x * sin(uTheta);
gl_Position.x = aPos.z * sin(uTheta) + aPos.x * cos(uTheta);
gl_Position.yw = aPos.yw;
gl_Position.z *= -1.0F; // negation
vColor = aColor;
}
float theta = 0.0F;
system_clock::time_point lastTime = system_clock::now();
void updateFunc(void) {
system_clock::time_point curTime = system_clock::now();
milliseconds elapsedTimeMSEC = duration_cast<milliseconds>(curTime - lastTime); // in millisecond
theta = (elapsedTimeMSEC.count() / 1000.0F) * (float)M_PI_2; // in <math.h>, M_PI_2 = pi/2
}
y축을 기준으로 회전하는 피라미드

피라미드의 색상을 vertex 단위로 지정
glDrawElements()
인덱스 배열로 데이터를 간접적으로 전달 가능
main 코드
필요한 vertex 정보만 입력
glm::vec4 vertPos[] = { // 5 vertices
{ 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 vertColor[] = { // 5 colors
{ 1.0F, 1.0F, 1.0F, 1.0F, }, // v0: white
{ 1.0F, 0.3F, 0.3F, 1.0F, }, // v1: red
{ 0.3F, 1.0F, 0.3F, 1.0F, }, // v2: green
{ 0.3F, 0.3F, 1.0F, 1.0F, }, // v3: blue
{ 1.0F, 1.0F, 0.3F, 1.0F, }, // v4: yellow
};
GLuint indices[] = { // 6 * 3 = 18 indices
0, 1, 2, // face 0: v0-v1-v2
0, 2, 3, // face 1: v0-v2-v3
0, 3, 4, // face 2: v0-v3-v4
0, 4, 1, // face 3: v0-v4-v1
1, 4, 3, // face 4: v1-v4-v3
1, 3, 2, // face 5: v1-v3-v2
};
void drawFunc(void) {
...
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]));
GLuint locTheta = glGetUniformLocation(prog, "uTheta");
glUniform1f(locTheta, theta);
// draw the pyramid
glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_INT, indices); // 18 indices
...
}
꼭짓점에 지정한 색상에 따라 이중 선형 보간된 피라미드가 그려짐

glDrawArrays
18 vertices 4 floats = 72 floats
18 colors 4 floats = 72 floats
face 마다 다른 색상 설정 가능
glDrawElements
5 vertices 4 floats = 20 floats
5 colors 4 floats = 20 floats
18 indices = 18 integers
효과적인 메모리 사용