이번 업그레이드를 적용해도 프로젝트의 시각적 일관성은 유지되지만, 구버전 언리얼 엔진의 자동 노출 시스템과의 하위 호환은 불가능합니다.
이번 블로그는 현재 시스템의 단점과 변경을 하게 된 이유를 살펴볼 것입니다. 자동 노출이 어떻게 (긍정적으로) 바뀌는지도 설명할 것입니다.
히스토그램과 기본 알고리즘
기존 히스토그램과 기본 알고리즘은 사용자들 입장에서의 직관성이 만족스럽지 않았고, 예상대로 항상 작동되지도 않았습니다. 이번 변경사항이 어떤 내용이고, 언리얼 엔진 4.25에 왜 적용되었는지 파악하려면 기존 작동 사례를 살펴볼 필요가 있습니다.- 기본 알고리즘은 씬의 로그 휘도(log luminance) 평균을 사용하여 노출량(metered exposure)을 결정합니다.
- 히스토그램 알고리즘은 씬 전체를 사용하지 않고 히스토그램의 목표 범위 이외의 픽셀은 제외합니다. 이 방식은 나머지 픽셀의 로그 휘도 평균으로 목표 노출을 결정합니다.
이러한 알고리즘은 포스트 프로세스 볼륨의 노출 설정을 기반으로 서로 다른 결과물을 도출합니다. 우리는 이 두 알고리즘이 예상대로, 직관적으로 작동하도록 두 가지 규칙을 고안했습니다.
- 회색은 회색이어야 합니다. 균등한 라이팅이 적용되는 18% 회색 카드(또는 0.18 cd/m^2의 이미시브 표면)는 화면 타깃 컬러가 0.18이어야 한다는 뜻입니다.
- 히스토그램 전반이 기본과 동일해야 한다. 히스토그램의 고저 범위를 0~100%으로 하면 기본 노출 알고리즘과 동일하게 보여야 한다는 뜻입니다.
이러한 논제를 가이드 원칙으로 삼아, 기존 알고리즘과 프로퍼티가 어떻게 혼란을 일으켰고, 언리얼 엔진 4.25에서 어떻게 향상되는지 알아보겠습니다.
4.24에서는 씬에 0.18 cd/m^2의 표면 하나를 생성하고, 히스토그램 범위를 1~99%로 두면 레벨 뷰포트에서 다음과 같은 결과를 얻었습니다.
(좌) 히스토그램 모드 (RGB 254), 언리얼 엔진 4.24, (우) 기본 모드 (RGB 111), 언리얼 엔진 4.24
히스토그램 노출 알고리즘이 거의 흰색에 가깝게(RGB 254로 측정됨) 수렴하는데, 기본 노출 알고리즘은 감마 2.2 공간에서 16% 회색인 회색(RGB 111로 측정됨)으로 수렴합니다.
이런 현상이 발생하는 이유는 무엇이고, 4.25에서 어떻게 개선될까요?
히스토그램 모드의 원래 의도는 히스토그램 중간값을 위한 조정을 할 필요가 없는 것이었습니다. 기본값이 80~98%이므로 히스토그램의 평균은 백색 지점이 됩니다.
기본 모드의 경우, 평균 씬 휘도 연산값을 회색 지점에 사용하는데, 이는 보정 상수(기본값은 16% 회색)에 의해 정의됩니다.
따로 놓고 보면 두 해석 모두 합리적입니다. 히스토그램 노출은 백색 지점으로 조정하고 전체 씬 모드는 회색 지점으로 조정하는 것은 합리적일 수 있지만, 비슷한 모드끼리 전혀 다르게 작동하는 파라미터를 공유하는 건 혼란스럽습니다.
분석 결과, 선택지는 다음과 같았습니다.
- 아무 조치도 하지 않고 자동 및 히스토그램 모드가 서로 다르게 작동하도록 한다.
- 둘을 똑같이 만드는 대신, 플래그와 파라미터가 하위 호환되도록 한다.
- 둘을 통합하는 대신, 하위 호환은 지원하지 않는다.
투표 결과, 세 번째로 정해졌습니다.
첫 번째 선택지는 아티스트가 여전히 혼란스럽고, 직관적이지 않은 파라미터를 사용해야 한다는 문제가 있었습니다. 두 번째 선택지는 기존 문제와 섞여서 파라미터의 직관성이 더 떨어질 것 같았습니다. 이러한 접근법을 세 번째 선택지와 통합하여, 복잡성과 혼란을 줄이는 동시에 아티스트가 툴을 더 직관적으로 사용할 수 있었습니다.
언리얼 엔진 4.25에서는 히스토그램 및 기본 노출 모드가 모두 회색 지점으로 수렴합니다. 히스토그램 모드에서 히스토그램 평균을 회색 지점으로 해석한다는 뜻입니다. 기본 노출 모드에서는 보정 상수(calibration constant)를 제거했습니다.
4.25의 자동 노출은 다음과 같이 변경되었습니다.
(좌) 히스토그램 모드 (RGB 116), (우) 기본 모드 (RGB 117)
히스토그램 모드와 기본 모드 모두 RGB값 측정 시 중간 회색으로 수렴합니다. (반올림에 의한 미세한 차이는 무시). 다음 공식을 사용하면 둘 다 18% 회색이라는 하나의 값이 됩니다.
(0.18^(1.0/2.2))*255=116.95
참고: 히스토그램이 백색으로 수렴하기를 원한다면, 노출 보정(Exposure Compensation) 파라미터를 변경하면 됩니다.
스케일 1.2에서 1.0으로 변경
언리얼 엔진에서 노출값은 EV100으로 해석됩니다. 그래서 EV100이 뭘까요? 복잡하기는 하지만, 여기에서 자세한 정보를 확인하실 수 있습니다.라이트값의 EV100값은 휘도를 cd/m^2로 하여 다음과 같은 공식으로 연산합니다.
EV100 = log2(휘도/1.2)
사용자 대부분은 이미시브값 0.18이 화면에 0.18(감마 보정)로 보이는 ‘유닛이 없는’ 환경에서 작업하므로, 이는 혼란만 야기할 뿐이었습니다. 그리고 이전 버전에서는 log2(1/1.2) = -0.263이라는 직관적이지 않은 노출 보정값을 사용해야 했습니다.
이 불필요한 중간 과정은 문제 해결은커녕 혼란만 가중시켰으며, 이제 기본적으로 제거된 상태입니다. 하지만, 필요하다면 이 과정을 다시 추가할 수 있는 옵션이 있습니다.
1.2의 물리적 기반
이전 언리얼 버전의 자동 노출에 사용했던 EV100 공식은 왜 1.2라는 값을 썼을까요?
해당 공식은 우리가 카메라의 물리적 기반으로 사용하는 ISO 표준 12232:2019에 따라 정의됩니다. 현실에서는 렌즈가 완벽하지 않으므로, 모든 빛이 렌즈를 통과해 센서를 건드리지 않습니다. 애플리케이션 대부분은 렌즈의 투과율을 0.65로 설정합니다. 라이트의 65%만 렌즈를 투과해 센서를 건드리고, 나머지 35%는 흡수, 상호반사, 원축오차로 손실된다고 간주하는 것입니다.
이 ISO 표준에 따라, ISO 100의 채도 기반 속도에서 렌즈는 0.78/q (q는 렌즈 투과율)값의 채도를 가집니다. 애플리케이션 대부분은 q=0.65를 사용합니다. 따라서 결과는 다음과 같습니다.
0.78/0.65 = 1.2.
하지만 언리얼 엔진의 가상 렌즈는 이런 식으로 작동하지 않습니다. 상호반사나 흡수에 의한 라이트 손실이 없기 때문입니다. 그래서 우리는 q를 r.EyeAdaptation.LensAttenutation로 제어 가능한 사용자 정의 변수로 설정했습니다.
참고: 언리얼 엔진의 어테뉴에이션은 기본적으로 0.78로 설정되어 있으므로, 언리얼 엔진 4의 라이팅은 유닛이 없습니다. 원래대로 1.2 스케일을 유지하고 싶으면 렌즈 어테뉴에이션 변수를 기존 값인 0.65로 설정하시면 됩니다.
향상된 물리 카메라 파라미터
물리 기반 카메라 파라미터도 혼란을 유발하는 분야였습니다. 포스트 프로세스 볼륨 및 카메라 설정에서 이용 가능한 수동 미터링 모드를 사용하는 경우, 수동 카메라가 현실의 물리적인 카메라와 유사하도록 노출/ISO/조리개/프레임율을 고려해야 합니다.이 방식의 단점은 워크플로 문제를 유발했다는 것입니다. 일반적인 경우에는 자동 노출로 씬을 구성하여 괜찮아 보일 수 있습니다. 히스토그램 모드(좌측 하단)은 제대로 보일 겁니다. 수동 모드로 전환 시(우측 아래), 노출이 지나치게 어두울 수 있습니다.
(좌) 0에 가까운 히스토그램 노출, (우) 10에 가까운 수동 노출
수동 미터링 모드에서는 자동 노출에 카메라의 파라미터를 사용하므로, 씬이 지나치게 어두울 수 있습니다. 이 모드의 원래 의도는 물리적 카메라를 모방하는 적절한 조리개 설정과 뎁스 오브 필드값으로 현실의 라이팅을 쉽게 조절하는 것이었습니다. 하지만 자동 모드와 동일한 씬을 수동 카메라로 사용할 때 비실용적이라는 단점이 있습니다.
이 워크플로를 향상하고, 더 분명히 하기 위해서 포스트 프로세스 볼륨에 새로운 플래그를 추가했습니다. 물리적 카메라 노출 적용. 물리적 카메라 파라미터를 자동 노출에 적용할지 여부를 제어할 수 있습니다. 이 프로퍼티가 비활성화된 경우, 노출 보정이 0.0인 수동 카메라는 0으로 설정된 자동 노출 씬과 동일하게 된다는 뜻입니다.
새로운 노출 미터링 마스크
아티스트가 환경 내 자동 노출을 더 통제할 수 있도록, 노출 미터링 마스크를 추가할 수 있는 머티리얼 슬롯을 추가했습니다. 이를 통해 아티스트는 화면 전체를 덮는 텍스처를 만들어낼 수 있습니다. 이 텍스처의 각 픽셀 인플루언스는 텍스처 마스크의 가중치 적용에 의해 책정됩니다.(좌) 포스트 프로세스 설정의 노출 미터링 마스크 머티리얼 슬롯, (우) 노출 미터링 마스크 텍스처 예시
위의 미터링 마스크 예시는 화면 끝부분이 아닌 중앙에 픽셀 인플루언스를 더 적용할 수 있습니다. 이는 자동 노출 안정화에 도움이 됩니다. 예를 들어 화면 끝부분에 밝은 오브젝트가 보이면, 예상된 자동 노출값이 갑자기 변할 수 있습니다. 이런 유형의 마스크는 화면 끝부분 샘플의 인플루언스를 줄이므로, 더 안정적이고 떨림이 적은 자동 노출을 가능케 합니다.
(좌) 전체 화면 노출 사용, (우) 노출 미터링 마스크 사용.
참고: 화면 중앙에 인플루언스를 더 부여하거나 화면에 균등하게 가중치를 주는 r.EyeAdaptation.Focus 콘솔 명령어를 제거했습니다. 이 파라미터는 새로운 노출 미터링 마스크와 유사한 기능을 가지고 있었지만, 히스토그램 모드가 아니라 자동 노출 기본 미터링 모드에만 효과가 있었습니다. 아티스트는 새로운 노출 미터링 마스크로 기본 및 히스토그램 모드에서 더 세밀한 연출을 할 수 있습니다.
향상된 HDR 시각화 모드
자동 노출 워크플로를 지속적으로 향상한다는 건 디버깅 및 시각화 모드도 향상한다는 뜻이기도 합니다.참고: 이 뷰는 레벨 뷰포트에서는 보기 > 시각화 > HDR (시각 적응)으로, 콘솔에서는 ShowFlag.VisualizeHDR 1로 활성화할 수 있습니다. 새로운 인터페이스에는 다음과 같은 세 개의 줄이 있습니다.
- 청색 줄은 해당 뷰의 목표 EV100 노출값입니다.
- 히스토그램 또는 기본 노출 미터링 모드와 무관하게 히스토그램 평균 씬 노출은 이와 같습니다.
- 보라색 줄은 현재 씬 뷰의 실제 EV100 노출값입니다.
- 이 뷰에 존재하는 현재 노출은 이와 같습니다. 항상 청색 줄을 향해 이동합니다.
- 백색 줄은 노출 보정을 조절한 뒤 최종 EV100 노출값입니다.
- 포스트 프로세스 파라미터에서 노출 보정을 조정한 뒤 실제 노출값입니다. 백색 및 보라색 줄은 노출 보정값을 기반으로 간극이 유지됩니다. 이 예시에서는 히스토그램에서 백색과 보라색 줄이 2.0 간극을 유지합니다.
참고: HDR (시각 적응) 시각화 모드가 반드시 활성화되어 있어야 합니다. 다음으로 콘솔 변수 r.EyeAdaptation.VisualizeDebugType을 사용하여 디버그 모드로 전환합니다. 0(기본값)이면 톤 매핑 후 씬 색상을 보여주고, 1이면 히스토그램 디버그 모드를 보여줍니다.
이 모드의 히스토그램 디버그 시각화는 매우 밝은 픽셀(예를 들어 태양광)과 매우 어두운 픽셀(예를 들어 어두운 그림자)을 HDR 연산에서 제외합니다. 이 씬에서는 목표 히스토그램 범위에 못 미치면 전부 적색으로, 범위를 넘으면 전부 청색으로 보입니다. 설정한 고저 퍼센트 범위를 기반으로 원하지 않는 픽셀을 연산에서 제외합니다. 픽처 인 픽처(PIP) HDR 씬 연출을 위 히스토그램 디버그 시각화로 교체했습니다.
노출 보정 커브
이번 버전에서는 노출 보정 커브를 업데이트하여 X 및 Y축 값을 취한 곳이 어디인지 명확히 했습니다.그 점을 염두에 두면, 아티스트가 밝고 어두운 영역에서 다른 노출 보정을 원할 수 있다는 사실을 이해할 수 있습니다. 포스트 프로세스 볼륨에 커브 애셋을 배정하면, 원하는 비주얼을 연출하면서도 환경에서 노출 보정이 어떤 값으로 영향을 받는지를 더 섬세하게 제어할 수 있습니다.
(좌) 포스트 프로세스 커브 애셋 배정, (우) 커브 애셋
참고: 콘텐츠 브라우저에서 새로 추가 버튼을 클릭하여 프로젝트에 커브 애셋을 추가한 다음, 기타 카테고리에서 커브를 선택합니다. 그리고 CurveFloat를 선택합니다.
HDR 시각화 모드에는 X, Y축을 나타내는 커브의 모든 정보가 담겨 있습니다. 평균 씬 EV100 값(1)과 히스토그램의 청색 줄(실제 노출)값(1)은 커브 애셋의 X축을 나타냅니다. 노출 보정(커브)은 커브의 Y축을 나타냅니다. 이 정보는 노출 보정(설정)값에 더해져 노출 보정(전체) 합산값을 얻게 됩니다. 이 씬에서 평균 EV100은 0.548입니다. 이 값은 커브 애셋의 X축에 적용되어, Y값 0.864을 반환합니다. 이 값 0.864이 노출 보정(커브)에 적용됩니다. 관련 값은 다음과 같습니다.
- 평균 씬 EV100은 연산한 목표 EV100값이며, 히스토그램에서 청색 줄로 표시됩니다.
- 노출 보정(설정)은 포스트 프로세스 볼륨의 노출 보정 세트입니다.
- 노출 보정(커브)는 커브 애셋의 Y 결과값입니다.
- 노출 보정(전체)는 기존 두 값의 합으로, 최종 노출 보정을 도출합니다.
노출 보정을 '설정'과 '커브'값으로 나누면 설정을 더 세밀하게 제어할 수 있고, 노출 보정이 작동된 이유를 더 명확하게 이해할 수 있습니다.
노출 변경 속도
현재 노출값에서 목표 노출값으로 조정하는 방식에 몇 가지 큰 변화가 있었습니다. 이 변경사항은 히스토그램 뷰에서 시간에 따라 보라색 줄(현재 노출값)이 청색 줄(목표 노출값) 위치로 조정되는 것을 관찰하는 것으로 확인할 수 있습니다.
로그 스페이스 조정
첫 번째 큰 변화는 이제 모든 노출 움직임이 선형값이 아니라 f값으로 이루어진다는 점입니다. (아래 그래프에서 볼 수 있듯이) 기존 설정과는 달리, 노출 적용이 지수적 단계로 이루어져 동일한 속도로 오르내립니다.예를 들어 기존 설정을 사용하면 현재 선형적 평균인 1.0으로 목표 1,000으로 이동할 때, 2초 후 반환점인 500.5에 도달합니다.
유사한 방식으로, 같은 속도에 반대 방향으로 진행해도(1,000에서 시작해 1.0), 2초 후 반환점에 도달합니다.
이런 현상은 직관적으로는 이해가 되지만, 인식 측면에서 문제가 있습니다. 양방향으로 동일한 선형 커브가 그려지기는 하지만, f값 같은 경우는 로그 스페이스에서 인식합니다. 예를 들어 1.0에서 500.5으로 가는 건 8 f값정도지만, 500.5에서 1000.0으로 가는 건 1 f값입니다.
이 경우, 값 상승 시 첫 2초 동안은 약 8 f값, 나머지 커브에서는 1 f값만큼 움직입니다. 하지만 값 하락 시에는 첫 2초 동안 1 f값만, 나머지 시간 동안 8 f값만큼 움직입니다. 따라서 목표 휘도까지 상승할 때는 노출이 빠르게 변화하고, 목표 휘도까지 하락할 때는 노출이 느리게 변화합니다. 언리얼 엔진 4.25 변경사항은 시간 흐름에 따라 노출 조정이 선형적으로 인식되도록 했습니다.
새로운 선형 및 지수함수적 움직임
언리얼 엔진 4.24 및 이전 버전에서는 모든 노출 조정이 지수함수적으로 이루어졌습니다. 이로 인해 다음과 같은 두 가지 문제가 발생했습니다.- 휘도가 조금만 바뀌어도 자동 노출이 빠르게 반응하여 떨림 현상이 발생합니다.
- 대규모 휘도 전환은 항상 빠르게 일어나며, 전환을 늦출 방법도 없습니다. 어두운 곳에서 밝은 곳으로 이동하는 경우, 전환을 늦출 방법이 없었습니다.
이러한 문제를 해결하기 위해 새로운 알고리즘을 적용했습니다. 목표 노출값과 차이가 크면 선형 커브(2)로 시작하지만, 목표값에 가까워지면 지수함수 커브(1)로 전환합니다.
기존 예시(로그 스페이스 조정 항목)를 사용하면, 밝은 씬에 적응하기 시작할 때는 선형적으로 움직입니다. 이제 포스트 프로세스의 가속 및 감속 파라미터는 초당 f값 단위로 측정합니다.
목표 노출에 가까워질수록 움직임은 선형에서 지수함수적으로 바뀌어 일관성을 유지합니다. 이 값은 콘솔 변수 r.EyeAdaptation.ExponentialTransitionDistance로 제어할 수 있습니다. 이 변수는 목표와 r.EyeAdaptation.ExponentialTransitionDistance f값 차이가 날 때 선형에서 지수함수로 전환합니다.
디폴트 지수함수 전환 거리는 1.5 f값입니다. 가속 및 감속으로 노출을 선형적으로 조정하다가, 1.5 f값 차이가 나는 시점에서 지수함수적 움직임으로 전환합니다.
이러한 새로운 방식은 기존 움직임과 비교하면 다음과 같은 몇 가지 강점을 가지고 있습니다.
- 제어 시 떨림이 적습니다. 목표 노출과 차이가 큰 경우, 선형적이므로 화면에 밝은 부분이 나타나도 빠르게 변화하지 않습니다.
- 느린 전환이 이루어지는 경우, 이 파라미터는 더 정밀한 제어를 제공합니다.
모바일 환경에서도 동등한 기능 지원
에픽게임즈 차이나 모바일팀의 노력 덕분에, 언리얼 엔진 4.25에서 지원하는 모든 모바일 플랫폼을 대상으로 자동 노출을 지원 및 최적화할 수 있었습니다. 따라서 모바일도 PC나 콘솔 플랫폼과 마찬가지로 다음과 같은 자동 노출 모드 세 가지를 지원합니다. 히스토그램, 기본 및 수동.참고: 모바일 자동 노출 기능은 ES 3.1 지원을 요구합니다. 언리얼 엔진 4.25는 ES2 지원이 종료되었습니다.
새로운 자동 노출 디폴트값
새로운 알고리즘으로 변경되어 히스토그램 노출 모드의 디폴트값이 바뀌었습니다. 기존에는 80% 저비율 및 98.3% 고비율 범위를 사용하여 히스토그램 대부분을 무시하고, 하이라이트에만 집중하는 방식이었습니다. 새로운 디폴트값은 기본 노출 모드와의 일관성을 위해 10% 저비율에서 90% 고비율 범위로 설정했습니다.이러한 변경 사항이 적용된 뒤, 0.0 디폴트 노출 보정값을 사용하면 일반적인 씬에서 너무 어둡게 보인다는 사실이 밝혀졌습니다. 따라서 새로운 포스트 프로세스 볼륨에서는 디폴트 노출 보정값을 1.0으로 변경했습니다. 하지만 프로젝트 설정의 '자동 노출 바이어스'로 디폴트값을 변경할 수도 있습니다.
언리얼 엔진 4.24 또는 이전 버전의 연출과 비슷한 수준을 원한다면 히스토그램 범위를 80%, 98.3%로 변경하면 됩니다. 그리고 노출 보정으로 log2(1.0/0.18)=2.47을 적용하세요.
둘 중에서 프로젝트에 더 적합한 버전을 선택하세요. 하지만 새로운 노출 디폴트값의 경우, 더 광범위한 히스토그램을 활용하여 기본적으로 서로 다른 노출 모드간의 일관성을 확보합니다.
기존 프로젝트 및 콘텐츠 자동 업데이트
마지막으로, 이번 변경사항은 까다로운 마지막 문제 하나를 남겼습니다. 언리얼 엔진 4.25로 업그레이드 시 기존 콘텐츠는 어떻게 다뤄야 할까요?엔진 버전과 무관하게 콘텐츠가 동일하게 보이는 게 이상적이지만, 이번에는 그럴 수 없었습니다. 우리는 프로젝트를 4.25로 업그레이드 시, 자동 노출 보정 업데이트를 적용하도록 했습니다.
업데이트 로직은 Engine\Source\Runtime\Private 폴더 내 Scene.cpp의 CalculateEyeAdaptationExposureVersionUpdate()에 저장되어 있습니다.
프로젝트에서 히스토그램 노출을 활성화하고 프로젝트 설정에서 디폴트 휘도 범위를 활성화한 경우, 관련 연산이 변경된 것을 고려하여 노출 보정을 약간 조정하게 되니 유의하시기 바랍니다. 예를 들어 히스토그램의 최대 최소 평균이 89.15라면, 노출 보정은 1.5를 적용합니다. 히스토그램 범위가 더 넓다면, 더 작은 노출 보정을 적용합니다. 최대 최소 평균이 50이라면, 노출 보정은 1.0을 적용합니다. 기존 설정과 완전히 동일하면 좋았겠지만, 씬에 있는 콘텐츠가 전부 다르니 불가능한 작업이었습니다. 위 디폴트값을 적용하면 기존 콘텐츠에서 적당한 값을 얻을 수 있습니다.
참고: 프로젝트 전환 시 문제가 있는 것 같다면, 기존 노출 보정값은 AutoExposureBiasBackup이라는 숨겨진 값에 저장되어 있으니 활용하시면 됩니다.
결론
변경사항 때문에 하위 호환성이 없어지고 기존 프로젝트의 비주얼이 달라질 수는 있지만, 자동 노출을 더 쉽게 활용할 수 있게 되었으니 작업 진행이 훨씬 원활해질 것입니다. 툴을 꾸준히 개선 및 업데이트하다 보면, 일반적인 변경사항보다 여파가 큰 방대한 변경이 이뤄질 때도 있습니다.이번 변경사항이 더욱 사용자 친화적인 인터페이스 및 사용 측면에서의 직관성 확보로 이어지기를 바랍니다. 설명한 내용과 관련된 자동 노출의 변경사항 정보를 담은 문서도 확인해보세요.