LDR ( Low Dynamic Range ) / HDR ( High Dynamic Range ) / Tone Mapping
- LDR : 기존의 색상 표현은 색상당 8bit 으로 표현해왔다. 하지만 Light 연산을 통해 출력을 할 경우 해당 Color가 1.0을 넘는
경우가 있는데 출력시에 [0.0, 1.0] 까지만 표현이 가능하다.
- HDR : 조금 더 넓은 범위의 Color를 표현하기 위해 장면의 고휘도 값을 Rendering Pipeline 전체에 유지하고, 그 결과를
디스플레이 장치에 출력할 수 있는 범위로 압축하는 방식이다.
- Tone Mapping : Shader 내에서는 HDR로 계산을하고 Rendering시에는 LDR로 변환을 해주는 것이다. 즉, HDR 결과를
디스플레이 출력이 가능한 적합한 휘도 범위로 변환해주는 처리이다.
HDR 장점
- 음영이 보다 현실감이 있게 표현 할 수 있다.
- 노출 보정을 할 수 있다. (어두운 공간에서 갑작스럽게 밝은 공간으로 갔을경우 적응하는데 시간이 걸리는 현상)
- 눈부심 표현이 가능하다. (Bloom, Glare, Glow)
Tone Mapping 방식
- 화면의 평균 휘도를 구한다.
- 평균 휘도를 키값으로 하여, 표시 가능한 LDR 색상으로 맵핑한다.
- 매번 처리를 해주는 것이 아니라 최종 출력물의 후처리로 해준다.
// LDR RenderTarget
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = width;
texDesc.Height = height;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
// HDR RenderTarget
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = width;
texDesc.Height = height;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; // 색상당 326bit 부동 소수점
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
- LDR 출력에서 HDR 출력으로 변경시 주의할 점은 출력시 채널별 8bit Format이 아닌 32bit 부동 소수점으로 출력을하여
Tone Mapping을 해주어야 하는점을 주의해야 할 것이다.
- 32bit 부동 소수점으로 출력 해논 RenderTarget을 기반으로 Tone Mapping을 통해 [0.0, 1.0] 범위의 값으로 압축하여
디스플레이에 출력하면 된다.
float3 Multiply(const float3 m[3], const float3 v)
{
float x = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2];
float y = m[1][0] * v[1] + m[1][1] * v[1] + m[1][2] * v[2];
float z = m[2][0] * v[1] + m[2][1] * v[1] + m[2][2] * v[2];
return float3(x, y, z);
}
float3 rtt_and_odt_fit(float3 v)
{
float3 a = v * (v + 0.0245786f) - 0.000090537f;
float3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
return a / b;
}
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
static float3 aces_input_matrix[3] = { float3(0.59719f, 0.35458f, 0.04823f), float3(0.07600f, 0.90834f, 0.01566f), float3(0.02840f, 0.13383f, 0.83777f) };
// ODT_SAT => XYZ => D60_2_D65 => sRGB
static float3 aces_output_matrix[3] = { float3(1.60475f, -0.53108f, -0.07367f), float3(-0.10208f, 1.10813f, -0.00605f), float3(-0.00327f, -0.07276f, 1.07602f) };
float3 ACESToneMapping(float3 colorIn)
{
colorIn = Multiply(aces_input_matrix, colorIn);
colorIn = rtt_and_odt_fit(colorIn);
colorIn = Multiply(aces_output_matrix, colorIn);
return saturate(colorIn);
}
- 최종 출력 전 ToneMapping을 통해 HDR 범위에서 LDR 범위로 압축하여 출력해주면 된다.
'DirectX 11' 카테고리의 다른 글
[DirectX 11] Bloom (1) | 2022.02.17 |
---|---|
[DirectX 11] Lambert / Half Lambert (0) | 2022.02.07 |
[DirectX 11] IBL (Image Based Lighting) (0) | 2022.01.23 |
[DirectX 11] PBR (Physically Based Rendering) (0) | 2022.01.21 |
[DirectX 11] Deferred Rendering FXAA (0) | 2022.01.16 |