Notice
Recent Posts
Recent Comments
Link
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

MOONSUN

[그래픽스] HDR 렌더링 : 렌더타겟, 노출, 톤 매핑 본문

D3D

[그래픽스] HDR 렌더링 : 렌더타겟, 노출, 톤 매핑

MoonSun_v 2025. 12. 17. 10:49

 

LDR(Low Dynamic Range)와 HDR(High Dynamic Range)는 렌더링에서 서로 다른 밝기 표현 방식을 의미한다.

두 용어는 종종 단순한 화질 차이처럼 사용되지만,
실제로는 픽셀 값의 범위, 계산 방식, 그리고 디스플레이로 전달되는 출력 경로까지 서로 다른 전제를 가진다.

이번 글에서는 LDR 렌더링이 가지는 한계부터, HDR 렌더링이 왜 필요해졌는지,
그리고 HDR 파이프라인이 어떤 단계들로 구성되는지를 알아보려고 한다. 

 

 

HDR 렌더링 파이프라인은 다음 순서로 이해하면 된다. 

현실적인 밝기 계산
	↓
HDR 렌더타겟 (밝기 차이를 자르지 않음)
	↓
노출 (전체 밝기 위치 조정)
	↓
톤 매핑 (사람 눈에 맞게 압축)
	↓
백버퍼 + Color Space 설정
	↓
모니터 출력

이제 각 단계를 왜 거치는지 하나씩 살펴보자.

 

 

 

1. LDR 렌더 타겟의 한계 

지금까지는 스왑체인의 BackBuffer를 만들 때 LDR(Low Dynamic Range) 렌더타겟을 사용해왔다. 

DXGI_FORMAT_R8G8B8A8_UNORM (LDR 포맷)

 

LDR은 UNORM 포맷 이며, 

 

UNORM 포맷은

  • 채널당 8비트를 사용하며, 값의 범위는 0.0 ~ 1.0 를 가지고 이 범위를 256단계로만 표현한다.
  • 또한, PixelShader에서 렌더타겟에 1.0 이상의 값을 출력 하더라도 실제는 0~1 범위로 잘려(Clamp)나간다.

즉, 표현 가능한 값의 범위가 매우 제한적이다

 

 

여기서 1.0은 "모니터 최대 밝기"가 아니다.

 

  • 1.0 은 Reference White(기준 백색) 를 의미하며, 보통 약 100 nit 정도를 의도한 값이다. 
  • 실제 출력 밝기는 디스플레이와 OS 설정에 의해 결정된다. 

 

 

LDR 렌더 타겟에서는

계산 결과가 아무리 밝아도 최종 출력은 기준 백색(≈100 nit) 근처로 제한된다는 뜻.

 

즉,  전등도 1.0 하늘도 1.0 태양도 1.0 으로 밝기의 차이가 모두 사라지며 

이게 LDR 방식의 근본적인 한계다. 

 

 

 

2. HDR 렌더 타겟의 필요성 

사실 조명 계산 자체는 이미 HDR 개념이다. 

픽셀 셰이더에서 계산되는 빛의 값은 1.0을 훨씬 넘는 값을 가질 수 있는 선형 공간(scene-linear) 에서 계산된다.

 

출력 공간은 UNORM [0.0, 1.0] 이지만, 문제는 출력 대상(Render Target) 

  • LDR 렌더타겟(UNORM)은 결과를 0.0 ~ 1.0 으로 잘라버린다.
  • HDR 렌더타겟은 훨씬 넓은 값 범위를 유지할 수 있다.

일반적으로:

  • SDR: 약 256 단계
  • HDR: 약 1024 단계 이상의 표현 정밀도를 가진다.

 

이미지의 쿼드는 NDC 좌표계이다.

즉, HDR 렌더타겟은 밝기 값을 0~1로 자르지 않고 1, 10, 100, 1000 같은 값 그대로 유지한다.
" 현실적인 밝기 차이를 최대한 구현 하려는 것" 

 

 

SDR vs LDR 용어 정리

용어 정의 초점 의미 
SDR Standard Dynamic Range 출력 규격
(Rec. 709, sRGB)
표준 색 공간(Rec.709 / sRGB)과 톤 매핑을 따르는 출력 (디스플레이)
LDR Low Dynamic Range 값의 범위
(Contrast Ratio)
1.0으로 클램프된 값만 저장하는 (렌더타겟)
SDR은 "출력 규격", LDR은 "값이 저장되는 방식"이라는 점이 중요

 

 

 

 

3. HDR값을 그대로 보여주면 안되는 이유

HDR 렌더타겟에 있는 값은 너무 극단적이다.

  • 모니터는 무한한 밝기를 표현할 수 없고
  • 사람 눈도 무한한 밝기 차이를 구분하지 못한다

그래서 HDR 계산 결과를 정리하는 단계 (1. 노출(Exposure)  2. 톤 매핑(Tone Mapping)) 가 필요하다.

 

 

 

 

4. 노출(Exposure) – 전체 밝기 위치 조정

HDR 렌더타겟의 선형 공간에서 계산된 값은 그대로 출력하지 않는다.

그 전에 반드시 거치는 단계가 바로 노출(Exposure) 이다.

 

노출이란?

HDR 선형 공간에서 계산된 모든 픽셀 값에, 일괄적으로 밝기 스케일을 적용하는 과정이다.
즉, "화면 전체 밝기를 한 번에 올리거나 내리는 과정"

 

수식으로 표현하면 다음과 같다

여기서 EV는 Exposure Value

 

EV를 2^EV 형태(지수)로 쓰는 이유는 사람 눈의 밝기 인식이 ‘선형’이 아니라 ‘로그적’이기 때문.

(위 말만 보면 HDR에서는 감마보정이 필요없는건가? 싶을 수도 있지만. 아님. 다른 개념임)

 

 

EV 값의 의미

EV 값 Exposure Factor 의미
EV = 0 1.0 기준 노출 (원본 밝기)
EV = +1 2.0 2배 밝게
EV = -1 0.5 절반으로 어둡게
EV = +2 4.0 4배 밝게
EV = -2 0.25 1/4로 어둡게

 

 

4-1. 노출의 역할 요약

 

  • 화면이 어두우면 → 전체를 밝게
  • 화면이 너무 밝으면 → 전체를 어둡게

 

중요한 포인트는 밝은 것과 어두운 것의 비율은 그대로 두고(대비는 유지), 전체 위치만 위/아래로 이동 하는 것. 

 

 

4-2. 자동 노출 (Auto Exposure)

자동 노출은 "사람 눈 처럼 자동으로 맞추는 기능" 으로

 

  • 동굴 안 → 자동으로 밝게
  • 밖으로 나오면 → 자동으로 어둡게

 

비유하자면, 게임에서 흔히 보는 어두운 곳에서 잠깐 후 밝아지는 효과 

 

 

 

5. 톤 매핑(Tone Mapping) – 사람이 볼 수 있게 압축

톤 매핑은 가장 중요한 부분으로

HDR 값의 넓은 범위를 →  LDR(또는 제한된 HDR 출력 범위) 로 압축하는 과정이다.

 

HDR 계산 결과는 여전히 태양(1000) 하늘(10) 전등(1) 이런 상태인데,

화면은 0 ~ 1만 표현이 가능하니까 

=> 압축이 필요한 상태

 

여기서 톤매핑이

아주 밝은 부분은 과감하게 압축하고, 중간~어두운 영역은 대비를 유지하면서 재분배 한다. 

 

그래서 태양(여전히 가장밝음) 하늘(밝음) 실내(디테일유지) 이런식으로 만든다.

 

이게  Filmic Tone Mapping (ACES) 같은 함수가 하는 일

 

 

5-1. ACES (Filmic Tone Mapping)

ACESFilm은 대표적인 Filmic 톤 매핑 함수이다.

  • 아주 밝은 영역: 인간이 구분하기 어려우므로 강하게 압축
  • 어두운 영역: 상대적인 대비를 유지하도록 비선형적으로 재분배
float3 ACESFilm(float3 x)
{
    float a = 2.51f;
    float b = 0.03f;
    float c = 2.43f;
    float d = 0.59f;
    float e = 0.14f;

    return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
}

 

톤매핑 이후의 값 분포는 다음과 같은 특성을 가진다.

  • 아주 밝은 일부 값만 1.0 이상
  • 대부분의 픽셀은 0.0 ~ 1.0 사이

 

 

 

즉, 여기까지의 파이프라인을 정리하면 아래와 같다. 

[현실적인 밝기 계산]
        ↓
HDR 렌더타겟 (1, 10, 1000 같은 값 유지)
        ↓
노출 (전체 밝기 위치 조정)
        ↓
톤 매핑 (사람 눈에 맞게 압축)
        ↓
0 ~ 1 범위의 최종 색
        ↓
화면 출력

 

 

 

 

6. HDR 백버퍼 설정

이제 이렇게 HDR 계산을 다 했는데, 백버퍼 설정을 안해주면 LDR처럼 취급된다. → “HDR인데 왜 안 밝지?” 상태 발생..!

 

문제의 본질은 

OS는 백버퍼 포맷만 보고서는
이 값이 "SDR 신호인지? HDR 신호인지?" 를 판단할 수 없다.

 

같은 0.8이라도:

  • SDR이라면 → “감마 기반 Rec.709에서의 밝은 회색”
  • HDR이라면 → “PQ 기준에서 훨씬 높은 실제 휘도를 가진 빛”

 

6-1. 포맷만으로 충분하지 않음 

예를 들어 DXGI_FORMAT_R10G10B10A2_UNORM은:

  • 채널당 10비트 정규화 값을 저장할 수 있는 포맷일 뿐
  • 그 값이 어떤 색 공간(Rec.709 / Rec.2020)을 쓰는지
  • 어떤 밝기 해석 방식(EOTF: 감마 / PQ)을 따르는지는 전혀 알 수 없다

그래서 OS 입장에서는:

  • 이 값이 SDR인가? HDR인가?
  • 어떤 방식으로 디스플레이에 전달해야 하나?

판단할 근거가 없다.

 

 

 

6-2. Color Space 설정 필요 

HDR 출력을 제대로 사용하려면:

1. HDR 백버퍼 포맷 생성한 뒤
2. 스왑체인에게 이 버퍼의 값이 어떤 신호인지 반드시 명시해야 한다.

 

예를 들어 다음 설정은 OS에게 이렇게 말하는 것이다. 

if (m_format == DXGI_FORMAT_R10G10B10A2_UNORM)
{
    // 이 백버퍼의 값은
    // PQ(ST.2084)로 인코딩된 HDR10 신호이며
    // 색역은 Rec.2020이고
    // RGB Full Range이다
    HR_T(swapChain3->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020));
}
“이 백버퍼에 들어 있는 0.0~1.0 값은, 감마 기반 SDR이 아니라 PQ 기반 HDR10 신호로 해석하라”

 

 

 

6-2-1. OS HDR 출력 파이프라인 활성화

 

Windows는 내부적으로 SDR 출력 경로와 HDR 출력 경로를 구분해서 처리한다. 

 

스왑체인의 Color Space를

DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020으로 설정해야만

 

  • 해당 스왑체인이 HDR10 출력 대상으로 인식되고
  • OS → 드라이버 → 디스플레이까지 HDR 경로로 신호가 전달된다.

 

정리하자면 

 

HDR 백버퍼 설정이란,
계산이 끝난 숫자에 “이 숫자를 어떻게 해석해야 하는지”를 OS에게 알려주는 마지막 단계다.

 

 

 

 

7. 정리 

  • HDR: 밝기 차이를 계산에서 잃지 않기 위함
  • 노출: 전체 밝기 위치 조정
  • 톤 매핑: 사람이 보기 좋게 압축
  • 백버퍼 설정: OS에게 “이건 HDR이다”라고 알려주는 단계