MOONSUN
[그래픽스] PBR(PBR Rendering)에서의 감마 보정 본문
PBR 렌더링은 “현실 세계의 빛을 물리적으로 정확하게 시뮬레이션하는 렌더링 방식” 이다.
하지만 렌더링 엔진이 계산하는 빛의 값(조명, 반사, BRDF 결과)은 선형 공간(Linear Space) 에 존재한다.
그런데 사람의 눈은 선형으로 밝기를 인지하지 않는다.
→ 이 지각 특성과 디스플레이 특성 때문에 감마 보정(Gamma Correction) 이 필요하다.
1. 감마 보정이 필요한 이유
사람의 눈은 빛을 "선형적으로" 느끼지 않는다.
사람 눈은 밝기 변화를 로그(log) 형태로 인식한다.
- 어두운 곳에서는 작은 변화도 크게 느끼고
- 밝은 곳에서는 큰 변화도 잘 못 느낀다.

실제로 위 이미지를 보면 상대적으로 어두운 부분보다 밝은 부분이 많은 것으로 느낀다.
따라서 디지털로 “빛의 양”을 그대로 저장하면, 사람이 볼 때 자연스럽지 않다.
1-1. 디지털 빛의 세기 차이와 사람이 인지하는 빛의 세기 차이의 격차

(a) Actual Luminace 실제 광도
- perceived as half as bright by eyes (광도를 카메라가 25% 감지 일때) 눈은 반쯤 밝게 인식함
- deteced as half as bright by camera (광도를 눈이 75% 인지 할때) 카메라는 절반의 밝기로 감지함
(b) 어두운 영역은 차이를 크게 느끼고, 밝은 영역은 차이를 작게 느낀다
- 밝은 부분은 줄이고 어두운 부분은 세밀하게 표현하면 사람의 눈에 더 자연스러워 보인다.
2. sRGB : 사람 눈을 기준으로 한 비선형 공간

모니터와 이미지 포맷(JPG/PNG)은 대부분 sRGB 색 공간을 사용한다.
sRGB는 사람 눈의 특성을 반영한 감마 곡선(약 2.2) 으로 인코딩되어 있다.
즉,
모니터는 픽셀 값을 선형적으로 출력하지 않는다.
인코딩된 색 = 실제 빛과 다르다(비선형)
그래서 3D 엔진은 감마 인코딩 / 디코딩 과정이 필요하다.
3. 감마 인코딩 / 디코딩

수학적 계산식의 결과로 나온 데이터(Linear) 를 사람의 눈이 선형적으로 인식하는 값(Gamma)으로 바꾸어야 한다
어두운 부분은 더 차이를 크게 변환이 필요하고 밝은 부분은 더 차이를 작게 작게 만드는것 필요
3-1. 감마 인코딩 (Gamma Encoding)
이미지 파일(JPG/PNG 등)은 저장할 때 사람 눈에 더 효율적인 방식을 위해 데이터를 감마 인코딩하여 저장한다.

// y = x ^ (1/2.2)
sRGBSpaceColor = pow(LinearSpaceColor, 1/2.2)
어두운 값은 더 밝게 펴고 → 밝은 값은 압축해서 저장
3-1. 감마 디코딩 (Linearization) : 렌더링 시 Linear 복귀
PBR의 조명 계산(BRDF)은 물리식 기반 → “선형 공간”에서만 의미가 있음
그래서 텍스처를 GPU에 불러올 때:
- Color Texture(sRGB) → 감마 디코딩 후 Linear로 변환
- Data Texture(선형 데이터) → 변환 없이 그대로 사용
// Linear = (Encoded_sRGB)^2.2
LinearSpaceColor = pow(sRGBSpaceColor,2.2)
4. PBR에서 감마 보정이 필요한 이유
이유 1) BRDF 수학 계산은 반드시 “선형 공간”에서 동작한다
- N·L
- DGF/(4NVNL)
- GGX
- Fresnel
- Energy conservation
이들 모두 빛의 에너지와 직접 연결되므로 비선형 sRGB 값으로 계산하면 물리적으로 틀어진다.
이유 2) 사람이 보는 최종 화면은 비선형(sRGB)이어야 한다
엔진 내부 계산은 선형이지만,
최종적으로 모니터는 sRGB라는 감마 곡선을 통해 빛을 출력한다.
따라서 마지막 단계에서 다시 감마 인코딩이 필요하다.
- 최종 화면 출력 과정
FinalLinearColor → (감마 인코딩) → sRGB로 출력
즉 그래픽 파이프라인은 다음과 같은 과정을 거친다:
- 텍스처 읽기
- sRGB 텍스처: 감마 디코딩 → Linear로 변환
- Linear 텍스처: 그대로 사용
- PBR 조명 계산 (항상 Linear)
- 화면 출력
→ Linear → sRGB로 다시 감마 인코딩
5. 어떤 텍스처가 감마 인코딩 되는가?
5-1. Color Texture(사람눈으로 편집) → Gamma 있음 (sRGB)
- BaseColor / Albedo
- Emissive Color
- Specular Color
- Subsurface Color
이런 텍스처들은 Photoshop 같은 툴에서 만들어지는데, 툴 자체가 sRGB로 작업하므로
파일도 sRGB로 저장됨.
5-2. Data Texture(계산용) → Gamma 없이 “선형”으로 저장해야 함
- Normal
- Roughness
- Metallic
- AO
- Height
- Displacement
- Mask / ORM
이 값들은 색이 아니라 숫자 데이터이므로 감마 인코딩되면 망가짐.
6. 파일 포맷과 감마
- JPG
- 무조건 sRGB(감마 인코딩)
- PNG
- 내부에 감마 값(gAMA)이나 ICC 프로파일을 저장할 수도 있음
- 보통 대부분 sRGB로 사용됨
- EXR/HDR
- 물리 기반 HDR 데이터 → 항상 Linear Float
- 감마 X
- DDS (BCn 포맷)
- 포맷 이름에 _SRGB 붙으면 감마 인코딩된 텍스처
- 로딩 시 GPU가 자동으로 감마 디코딩
- BC7_UNORM_SRGB → sRGB (Color Texture)
- BC7_UNORM → Linear (Data Texture)
7. GPU의 sRGB 하드웨어 디코딩
DirectX, OpenGL 모두 sRGB 텍스처는:
샘플링 시 자동으로 pow(x, 2.2)를 해줌
즉 개발자가 직접 pow()를 할 필요 없음!!
8. 최종 요약
| 단계 | 공간 | 설명 |
| 텍스처 로딩 | sRGB 텍스처는 감마 디코딩 → Linear | GPU가 자동 처리 |
| 조명 계산 | Linear | BRDF, PBR 수학적 연산 |
| 후처리 | Linear | Bloom, DOF, Tonemap 직전까지 |
| 화면 출력 | Linear → 감마 인코딩 | pow(x, 1/2.2) 적용 |
PBR에서 감마 보정은
인간의 눈의 비선형 지각을 보정하기 위해, 입력 텍스처는 Linear로 디코딩하고,
계산은 Linear에서 수행한 뒤, 최종 출력에서 다시 감마로 인코딩하는 과정이다.
'D3D' 카테고리의 다른 글
| [D3D] IBL 구현 이슈 : IBL Specular가 Roughness에 반응하지 않았던 이유 (0) | 2025.12.16 |
|---|---|
| [그래픽스] IBL (Image Based Lighting) : PBR을 위한 환경 기반 간접광 (0) | 2025.12.10 |
| [그래픽스] PBR 이론 및 구현 : BSDF, BRDF, Cook–Torrance (0) | 2025.12.02 |
| [그래픽스] PBR(Physically Based Rendering) : 빛의 물리 기반 렌더링의 이해 (0) | 2025.12.01 |
| [그래픽스] Toon Shading의 OutLine 표현 : 실루엣 Pass (0) | 2025.11.11 |