본문 바로가기

OpenGL Study

OpenGL "Face Culling"

[FACE CULLING]

1.  Before

- face culling

: 모든 면을 확인하여 viewer의 관점에서 front facing한 면은 렌더링하고 back facing한 면은 폐기하여 fragment shader의 호출을 줄이는 기능

- OpenGL에게 현재 사용 중인 면들이 실제로 앞쪽 면인지 뒤쪽 면인지를 알려주어야한다

: OpenGL은 vertex data의 winding 순서를 분석한다

2. Winding Order

- 삼각형 vertex들을 정의할 때 시계 방향 또는 반시계 방향으로 특정 순서를 정의한다

: 각 삼각형은 3개의 vertex를 가지고 있고, 우리는 이 3개의 vertex들을 삼각형의 중앙을 바라보았을 때의 winding 순서로 지정한다

float vertices[] = {
    // clockwise
    vertices[0], // vertex 1
    vertices[1], // vertex 2
    vertices[2], // vertex 3
    // counter-clockwise
    vertices[0], // vertex 1
    vertices[2], // vertex 3
    vertices[1]  // vertex 2  
};

- 위 이미지와 코 같이 먼저 vertex 1을 정의하고 vertex 2나 3을 정의할 수 있다

: 삼각형의 winding 순서를 정의하는 과정이다

- 각 삼각형을 이루고 있는 3개의 vertex들은 winding 순서를 가지고 있고, OpenGL은 렌더링할 때 이 정보를 사용하여 삼각형이 front-facing인지 back-facing인지를 결정한다

: 기본적으로 반시계 방향으로 정의된 삼각형들이 front-facing 삼각형으로 처리된다

- 실제 winding 순서는 vertex shader가 이미 실행되고 난 후의 raterization 단계에서 계산도니다

- 이후 vertex는 viewer의 관점에서 보이게 된다

- viewer가 대면하고 있는 모든 삼각형 vertex들은 확실히 정확한 winding 순서로 이루어져 있지만, 큐브의 다른 면의 삼각형 vertex들은 winding 순서가 반대로 된 채로 렌더링된다

: 결과적으로 우리가 대면하고 있는 삼각형들은 front-facing 삼각형으로 보이게 되고, 뒤에 있는 삼각형들은 back-facing 삼각형으로 보이게 된다

- vertex data에서 우리는 두 삼각형을 viewer의 시점에서 반시계 방향으로 정의했지만 viewer의 방향으로부터 뒤에 있는 삼각형은 시계 방향으로 렌더링된다 (뒤에 있는 삼각형도 동일하다)

: 이는 viewer의 시점에서 보이지 않는 면들을 폐기하는 것을 의미한다

3. Face Culling

float cubeVertices[] = {
    // Back face
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // Bottom-left
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
     0.5f, -0.5f, -0.5f,  1.0f, 0.0f, // bottom-right         
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // bottom-left
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
    // Front face
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
    -0.5f,  0.5f,  0.5f,  0.0f, 1.0f, // top-left
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
    // Left face
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
    -0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-left
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
    // Right face
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right         
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
     0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left     
    // Bottom face
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
     0.5f, -0.5f, -0.5f,  1.0f, 1.0f, // top-left
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
    // Top face
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right     
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
    -0.5f,  0.5f,  0.5f,  0.0f, 0.0f  // bottom-left        
};

- 지난 장에서 사용한 큐브의 vertex data는 반시계 방향의 winding 순서로 정의되지 않았으므로, 위 코드를 사용해 반시계 방향으로 수정한다

glEnable(GL_CULL_FACE);

- GL_CULL_FACE option을 사용하여 face culling을 활성화한다

- 이 시점부터 앞쪽 면이 아닌 모든 면들은 폐기된다 

- 이 기능은 오직 큐브처럼 닫힌 도형에서만 동작한다

: 이전 장의 잔디를 그릴 떄에는 face culling을 비활성화 해야한다

glCullFace(GL_FRONT);

- glCullFace 함수의 option을 통해 폐기할 면의 유형을 선택한다

GL_BACK : 뒷쪽 면만 폐기한다 (기본값)
GL_FRONT : 앞쪽 면만 폐기한다
GL_FRONT_AND_BACK : 앞쪽/뒷쪽 면 모두 폐기한다

glFrontFace(GL_CCW);

- glFrontFace 함수를 사용해 OpenGL에게 폐기한 면을 포함한 시계방향의 면들이 후면이 아니라 전면이라고 말해준다

- 기본 option 값은 GL_CCW로 반시계 방향을 나타낸다 (GL_CW는 시계방향)

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);

- OpenGL에게 전면은 이제부터 시계방향이라고 말해줌으로써 winding 순서를 반대로 할 수 있다

- 위 코드를 실행시키면 큐브의 후면만 렌더링되어 출력된다

glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);

- 반시계 방향의 winding 순서로 전면을 폐기함으로써 동일한 결과를 얻을 수 있다

'OpenGL Study' 카테고리의 다른 글

OpenGL "Cubemaps"  (0) 2023.02.08
OpenGL "FrameBuffers"  (0) 2023.02.07
OpenGL "Blending"  (1) 2023.02.01
OpenGL "Stencil testing"  (0) 2023.02.01
OpenGL "Depth Testing"  (0) 2023.01.31