Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

게임공장

[Learn OpenGL 번역] 5-4. 고급 OpenGL - Face culling 본문

OpenGL

[Learn OpenGL 번역] 5-4. 고급 OpenGL - Face culling

짱승_ 2018. 8. 8. 11:25

Face culling

고급 OpenGL/Face-culling

  마음속으로 3D 큐브를 상상해보고 어느 방향에서나 볼 수 있는 최대 면들의 갯수를 세보세요. 여러분은 아마도 최댓값은 3이라고 생각할 수 있을것입니다. 여러분은 어떠한 위치나 방향에서든 큐브를 볼 수 있습니다. 하지만 여러분은 3개보다 많은 면들을 절대 볼 수 없습니다. 그러면 왜 우리는 우리가 볼 수 없는 다른 3개의 면을 그리기 위해 노력을 낭비하는 것일까요? 이들을 어떠한 방법으로 폐기한다면 fragment shader의 노력을 50%이상 줄일 수 있습니다!

  50%가 아니라 50% 이상이라고 했습니다. 특정 각도에서는 오직 2개나 1개의 면만 볼 수 있기 때문입니다. 이 경우에는 50% 이상 절약할 수 있습니다.

  이는 훌륭한 생각입니다. 하지만 해결해야할 하나의 문제가 존재합니다. 이 면이 view의 입장에서 보이지 않는 면인지 어떻게 알 수 있을까요?
  닫힌 도형을 상상해보면 각 면들은 2개의 양쪽면을 가지고 있습니다. 한쪽은 사용자와 대면하고 있고 다른 한쪽은 사용자와 등지고 있습니다. viewer와 대면하고 있는 면들만 렌더링할 수 있다면 어떨까요?


  이 것이 정확히 face culling이 하는 일입니다. OpenGL은 모든 면들을 확인하여 viewer의 관점에서 front facing한 면은 렌더링하고 back facing한 모든 면들은 폐기하여 fragment shader 호출(이는 비용이 많이 듭니다)을 많이 줄여줍니다. 우리는 OpenGL에게 우리가 우리가 사용하는 면들이 실제로 앞쪽 면인지 뒷쪽 면인지 알려주어야 합니다. OpenGL은 이에 대해 vertex 데이터의 winding 순서를 분석하는 똑똑한 방법을 사용합니다.

Winding 순서

  우리가 삼각형 vertex들을 정의할 때 시계 방향 혹은 반시계 방향으로 특정 순서롤 정의합니다. 각 삼각형은 3개의 vertex를 가지고 있고 우리는 이 3개의 vertex들을 삼각형의 중앙을 바라보았을 때의 winding 순서로 지정합니다.


Winding order of OpenGL triangles

  이미지에서 볼 수 있듯이 먼저 vertex 1을 정의한 후 vertex 22을 정의할 수 있습니다. 이 선택은 삼각형의 winding 순서를 정의합니다. 다음의 코드가 이것을 설명해줍니다.


float vertices[] = {
    // 시계 방향
    vertices[0], // vertex 1
    vertices[1], // vertex 2
    vertices[2], // vertex 3
    // 반시계 방향
    vertices[0], // vertex 1
    vertices[2], // vertex 3
    vertices[1]  // vertex 2  
};

  각 삼각형을 이루고 있는 3개의 vertex들은 winding 순서를 가지고 있습니다. OpenGL은 렌더링할 때 이 정보를 사용하여 삼각형이 front-facing인지 back-facing인지를 결정합니다. 기본값으로는 반시계 방향으로 정의된 삼각형들이 front-facing 삼각형으로 처리됩니다.


  vertex 순서를 정의할 때 해당 삼각형을 여러분을 대면하고 있는지 상상해보세요. 그리고 여러분이 지정하고 있는 삼각형이 반시계 방향이어야 합니다. 모든 vertex들을 이처럼 지정하는 것에 대해 좋은 점은 실제 winding 순서는 vertex shader가 이미 실행되고 난 후의 rasterization 단계에서 계산된다는 것입니다. 그런 다음 vertex들은 viewer의 관점에서 보이게 됩니다.


  viewer가 대면하고 있는 모든 삼각형 vertex들은 확실히 정확한 winding 순서로 이루어져 있습니다. 하지만 큐브의 다른 면의 삼각형 vertex들은 winding 순서가 반대로 된채로 렌더링됩니다. 그 결과 우리가 대면하고 있는 삼각형들은 front-facing 삼각형으로 보이게 되고 뒤에 있는 삼각형들은 back-facing 삼각형으로 보이게 됩니다. 다음 이미지가 이 효과를 보여줍니다.


Image of viewer seeing front or back facing triangles

  vertex 데이터에서 우리는 두 삼각형을 viewer의 시점에서 반시계 방향으로 정의했을 것입니다. 하지만 viewer의 방향으로부터 뒤에 있는 삼각형은 시계 방향으로 렌더링됩니다. 뒤에 있는 삼각형도 반시계 방향으로 지정하였음에도 불구하고 지금은 시계방향으로 렌더링됩니다. 이는 정확히 우리가 보이지 않은 면들을 폐기하는 것입니다!

Face culling

  이 강좌의 처음에 우리는 OpenGL이 등지고 있는 삼각형들을 폐기할 수 있다고 말했습니다. 이제 vertex들의 winding 순서를 설정하는 방법을 알았으므로 기본적으로 비활성화되어 있는 OpenGL의 face culling 옵션을 사용할 수 있습니다.


  지난 강좌들에서 우리가 사용한 큐브의 vertex 데이터는 반시계 방향의 winding 순서로 정의되지 않았었습니다. 그래서 반시계 방향으로 winding 순서로 수정해야 합니다. 여기에서 복사할 수 있습니다. 이 vertex들이 모두 정확히 반시계 방향으로 정의되었다는 것을 생각해보면서 보면 좋습니다.


  face culling을 활성화하기 위해 OpenGL의 GL_CULL_FACE 옵션을 활성화시키기만 하면 됩니다.


glEnable(GL_CULL_FACE);  

  이 시점부터 앞쪽면이 아닌 모든 면들은 폐기됩니다(큐브의 내부로 들어가서 내부에 있는 면들이 정확히 폐기되었음을 확인해보세요). 현재 우리는 fragment를 렌더링하는 데에 50% 이상의 성능을 절약했습니다. 하지만 이는 오직 큐브처럼 닫힌 도형에서만 동작한다는 것을 알아두세요. 우리는 이전 강좌의 잔디를 그릴때에는 face culling을 비활성화해야 합니다. 이들은 앞쪽면 그리고 뒷쪽면 모두 보여야 하기 때문입니다.


  OpenGL은 우리가 폐기하고 싶은 면의 유형을 바꿀수 있도록 해줍니다. 후면이 아니라 전면을 폐기하고 싶다면 어떨까요? 우리는 glCullFace 함숫를 통해 이를 정의할 수 있습니다.


glCullFace(GL_FRONT);  

  glCullFace 함수는 3개의 가능한 옵션들을 가지고 있습니다.


  • GL_BACK: 후면만을 폐기합니다.
  • GL_FRONT: 전면만을 폐기합니다.
  • GL_FRONT_AND_BACK: 전면 후면 모두 폐기합니다.

  glCullFace 함수의 기본값은 GL_BACK입니다. 폐기한 면 뿐만 아니라 OpenGL에게 시계 방향의 면들이 후면이 아니라 전면이라고 말해줄 수도 있습니다. glFrontFace 함수를 통해 이를 정의할 수 있습니다.


glFrontFace(GL_CCW);  

  기본값은 GL_CCW이므로 반시계 방향을 나타냅니다. 다른 옵션은 GL_CW로 시계 방향을 나타냅니다.


  간단한 실험으로서 OpenGL에게 이제 전면은 반시계 방향이 아니라 시계 방향이라고 말해줌으로써 winding 순서를 반대로 할 수 있습니다.


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

  결과는 후면들만 렌더링됩니다.


Image of faceculling with clockwise ordering, only culling the front faces

  반시계 방향의 winding 순서로 유지하고 전면을 폐기함으로써 동일한 효과를 얻을 수 있습니다.


glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);  

  보시다시피 face culling은 적은 비용으로 OpenGL 응용 프로그램의 성능을 증가시킬 수 있는 좋은 도구입니다. 여러분은 어떠한 오브젝트가 face culling을 이점을 누릴 수 있고 어떠한 오브젝트가 face culling을 하면 안되는지 알고 있어야 합니다.

연습

  • 각 삼각형들을 시계 방향으로 지정하고 시계 방향의 면들을 앞쪽면으로 설정할 수 있습니까?: 해답



출처 : https://learnopengl.com, Joey de Vries

반응형