공부/컴퓨터 그래픽스

OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문 Chapter 10 출력 병합기

bokob 2024. 7. 12. 14:45

프래그먼트 색상은 뷰포트에 즉시 표시되지 않고 출력 병합기(output merger)에 전달되며, 출력 병합기는 세 종류의 버퍼를 관리한다. 이 세 종류의 버퍼를 합해서 프레임 버퍼라고 한다.

 

프레임 버퍼(frame buffer)

GL에서는 다음 세 종류의 버퍼를 제공한다

  • 컬러 버퍼(color buffer): 스크린의 2차원 뷰포트에 나타날 픽셀 전체를 저장하는 메모리 공간
  • 깊이 버퍼(depth buffer): z-버퍼라고도 불리는데, 컬러 버퍼와 동일한 해상도를 가지며 현재 컬러 버퍼에 저장되어 있는 픽셀의 z값을 저장, 이 z값은 스크린 공간에서 정의된 3차원 뷰포트의 z범위에 속한다.
  • 스텐실 버퍼(stencil buffer): 컬러 버퍼와 깊이 버퍼 외에 추가적인 데이터 버퍼, 다양한 그래픽 효과를 구현하는 데 사용 (책에서 다루지 않으므로, 위키백과 찾아봄)

 

래스터라이저는 노멀 및 텍스처 좌표뿐만 아니라 z 좌표도 보간한다. 다른 프래그먼트 속성과 달리 보간된 z는 출력 병합기(프래그먼트 쉐이더 그냥 통과)로 전달되어 출력 병합기가 각 프래그먼트의 색상과 z를 갖는다.

 

10.1 Z-버퍼링

z-버퍼링(z-buffering) 또는 깊이 버퍼링(depth buffering)

  • z-버퍼를 이용하여 픽셀과 프래그먼트의 앞뒤 순서를 가리는 알고리즘

해당 픽셀은 파란색으로 칠해진다.

 

위 사진은 뷰포트 안의 파란색, 빨간색 삼각형의 스크린 공간 좌표가 (x, y)인 픽셀 위치에서 어떤 색을 칠할 지는 z 값을 비교해 결정하게 된다.

 

z-버퍼링, (a) 빨간색, 파란색 순서로 렌더링, (b) 파란색, 빨간색 순서로 렌더링
컬러 버퍼와 깊이 버퍼를 초기화하는 GL 프로그램 고

glDepthRange로 정의된 스크린 공간 3차원 뷰포트의 z범위가 [0.0, 1.0]이라고 가정하자.

z-버퍼는 배경의 z값에 해당하는 1.0으로 초기화된다.

컬러 버퍼는 배경색으로 초기화된다. 위 그림에서는 배경이 흰색이라고 가정했으므로 컬러 버퍼는 흰색으로 초기화된다.

위 예제 코드에서 glClearDepth, glClearColor는 각각 초기 z값과 컬러를 설정하고, glClear는 이를  이용해 z-버퍼와 컬러 버퍼를 초기화한다.

 

프래그먼트 쉐이더가 한 프래그먼트의 RGBA 색상을 출력할 때, 그 프래그먼트의 스크린 공간 좌표 (x, y, z)는 자동으로 출력 병합기에 전달된다.

출력 병합기는 z 좌표를 현재 z-버퍼의 (x, y)에 기록되어 있는 Z값과 비교

프래그먼트의 z좌표가 작다면, 현재 컬러 버퍼에 저장되어 있는 픽셀보다 앞에 있다는 것이다. 따라서 컬러 버퍼의 픽셀을 프래그먼트 색상으로 대체한다. 동시에 z-버퍼의 (x, y)에 저장된 z값도 프래그먼트의 z봐표로 대체한다.

반대로, 프래그먼트의 z좌표가 크다면, 현재 컬러 버퍼에 저장되어 있는 픽셀보다 뒤에 있다는 것이다. 따라서 해당 프래그먼트를 버린다.

 

위 사진에서 (b)는 (a)와 반대로 처리한 경우다. 파란색 삼각형보다 빨간색 삼각형이 나중에 그려진 것이다.

원칙적으로 z-버퍼링 알고리즘은 삼각형들을 임의의 순서로 처리하는 것을 허용한다.

하지만 삼각형 처리 순서가 중요할 때가 있다. ex) 알파 블렌딩

 

z-버퍼링을 활성화하기 위해서는 glEnable(GL_DEPth_TEST)를 호출해야 한다. 그 다음, glDepthFunc를 사용하여 z값 비교에 사용할 방법을 지정해야 한다. 특별한 경우가 아니라면 프래그먼트의 z좌표가 픽셀의 z값보다 작을(less) 때, z 버퍼와 컬러 버퍼가 갱신되므로, glDepthFunc의 기본값은 GL_LESS이다.

 

10.2 알파 블렌딩

출력 병합기에 입력을 종종 RGBAZ 프래그먼트라 부른다.

A는 투명도를 나타내고, Z는 깊이를 나타낸다.

α 값에 따른 불투명도 차이

α는 [0, 1] 범위를 가지고 1은 완전한 불투명, 0은 완전한 투명을 나타낸다. 

α값을 사용하면 프래그먼트가 컬러 버퍼의 픽셀과 병합된다.

$c$는 블렌딩된 색상을 나타내고, $a$는 프래그먼트의 불투명도(알파 채널), $c_f$는 프래그먼트 색상, $c_p$는 픽셀 색상을 나타낸다.

$a$가 0이면 투명한 프래그먼트는 보이지 않고, $a$가 1이면 프래그먼트는 픽셀의 색상을 완전히 가리게 된다. $a$가 0.5라면 $c$는 프래그먼트와 픽셀 색상의 평균값이 된다.

 

렌더링 순서가 바뀌어 파란색 삼각형을 먼저, 빨간색 삼각형을 나중에 z-버퍼링에 의해 빨간색 프래그먼트의 z 좌표는 파란색 프래그먼트의 z 좌표보다 크므로 폐기되어 블렌딩이 이루어지지 않을 것이다.

 

z-버퍼링 알고리즘은 삼각형 처리 순서에 독립적이지만, 이는 불투명한 삼각형들에만 적용되는 것이다.

반투명한 삼각형들은 임의의 순서로 렌더링할 수 없다.

대신, 모든 불투명한 삼각형이 처리된 뒤, 반투명한 삼각형들은 뒤에서부터 앞으로(back-to-front) 차례로 처리되어야 한다. 이를 위해 반투명한 삼각형들은 정렬(sorting)되어야 한다.

삼각형들을 정렬하는 것은 간단한 문제가 아니다. 매 프레임마다 카메라 시선이 바뀐다면, 새로운 시선에 대해 실시간으로 정렬이 이루어져야 한다. 뷰 프러스텀 안에 반투명한 삼각형이 많을수록 계산 부하는 커진다.

 

알파 블렌딩을 위한 GL 프로그램
z-버퍼링에서와 마찬가지로 glEnable(GL_BLEND)를 호출해서 알파 블렌딩을 활성화한 후, glBlendFunc와 glBlendEquation을 사용하여 프래그먼트와 픽셀이 혼합되는 방법을 지정한다.

 

glBlendFunc(GLenum sfactor, GLenum dfactor)

  • sfactor: 프래그먼트의 가중치
  • dfactor: 픽셀의 가중치,

GL_ZERO와 GL_ONE 같은 값이 두 파라미터에 할당될 수 있다. 하지만 GL_SRC_ALPHA가 sfactor에, GL_ONE_MINUS_ALPHA가 dfactor에 최적일 수 있다. 각각 α와 1- α를 의미한다.

 

glBlendEquation(GL_FUNC_ADD)는 가중치를 가진 프래그먼트 색상과 픽셀 색상이 어떻게 혼합될 것인지 지정하는데, 기본값은 GL_FUNC_ADD이다.

 

출처
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문]을 보고 공부하고 정리한 내용