티스토리 뷰
이전에는 사진에서 쓰이는 톤매핑 구현하다(했다가 그만 뒀는데) 치웠는데
검색어를 바꾸니 더 나오네;
https://www.slideshare.net/youpyo/hdr-8480350
https://www.slideshare.net/cagetu/ndc11-hdr
40 페이지 부터 언급이 되어있다.
42 페이지 Reinhard 가 나온다.
그 다음이야기가 아래에서 이어진다.
http://egloos.zum.com/cagetu/v/6198009
우선 이걸 기반으로 ModelViewer를 해석해보자.
ToneMappingUtility.hlsli 에서
float3 TM_Reinhard(float3 hdr, float k = 1.0)
{
return hdr / (hdr + k);
}
// The next generation of filmic tone operators.
float3 ToneMapACES( float3 hdr )
{
const float A = 2.51, B = 0.03, C = 2.43, D = 0.59, E = 0.14;
return saturate((hdr * (A * hdr + B)) / (hdr * (C * hdr + D) + E));
}
이렇게 되어있는데 ACES는 표준이라는데 저 공식이면 끝나는건가?
https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
언리얼 기본은 ACES 라네
https://docs.unrealengine.com/latest/INT/Support/Builds/ReleaseNotes/2015/4_8/
그리고 32x32x32 LUT로 50% 빨라졌다는데 뭔지;
머 대강 먼가 시스템이 있는데 근사하는 매핑 커브를 얻었다는거 같다.
머 그담에...
https://developer.nvidia.com/high-dynamic-range-display-development
900 및 1000 시리즈의 모든 NVIDIA GPU는 HDR 디스플레이 출력을 지원합니다
1\. 내부적으로 좋은 HDR 데이터를 렌더링합니다.
2\. 렌더링 된 색상 데이터의 정밀도 유지.
3\. 장면을 적절하게 매핑합니다.
4\. NVAPI를 사용하여 드라이버와 통신하고 HDR 이미지를 표시하고자 함을 표시하십시오.
NVAPI 를 통해 통신하라는데;
언리얼에서는 어떻게 박은거지?
https://docs.unrealengine.com/latest/INT/Engine/Rendering/HDRDisplayOutput/index.html
MiniEngine 에서는 Direct 12 에서 그냥 HDR 스왑체인을 생성하고 끝이네;
DXGI_FORMAT SwapChainFormats[2] = { DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM };
그 다음엔 자동 노출보정이다.
https://knarkowicz.wordpress.com/2016/01/09/automatic-exposure/
자동 노출에 대한 표준 접근 방식은 장면의 기하 평균 (log2 평균)을 계산하고,
그런 다음 모든 픽셀에 노출을 곱하고 톤 매핑, 색상 채점 및 감마를 추가합니다.
다른 곳에서도 늘 나오는 이런 저런 문제로 인해 평균은 때려치우고 결국 히스토그램이 등장했다는 건데
MiniEngine 에서는
- Extract Luma
- Generate Histogram
- AdaptExposure
로 구성되는데
- Luma
가로 세로 0.5 배 한 이미지에 Luma 를 1~255로 변경하여 기록한다.
// Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x
float3 color1 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x, -offset.y), 0 );
float3 color2 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x, -offset.y), 0 );
float3 color3 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x, offset.y), 0 );
float3 color4 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x, offset.y), 0 );
buffer manager 에서 무조건 1/4 이상을 유지합시다라고 했기에 BiLinear는 필요없을것 같은데 사람일은 모르니께 그냥 넘어가자
const float MinLog = Exposure[4];
const float RcpLogRange = Exposure[7];
float logLuma = saturate((log2(luma) - MinLog) * RcpLogRange); // Rescale to [0.0, 1.0]
LumaResult[DTid.xy] = logLuma * 254.0 + 1.0; // Rescale to [1, 255]
Min은 -12, Max는 4이다.
- Histogram
384라는 값이 나와서 당황했는데
Context.SetPipelineState(GenerateHistogramCS);
Context.Dispatch2D(g_LumaLR.GetWidth(), g_LumaLR.GetHeight(), 16, 384);
별거 없어 보인다. 그냥 하나의 thread excution 에 단순히 InterlockedAdd 하기엔 아까웠는지 24칸을 수행한다는 것 같다.
16*24 = 384
// Loop 24 times until the entire column has been processed
for (uint TopY = 0; TopY < 384; TopY += 16)
{
uint QuantizedLogLuma = LumaBuf[DTid.xy + uint2(0, TopY)];
InterlockedAdd( g_TileHistogram[QuantizedLogLuma], 1 );
}
- Adaptive Exposer
먼가 코드가 길다?
마지막으로 히스토그램을 계산 한 후 가장 어두운 픽셀의 큰 비율
(50 % -80 %), 가장 밝은 픽셀의 작은 비율 (2 % -20 %)을 건너 뛰고 나
머지 픽셀의 평균을 계산합니다.
이 방법을 계량하면 자동 노출이 안정화되고 중요 무언가에 집중할 수 있습니다.
인데, 이건 머냐;
[numthreads( 256, 1, 1 )]
256 칸 밖에 안된느데 그냥 하면 안되나;;
// 0은 빈칸, 1-255 까지, 존재
float WeightedSum = (float)GI * (float)Histogram.Load(GI * 4);
[unroll]
for (uint i = 1; i < 256; i *= 2)
{
gs_Accum[GI] = WeightedSum; // Write
GroupMemoryBarrierWithGroupSync(); // Sync
WeightedSum += gs_Accum[(GI + i) % 256]; // Read
GroupMemoryBarrierWithGroupSync(); // Sync
}
그냥 for문 돌리면 히스토그램 생성 + 다시 저장까지 합쳐서 0.071 ms 인데, 위 방법으로 하면 0.067 ms 가 나온다. 진짜 대충 측정했기에 의미가 있는지는 모르겠지만 아주 약간은 도움이 된다는 걸로;
256칸의 합을 계산하기 위해, 0+1, 1+2, 2+3,... 이걸 다시 0,1,2 칸에 저장 0+2, 1+3, 2+4,... 이러면, 0+1+2+3 이됨. 이런식. 그다음엔 그냥 평균 구하고, 원복 시키고 등등
이걸 다하면,
먼가 보이다가 급속도록 검해지는 화면
cbuffer 값을 설정안해뒀네;
너무 어둡다.
float targetExposure = TargetLuminance / log(AvgLuminance);
Key 값을 받는구나;
시커먼 곳을 보다가 돌리면,
어두어진다.
'Game > MMD' 카테고리의 다른 글
Outline (2) (0) | 2017.10.06 |
---|---|
Deferred Rendering (2) (0) | 2017.10.02 |
Outline (1) (0) | 2017.09.21 |
Deferred Rendering (1) (0) | 2017.09.19 |
Bullet (5) Skinning (0) | 2017.08.31 |
- Total
- Today
- Yesterday