오늘은 GL 에서 중요한 기본 개념인 Graphics pipeline에 대해 정리하고자 한다.
지난 글에서 프레임 버퍼를 설명할 때, 그래픽 프로그램이 적절히 처리한 데이터를 프레임 버퍼에 저장하면, 프레임 버퍼에 저장된 데이터를 비디오 컨트롤러가 가져다가 화면에 출력할 수 있는 데이터로 변환해준다고 했다.
이제 구체적으로 그래픽 프로그램이 어떻게 '적절히 처리' 하는지 과정을 살펴보자.
먼저 프레임 버퍼에 데이터를 저장하기까지 처리하는 큰 흐름은 위와 같다.
이 흐름을 따라가려면 먼저 Vertex 에 대한 이야기를 해야한다.
이를 위해 OpenGL 의 기본 용어 4가지를 정리해보자.
Open GL 기본 용어
Primitive : 원시적인 이라는 뜻 그대로, 렌더링의 기반이 되는 기본 단위(점, 선, 삼각형 등)를 의미한다.
Vertex : 정점이라는 뜻이다. 좌표 상 하나의 점 (꼭짓점) 을 의미한다.
Rasterizer : primitive를 렌더링하는 하드웨어 가속기이다.
Frame Buffer : 화면의 정해진 영역에 보이는 데이터가 저장되는 메모리상 공간을 의미한다. 색상 값과 같이 픽셀 하나가 가지는 데이터가 저장되는 메모리 영역이다.
Stage : 위 파이프 라인의 각 단계를 스테이지 라고 부른다. (즉, 파란색 사각형 하나)
Shader : 그래픽 카드의 코어에서 Stage마다 작동하는 작은 프로그램
우리가 현실에서 다루는 데이터는 모두 3차원 정보로 표현되지만, 모니터에서 볼 때는 2차원 데이터로 표현되므로 3차원 데이터를 2차원 데이터로 변환할 필요가 있다. 그 과정을 위 파이프라인을 거치면서 변환하고, 최종 변환된 결과물을 프레임 버퍼에 저장하여 모니터에 출력할 대기를 시키는 것이다.
현재 그래픽 카드 하나에는 수천개의 코어가 있다. (Nvidia는 cuda 코어)
이 코어들은 이미지로 만들 데이터를 입력값으로 받아 병렬적으로 처리할 수 있다.
이때 각 그래픽 카드의 코어에서 Stage 별로 작동하는 작은 프로그램을 Shader 라고 한다.
(즉, 위 파이프 라인의 단계는 그래픽카드 내부에 있는 코어에서 일어나는 일련의 과정인 것이다!!)
OpenGL 의 셰이더는 C언어와 유사한 OpenGL Shader Language (GLSL) 라는 별도의 언어로 작성된다.
이렇게 C와 유사한 문법을 가지고 있다.
OpenGL 에서는 여러 Stage의 셰이더를 프로그래밍 할 수 있는데, 보통은 Vertex Shader, Fragment Shader 를 프로그래밍한다. (수업에서도 이 2개 셰이더 위주로 본다)
Graphics Pipeline
이제 그래픽스 파이프라인에 대해 더 자세히 들어가보자.
그래픽스 파이프라인은 단계에 따라 크게 '프론트엔드' 와 '백엔드' 로 구분할 수 있다.
그래픽스 파이프라인 프론트엔드는 Vertex, Primitive를 처리하여 점, 선, 삼각형으로 구성하고, Rasterizer(하드웨어 가속기)에 전달하기 직전까지의 과정을 말한다.
정점과 primitive를 이리저리 잘 계산해서 화면에 보여줄 2D 정점 벡터들의 집합을 모두 계산하면, Geometry Shader가 벡터를 모니터에서 표현할 수 있는 픽셀 데이터로 변환한다.
그래픽스 파이프라인 백엔드는 Geometry Shader가 만들어낸 픽셀을 Rasterizer(하드웨어 가속기)에 넘겨 2D 데이터를 처리하는 작업을 수행하고 최종적으로 Frame Buffer에 담는 역할을 수행한다.
이제 구체적인 단계를 하나씩 살펴보자.
Vertex Patch & Vertext Shader
Vertex Patch (= vertext pulling)은 vertex shader에 입력을 제공하는 단계이다.
여기에 들어가는 입력값은 vertex의 위치, 색상값 등이 해당된다.
Vertex Shader는 이렇게 받아들인 위치, 색상 값 등을 행렬을 이용해 적절히 처리하는 역할을 수행한다.
대표적인 작업으로 3차원 좌표를 받아들인 뒤, 이 좌표 값에 1.0 을 붙여 4개 정점으로 표현하는 것이 있다.
(Homogenious 식으로 표현하여 행렬 계산하기 위함. 여기에 행렬을 이용해 정점 위치를 옮기고 회전시킬 수 있다.)
Tessellation (조각화)
Primitive Assembly Stage라고도 한다.
사각형, 삼각형, 선 등의 patch 나 고차원 primitive를 더 작고 단순한 점, 선, 삼각형 등으로 조각내는 과정을 의미한다.
큰 덩어리를 렌더링 가능한 작은 덩어리로 조각내는 과정이다.
이 과정에 관여하는 Shader는 2가지가 있다.
Tessellation control shader 는 어느 정도로 조각낼지 tessellation level 을 결정하고, tessellation을 수행한다.
그리고 그 결과물을 tessellation evaluation shader에 보내기 위해 그 입력값 형식에 맞는 데이터를 생성한다.
Tessellation Evaluation Shader (TES) 는 Tessellation Engine 이 만들어낸 Primitive에 대한 출력 Vertex를 돌려준다.
TES는 해당 Vertex에 대해 한번씩 호출된다.
조각화 부분은 자세히 다루지 않아 간단히 큰 개념만 설명하고 넘어갔다.
Geometry Shader & Rasterization
프론트엔드와 백엔드의 경계 구간이다.
Geometry Shader 는 Tessellation 과정을 통해 렌더링 가능하도록 조각낸 데이터에 대해 더 로우 레벨 데이터(픽셀)로 변환하는 셰이더이다. 프로그래밍을 통해 파이프라인 내 데이터의 흐름량을 증가/감소 시키거나, 삼각형을 받아서 점, 선으로 분리하는 등 Primitive의 모드를 변경하기도 한다.
이 과정은 Optional 하기도 하고 잘 안쓴다고 한다.
다만 Rasterization 과정은 필수로 거쳐야 하는데, Fragment ( 한 픽셀의 최종 색상에 적용되는 요소 ) 들이 선이나 삼각형 등의 Primitive에 의해 채워지는지 결정하는 작업을 수행한다.
(사실 무슨 말인지 나도 모르겠다...)
Fragment Shader & Framebuffer Operation
Fragment Shader는 OpenGL 그래픽스 파이프라인에서 마지막으로 프로그래밍 가능한 스테이지이다.
각 fragment 의 색상을 결정하는 역할을 수행한다고 한다.
이렇게 결정된 최종 데이터는 frame buffer로 보내져 화면에 그려지게 된다.
framebuffer operation 단계에서는 최종적으로 scissor test, stencil test, depth test 등을 진행한다.
또는 블렌딩이나 논리 연산을 수행하기도 한다.
이게 무슨 말인가 하면, 어떤 물체의 앞에 있는지 뒤에있는지 결정하는 것이 위에 언급한 각종 test 이다.
이 테스트 결과 어떤 데이터가 어떤 데이터의 뒤에 그려져야 하는지, 그 불투명도는 어느정도 인지 결정이 되면 그 내용을 토대로 각종 색상값을 합치는 블렌딩 작업을 거치게 된다.
더 구체적인 예를 들자면, 나무가 있고 나무 밑에 풀이 있다고 하자.
나무는 햇빛을 받아 그림자를 만들어내는데 풀 데이터를 화면에 그릴 때는 기본적인 풀 데이터가 가지는 색상에 그림자 색상을 함께 섞어서 조금 더 어두운 녹색으로 보여지게 해야할 것이다.
이 때는 그림자가 풀 보다 더 위에 있고, 그림자는 검은색이지만 불투명도가 조금 낮은 검은색이고, 이 색상을 풀 색상인 녹색에 섞어서 (블렌딩) 좀 어두운 녹색처럼 보이게 하는 과정을 의미한다.
- Alpha test
프래그먼트의 깊이 계산을 통해, 이 프래그먼트가 다른 프래그먼트 앞에 그려져야 하는지 테스트한다.
만약 다른 프래그먼트 뒤에 있어서 가려진다면, 해당 프로그래먼트는 버린다.
- Blending
alpha 값에 따라 뒤에 있는 객체와 색상을 섞는 과정이다.
다음 글에서는 이제 실제로 삼각형을 그리는 예제를 보면서 이 파이프라인을 어떻게 따라가는지 살펴보도록 하자.
'CS > HCI 윈도우즈프로그래밍' 카테고리의 다른 글
[OpenGL] 6. Shader (2) - VAO (1) | 2024.04.07 |
---|---|
[OpenGL] 5. Shader (1) - Shader, VBO, Shader Program (0) | 2024.04.05 |
[OpenGL] 3. GLFW 기본 예제 뜯어보기 (0) | 2024.04.04 |
[OpenGL] 2. Open GL 개념 (0) | 2024.04.03 |
[OpenGL] 1. GLFW, GLAD 환경설정 (2) | 2024.04.03 |