OpenGL 정리 - 3. 프로그래머블 셰이더(Programmable Shader)
강의에서는 간단하게만 설명 되었지만 일단 알아두면 좋은 개념일 거 같아 검색하여 기록한다.
프로그래머블 셰이더(Programmable Shader)는 GPU에서 실행되는 작은 프로그램으로, 그래픽 파이프라인의 특정 단계를 프로그래머가 제어할 수 있게 해준다. 초기의 그래픽 파이프라인은 고정 기능 파이프라인(Fixed-Function Pipeline)이라 불리며, 하드웨어에서 미리 정의된 방식으로만 그래픽 처리 작업을 수행했으나, 프로그래머블 셰이더를 통해 그래픽 연산의 유연성과 효율성을 극대화할 수 있게 되었다.
1. 셰이더의 기본 개념
셰이더는 주로 그래픽 렌더링 과정에서 색상, 조명, 텍스처, 변환 등을 처리하는 데 사용된다. 프로그래머는 이 셰이더를 통해 GPU에서 직접적인 그래픽 연산을 제어할 수 있으며, 일반적으로 GLSL(OpenGL Shading Language), HLSL(DirectX의 셰이더 언어), 혹은 SPIR-V(Vulkan에서 사용되는 중간 언어) 같은 언어로 작성한다.
2. 프로그래머블 셰이더의 종류
그래픽 파이프라인에서 셰이더는 여러 가지 단계에 걸쳐 있으며, 각 단계에서 서로 다른 작업을 수행한다. OpenGL과 같은 API에서 지원하는 주요 셰이더 유형은 다음과 같다.
a) 버텍스 셰이더(Vertex Shader)
- 역할: 3D 모델의 각 정점(vertex)을 처리하는 셰이더이다. 주로 공간 변환(월드 좌표, 카메라 좌표, 클립 좌표 등)을 수행하며, 조명 계산이나 텍스처 좌표 계산도 여기서 가능하다.
- 주요 기능:
- 모델 좌표계를 월드, 뷰, 클립 좌표계로 변환
- 정점의 위치, 법선, 텍스처 좌표 계산
- 기본적인 조명 처리 가능
b) 프래그먼트 셰이더(Fragment Shader 또는 Pixel Shader)
- 역할: 화면에 그려질 각 픽셀(fragment)의 색상을 결정하는 셰이더이다. 텍스처 매핑, 조명 효과, 음영 처리 등과 관련된 계산을 담당한다.
- 주요 기능:
- 텍스처 샘플링 및 혼합
- 조명 및 그림자 효과 처리
- 픽셀 기반의 다양한 후처리 효과(블러, 반사, 굴절 등)
c) 지오메트리 셰이더(Geometry Shader)
- 역할: 버텍스 셰이더의 출력 이후에 실행되며, 정점 데이터를 변경하거나 새로운 정점을 추가하는 역할을 한다. 지오메트리 셰이더를 사용하면 원래의 기본 도형을 변형하거나, 새로운 도형을 추가로 생성할 수 있다.
- 주요 기능:
- 정점 수를 증가 또는 감소시켜 도형을 변형
- 1개의 점 또는 선을 기반으로 더 복잡한 도형 생성 가능
d) 테셀레이션 셰이더(Tessellation Shader)
- 역할: 복잡한 표면을 세부적으로 나누어 더 부드럽고 정교한 모델을 만드는 셰이더이다. 주로 고해상도의 메시(mesh)를 생성하는 데 사용된다. 테셀레이션 셰이더는 두 단계로 나뉜다: 테셀레이션 컨트롤 셰이더와 테셀레이션 평가 셰이더.
- 주요 기능:
- 3D 모델의 표면을 동적으로 세분화하여 고해상도 디테일 표현
- 낮은 해상도의 메시에 고해상도 표현을 추가하여 성능을 최적화
e) 컴퓨트 셰이더(Compute Shader)
- 역할: 전통적인 그래픽 렌더링 파이프라인과는 독립적으로 작동하며, 복잡한 연산을 GPU에서 처리할 수 있는 범용 셰이더이다. 물리 시뮬레이션, 인공지능, 병렬 연산 등 다양한 분야에서 활용된다.
- 주요 기능:
- 그래픽 외의 복잡한 계산 작업 처리
- 파티클 시스템, 물리 엔진, 볼륨 렌더링 등에서 사용
3. 프로그래머블 셰이더의 동작 방식
프로그래머블 셰이더는 GPU가 각각의 정점 또는 픽셀 단위로 병렬 연산을 수행하도록 해주며, 이는 CPU가 처리할 수 없는 대규모 그래픽 연산을 매우 빠르게 처리할 수 있게 해준다. 셰이더는 다음과 같은 과정을 거친다:
- 셰이더 코드 작성: GLSL 같은 셰이더 언어로 셰이더 프로그램을 작성한다.
- 셰이더 컴파일 및 링크: 셰이더 코드를 GPU에 맞는 형식으로 컴파일하고, 여러 셰이더 프로그램을 연결하여 그래픽 파이프라인에서 사용할 수 있는 프로그램으로 만든다.
- 셰이더 실행: GPU는 셰이더 프로그램을 실행하며, 정점 또는 픽셀의 데이터를 처리하고 출력한다.
4. 프로그래머블 셰이더의 장점
- 그래픽 품질 향상: 프로그래머는 고유한 조명, 음영, 후처리 효과 등을 구현하여 더욱 리얼한 그래픽을 만들 수 있다.
- 성능 최적화: CPU 대신 GPU에서 병렬 연산을 수행하여 복잡한 계산을 빠르게 처리할 수 있다.
- 유연성: 고정된 기능 대신 프로그래머가 직접 원하는 계산을 구현할 수 있기 때문에 다양한 시각 효과와 연산을 자유롭게 처리할 수 있다.
5. 프로그래머블 셰이더의 사용 예시
- 조명 처리: 각 픽셀마다 다양한 조명 효과(예: 퐁 셰이딩, 블린-퐁 셰이딩)를 계산하여 화면을 그리는 데 사용할 수 있다.
- 텍스처 매핑: 물체에 텍스처를 입히거나, 텍스처의 특성을 기반으로 다양한 시각 효과(예: 노말 매핑, 디스플레이스먼트 매핑)를 추가할 수 있다.
- 포스트 프로세싱: 화면이 그려진 후 블러, 그레인, 화면 왜곡 등의 후처리 효과를 적용할 수 있다.
OpenGL에서 3D 그래픽을 그려내기 위해서는 최소한 두 가지 종류의 셰이더 (버텍스 셰이더(Vertex Shader), 프래그먼트 셰이더(Fragment Shader))가 필요하다.