Home [learn-opengl] Advanced OpenGL: Face culling
Post
Cancel

[learn-opengl] Advanced OpenGL: Face culling

Face culling

  • 큐브를 생각해보자

    • 어느 방향에서 볼 수 있는 최대 면들의 개수는 3개이다.
    • 다른 면들은 보이지 않는다.
    • 이들을 폐기하면, 50%이상 비용을 절약할 수 있다.
  • 문제는 view 입장에서 보이지 않는 면인지 어떻게 알 수 있는가이다.

    • 닫힌 하나의 도형(closed shape)를 생각해보자
    • 각 면들은 2개의 양쪽면을 가지고 있다.
    • 한쪽은 사용자와 대면하고 있고, 다른 한쪽은 사용자와 등지고 있다.
  • Face Culling:

    • viewer와 대면하고 있는 면들만 렌더링하는 것
    • OpenGL은 모든 면들을 확인하여, front facing 한 면은 렌더링하고
    • back facing한 모든 면들은 폐기하여 fragment shader 호출을 많이 줄여준다. (fragment shader 호출은 비용이 많이든다)
    • OpenGL은 이에 대해 vertex 데이터의 winding 순서를 분석하는 똑똑한 방법을 사용한다.

Winding order

  • 삼각형 vertex들을 정의할 때 시계방향 혹은 반시계방향으로 특정 순서를 정의한다.

    • 3개의 vertex들을 삼각형의 중앙을 바라보았을 때의 winding 순서로 지정한다.

    • 아래 코드가 위 이미지를 설명한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      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
      };
    
    • 이처럼 3개의 vertex들은 winding 순서를 가진다.
      • 이 정보를 사용하여 OpenGL은 front-facing, back-facing인지를 결정한다.
  • 기본값으로 반시계 방향으로 정의된 삼각형들이 front-facing 으로 처리됨

  • 실제 winding 순서는 vertex shader가 실행되고 난 후의 rasterization 단계에서 계산된다는것.

    • 그러므로 vertex들은 viewer 관점에서 보이게된다.
  • viewer가 대면하고 있는 모든 삼각형 vertex들은 확실히 정확한 winding 순서로 이루어져 있다.

    • 하지만 다른 면의 삼각형 vertex들은 winding 순서가 반대로 된채로 렌더링된다.(반시계 방향으로 정점을 지정했음에도 불구하고)
    • 그 결과 대면하고 있는 삼각형들은 front-facing 삼각형으로 보이게 되고 뒤에 있는 삼각형들은 back-facing 삼각형으로 보이게 된다.
    • 뒤에 있는 우리한테 보이지 않는 삼각형은 폐기된다.

Face culling

  • 기본적으로 비활성화되어 있는 OpenGL의 face culling 옵션을 사용해보자

  • 반시계방향으로 winding 순서로 수정해야한다.

  • 수정된 vertex data

glEnable

  • GL_CULL_FACE 옵션을 활성화 시켜주자
1
glEnable(GL_CULL_FACE);
  • 이 시점부터 front face 가 아닌 모든 면들은 폐기된다.
    • fragment 렌더링하는데 50% 이상의 성능을 절약했다.
    • 하지만 이는 큐브같은 닫힌 도형에서만 동작한다.
  • blend 에서 다루었던 잔디를 그릴 때에는 face culling을 비활성화 해야한다.
    • 이들은 앞, 뒤가 전부 보여야하기 때문이다.

glCullFace

  • 다음 함수로 폐기하고 싶은 유형을 변경할 수 있다.
1
glCullFace(GL_FRONT);
  • glCullFace 함수는 3가지 가능한 옵션들을 가짐.

    • GL_FRONT
    • GL_BACK
    • GL_FRONT_AND_BACK
  • 기본값은 BACK

glFrontFace

  • 이 함수로 face 방향을 설정할 수 있다.
1
glFrontFace(GL_CW);
  • 기본값은 GL_CCW,

  • 시계방향으로 변경하여 winding 순서를 반대로 해보자

1
2
3
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
  • 결과는 후면들만 렌더링됨

  • 아래 코드는 동일한 결과를 내놓는다.
    • 전면을 폐기
1
2
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
  • 이처럼 face culling 은 적은 비용으로 성능을 증가시킬 수 있다.
    • 어떠한 오브젝트를 face culling 해야하는지 알아야하며, 어떠한 오브젝트가 수행하면 안되는지 알아야한다(전후면 둘다 렌더링 필요할 경우).

출처

Face culling

Face culling

This post is licensed under CC BY 4.0 by the author.

[learn-opengl] Advanced OpenGL: Blending

[learn-opengl] Advanced OpenGL: Framebuffers