개발/Graphics

OpenGL Super Bible 그래픽스 공부하기 - 3. 파이프라인 따라가기 - 5) 프래그먼트 쉐이더~프레임버퍼

huiyu 2018. 1. 27. 12:55

OpenGL Super Bible 그래픽스 공부하기 - 1. OpenGL 기본개념이해
OpenGL Super Bible 그래픽스 공부하기 - 2. 첫번째 OpenGL 프로그램
OpenGL Super Bible 그래픽스 공부하기 - 2-3. 처음 그리는 삼각형
OpenGL Super Bible 그래픽스 공부하기 - 3. 파이프라인 따라가기 - 1) 쉐이더간 데이터 전달
OpenGL Super Bible 그래픽스 공부하기 - 3. 파이프라인 따라가기 - 2) 테셀레이션
OpenGL Super Bible 그래픽스 공부하기 - 3. 파이프라인 따라가기 - 3) 지오메트리 쉐이더
OpenGL Super Bible 그래픽스 공부하기 - 3. 파이프라인 따라가기 - 4) 
프리미티브 어셈블리, 클리핑, 래스터라이제이션

Part 3 파이프라인 따라가기 - 5) 프래그먼트 쉐이더~프레임버퍼

3.6 프래그먼트 쉐이더 (Fragment Shader)

 - 마지막 프로그래밍 가능 스테이지
 - 프래그먼트의 색상을 결정, 프레임 버퍼로 전달
 -*여기서 파이프라인의 작업량이 폭발적으로 증가하게 된다. -> 삼각형이 수백,수천, 수백만의 프래그먼트를 생산하기 때문

아래는 간단한 프래그먼트 쉐이더 예제, 실제는 훨씬 복잡한 라이팅 계산, 재질 적용, 프래그먼트 깊이 결정하는 일을 수행

1
2
3
4
5
6
7
8
9
10
11
#version 430 core
 
out vec4 color;
 
void main(void)
{
    color = vec4(sin(gl_FragCoord.x * 0.25* 0.5 + 0.5,
                 cos(gl_FragCoord.y * 0.25* 0.5 + 0.5,
                 sin(gl_FragCoord.x * 0.15* cos(gl_FragCoord.y * 0.15),
                 1.0);
}
cs

 - glFragCoord : 윈도우 안 프래그먼트의 위치를 갖고 있다. 이 변수를 사용하면 각 프래그먼트에 대해 고유한 색상을 부여 가능하다.


또한 프래그먼트 쉐이더의 입력은 다른 스테이지의 입력과는 차이가 있다. 다른 스테이지들은 OpenGL이 입력값을 렌더링 되는 프리미티브에 따라 보간한다. 

이를 예제로 살펴보면, 버텍스 쉐이더의 color값을 gl_VertexID를 이용하여 채워보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#version 430 core
 
out vec4 color;
 
void main(void)
{
    const vec4 vertices[3= vec4[3](vec4(0.25-0.250.51.0),
                             vec4(-0.25-0.250.51.0),
                             vec4(0.250.250.51.0));
    const vec4 colors[3]   = vec4[3](vec4(1.00.00.01.0),
                             vec4(0.01.00.01.0),
                             vec4(0.00.01.01.0));
    gl_Position = vertices[gl_VertexID];    
    vs_color    = colors[gl_VertexID];               
}
cs


1
2
3
4
5
6
7
8
9
#version 430 core
 
in vec4 vs_color; 
out vec4 color;
 
void main(void)
{
    color = vs_color;         
}
cs

출력결과, 내부의 색이 부드럽게 보간되어 채워진 걸 확인할 수 있다.


3.7 프레임버퍼 동작

 - 그래픽스 파이프라인의 마지막 스테이지, 화면의 보이는 영역을 나타내며, 색상 이외에도 픽셀당 값을 저장하기 위해 사용되는 메모리 영역
 - 많은 플랫폼에서 보이는 윈도우를 의미하며, 운영체제가 소유한다(윈도우 시스템 소유). 
 - 윈도우 시스템이 제공하는 프레임버퍼는 디폴트 프레임버퍼지만, 오프스크린(off-screen) 영역에 렌더링 등의 작업을 원한다면 직접 프레임버퍼를 제공하는 것도 가능.
 - 프레임버퍼는 프래그먼트 쉐이더에 의해 쓰일 위치 및 포맷 등에 대한 상태정보도 필요, 이러한 상태는 프레임버퍼객체에 저장된다.

3.7.1 픽셀 오퍼레이션

 - 프래그먼트 쉐이더가 출력을 생성한 후, 윈도우에 쓰이기 전까지 프래그먼트에 일어난다.
  1) 가위 테스트(Scissor test) : 사용자가 정의한 사각형에 대해 프래그먼트 테스트. 사각형 안에 있으면 진행/아니면 사라진다.
  2) 스텐실 테스트(Stencil test) : app에서 지정한 참조값과 스텐실 버퍼 내용 비교, 스텐실 버퍼는 각 픽셀당 하나의 값 저장.
  3) 깊이 테스트(Depth test) : 프래그먼트의 z좌표와 깊이버퍼의 내용을 비교. 깊이 버퍼는 스텐실 버퍼처럼 메모리 영역이며, 각 픽셀당 하나의 값을 가지는 프레임버퍼의 특정영역. 각 픽셀의 깊이(사용자로부터의 거리에 상대적인)를 담고 있다.

 * 보통 깊이 버퍼의 값은 0~1. 0이 가까운 점이고, 1이 먼점이다. 
 프래그먼트가 동일한 위치에 있는 이미 렌더링된 다른 프래그먼트보다 가까운지 결정하기 위해 깊이버퍼와 z좌표를 비교한 뒤, 기존값보다 작으면 보이게 된다.

* 프래그먼트 쉐이더의 출력 컴포넌트와 현재 프레임버퍼의 컴포넌트를 인자로 하는 여러 함수를 사용하여 새로운 값을 계산하여 다시 프레임버퍼에 저장 가능


+ 3.8 컴퓨트 쉐이더

 - 그래픽스 관련 스테이지와 별개로 동작하는 파이프라인
 ->GPU의 막강한 계산력을 이용한 방법으로, 단일 스테이지 파이프라인.
 - 각 호출은 워크아이템(Work Item)이라는 단일 구성 요소 작업을 하며, 이 아이템들이 모여 지역작업그룹(Local work group)이라는 작은 그룹을 형성.

 - 그 외 사용 방법은 일반 쉐이더와 같다.
 (glShaderSource() -> glCompileShader() -> glAttachShader() -> glLinkProgram())


728x90
반응형