KoreanFoodie's Study

[OpenGL ES] 10강 : 출력 병합(Output Merger), 색상 버퍼(Color Buffer), 깊이 버퍼(Depth Buffer) 본문

Game Dev/OpenGL ES

[OpenGL ES] 10강 : 출력 병합(Output Merger), 색상 버퍼(Color Buffer), 깊이 버퍼(Depth Buffer)

GoldGiver 2023. 4. 20. 22:42
이 강의는 유투브에 무료로 공개되어 있는 한정현 교수님의 컴퓨터 그래픽스 강좌를 정리한 글입니다. 자세한 내용은 강의를 직접 들으시거나 을 구입하셔서 확인해 보세요. 강의 자료는 깃헙 링크에 올라와 있습니다.

요약 :

1. 출력 병합 단계에서는 Fragment Shader 를 통해 전달받은 픽셀을 보여줄지 말지, 혹은 어떻게 보여줄지를 결정한다. 이때 3 가지의 버퍼를 사용한다(Color Buffer, Depth Buffer, Stencil Buffer)

2. Z-buffering 을 이용해 z 값을 이용한 컬링을 스크린 스페이스에서 수행할 수 있다. 이때, 어떤 물체를 먼저 렌더링하는지와 관계없이 결과값은 동일하다.

3. 알파 블렌딩(Alpha Blending) 을 이용하면 투명한 오브젝트들이 겹쳐져 있는 경우, 색상을 보간을 통해 합리적으로 표현할 수 있다. 이때, 렌더링되는 순서는 뒤에서 앞(back-to-front)이어야 한다!

Color Buffer, Depth Buffer, Stencil Buffer

Fragment Shader 를 거치면, 각 픽셀은 색상값을 가지게 된다.
Output Merger 에서는 이제 해당 픽셀이 보일 것인지 아닌지, 보여준다면 그냥 보여줄 것인지 변형을 가할 것인지를 결정한다.
 

OpenGL ES 에서는 스크린에서 보여줄 영역(viewport)을 잠시 보관하고 있는 버퍼가 3 개 있다. 바로...

  • Color buffer : 스크린에서 보여줄 픽셀을 저장
  • Depth buffer : z-buffer 라고도 하는 이 버퍼는 color buffer 와 동일한 해상도를 갖고 있으며, color buffer 에 저장된 픽셀의 z 값을 저장한다.
  • Stencil buffer : 스텐실 버퍼는 이 글에서는 다루지 않을 것이다 😅

위 3 가지를 합해서 Frame buffer 라고 한다!
 
 

Z-buffering

Fragment Shader 의 결과는 RGBAZ fragment 라고 불린다. 이때 A 는 투명도, Z 는 깊이값이다.
(x, y) 점에 있는 fragment 는, 동일한 (x, y) 좌표에 있는 다른 fragment 들과 비교하여 z 좌표 값이 작을 경우 출력되고,  그렇지 않을 경우 버려진다.
 

그림으로 보면 사실 매우 간단한 이야기다. 위에서 파란색 삼각형과 빨간색 삼각형이 있는데, 스크린 관점에서는 파란색이 z 값이 더 작다. 즉, 두 삼각형이 겹치는 부분에서는 파란색 삼각형이 출력되고, 빨간색 삼각형은 그려지지 않을 것이다!
 

어떤 삼각형을 먼저 렌더링하는지와 상관없이, z 값에 의해 필터링을 수행하므로, 결과는 같을 것이다! 
 

해당 부분은 OpenGL ES 가 알아서 해 줄 부분이긴 하다. 아래 함수를 통해 각 Buffer 가 초기화된다 :

나머지 함수들은 depth 에 의해 픽셀을 보여줄 것인지.... 등등의 옵션을 설정하는 함수들이라고 보면 된다. 필요할 때 참고하는 것으로 하자.
 
 

알파 블렌딩 (Alpha Blending)

이제 A 값을 어떻게 처리하는지를 보자. 0 은 완전 투명, 1 은 완전 불투명을 의미한다.
위처럼 파란색 삼각형과 빨간색 삼각형이 일부 겹쳐져 있다고 하자. 그럼 색깔이 조금 섞여야 할텐데... 사실 이는 매우 간단하다. 그냥 보간만 시켜주면 된다!

이때 c 의 값은 rgb 값이다 😄
그런데 알파 블렌딩에서는, 각 픽셀이 랜덤하게 렌더링 되서는 안된다. 투명도가 1 보다 작은 녀석들은 완전 불투명한 녀석들 이후에 렌더링 되어야 한다... 뒤에서 앞으로(back-to-front)!
따라서, 부분적으로 투명한 오브젝트들을 z 값에 따라 정렬이 되어 있어야 한다! 왜냐하면, z-buffering 을 앞부터 적용시켜 버리면, 뒤에 있는 겹치는 부분이 무시될 것이기 때문이다!
 

이제 코드를 보자. 사실 위에서 설명한 내용을 그대로 옮겼다고 생각하면 된다.
glBlendFunc 에서의 첫 원소는 파란색 삼각형, 두번째 원소는 빨간색 삼각형의 알파값이라고 보면 된다.
나머지는 필요에 따라 읽으며 사용하도록 하자 😉

Comments