HDR(High Dynamic Range) 출력은 톤 매핑과 색 공간 변환을 적용할 때 스크립터블 렌더 패스에 대한 입력을 변경합니다. 이러한 변화로 인해 스크립터블 렌더 패스가 잘못된 결과를 생성할 수 있습니다. 따라서__ HDR__하이 다이내믹 레인지
See in Glossary 출력 및 AfterRenderingPostProcessing 주입 지점 또는 그 이후에 발생하는 스크립터블 렌더 패스를 사용하는 경우, HDR 출력으로 인해 발생하는 변화를 고려해야 합니다. 이는 포스트 프로세싱 도중 또는 이후에 오버레이를 추가하려는 경우에도 마찬가지인데(예: UI 또는 다른 카메라의 출력), 이는 HDR 출력에 따른 색 영역을 사용해야 하기 때문입니다. 스크립터블 렌더 패스가 HDR 출력에 따른 변화와 함께 작동하도록 하려면 스크립트에서 수동으로 톤 매핑과 색 공간 전환을 수행해야 합니다.
그러나 BeforeRenderingPostProcessing 주입 지점 또는 그 이전에 스크립터블 렌더 패스를 추가하는 경우 HDR 출력과의 호환성을 위해 변경해야 할 것은 없습니다. 이는 Unity가 HDR 출력을 렌더링하기 전에 스크립터블 렌더 패스를 실행하기 때문입니다.
참고: Unity가 톤 매핑을 수행하기 전에 카메라 스택을 사용하여 카메라 출력을 렌더링하는 경우 이 문제를 방지할 수 있습니다. 이후 Unity는 스택의 마지막 카메라에 HDR 출력 처리를 적용합니다. 카메라 스택을 설정하는 방법은 카메라 스태킹을 참고하십시오.
스크립터블 렌더 패스가 HDR 출력에 따른 색 공간 및 동적 범위의 변화와 함께 작동하도록 하려면 SetupHDROutput 함수를 사용하여 스크립터블 렌더 패스가 변경하는 머티리얼에 톤 매핑과 색 공간 변환을 적용합니다.
HDR 출력과 함께 사용할 스크립터블 렌더 패스를 포함하는 C# 스크립트를 엽니다.
Render Pass 클래스에 이름이 SetupHDROutput인 메서드를 추가합니다.
SetupHDROutput 함수는 예컨대 다음 스크립트처럼 사용할 수 있습니다.
class CustomFullScreenRenderPass : ScriptableRenderPass
{
// Leave your existing Render Pass code here
static void SetupHDROutput(ref CameraData cameraData, Material material)
{
// This is where most HDR related code is added
}
}
if 문을 추가하여 HDR 출력이 활성화되어 있으며 카메라에 포스트 프로세싱이 활성화되어 있는지 확인합니다. 두 조건 중 하나라도 충족되지 않을 경우 HDR 출력 셰이더 키워드를 비활성화하여 리소스 사용량을 줄이십시오.
static void SetupHDROutput(ref CameraData cameraData, Material material)
{
// If post processing is enabled, color grading has already applied tone mapping
// As a result the input here will be in the display colorspace (Rec2020, P3, etc) and in nits
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
}
else
{
// If HDR output is disabled, disable HDR output-related keywords
// If post processing is disabled, the final pass will do the color conversion so there is
// no need to account for HDR Output
material.DisableKeyword(HDROutputUtils.ShaderKeywords.HDR_INPUT);
}
}
아래와 같이 디스플레이에서 휘도 정보를 검색하고 저장할 변수를 생성합니다.
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
// Get luminance information from the display, these define the dynamic range of the display.
float minNits = cameraData.hdrDisplayInformation.minToneMapLuminance;
float maxNits = cameraData.hdrDisplayInformation.maxToneMapLuminance;
float paperWhite = cameraData.hdrDisplayInformation.paperWhiteNits;
}
else
{
// If HDR output is disabled, disable HDR output-related keywords
// If post processing is disabled, the final pass will do the color conversion so there is
// no need to account for HDR Output
material.DisableKeyword(HDROutputUtils.ShaderKeywords.HDR_INPUT);
}
볼륨 관리자에서 톤 매핑 컴포넌트를 가져옵니다.
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
var tonemapping = VolumeManager.instance.stack.GetComponent<Tonemapping>();
// Get luminance information from the display, these define the dynamic range of the display.
float minNits = cameraData.hdrDisplayInformation.minToneMapLuminance;
float maxNits = cameraData.hdrDisplayInformation.maxToneMapLuminance;
float paperWhite = cameraData.hdrDisplayInformation.paperWhiteNits;
}
다른 if 문을 추가하여 톤 매핑 컴포넌트가 있는지 확인합니다. 톤 매핑 컴포넌트가 존재할 경우 디스플레이의 휘도 데이터를 오버라이드할 수 있습니다.
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
var tonemapping = VolumeManager.instance.stack.GetComponent<Tonemapping>();
// Get luminance information from the display, these define the dynamic range of the display.
float minNits = cameraData.hdrDisplayInformation.minToneMapLuminance;
float maxNits = cameraData.hdrDisplayInformation.maxToneMapLuminance;
float paperWhite = cameraData.hdrDisplayInformation.paperWhiteNits;
if (tonemapping != null)
{
// Tone mapping post process can override the luminance retrieved from the display
if (!tonemapping.detectPaperWhite.value)
{
paperWhite = tonemapping.paperWhite.value;
}
if (!tonemapping.detectBrightnessLimits.value)
{
minNits = tonemapping.minNits.value;
maxNits = tonemapping.maxNits.value;
}
}
}
디스플레이 및 톤 매핑의 휘도 데이터를 사용하여 머티리얼의 휘도 프로퍼티를 설정합니다.
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
var tonemapping = VolumeManager.instance.stack.GetComponent<Tonemapping>();
// Get luminance information from the display, these define the dynamic range of the display.
float minNits = cameraData.hdrDisplayInformation.minToneMapLuminance;
float maxNits = cameraData.hdrDisplayInformation.maxToneMapLuminance;
float paperWhite = cameraData.hdrDisplayInformation.paperWhiteNits;
if (tonemapping != null)
{
// Tone mapping post process can override the luminance retrieved from the display
if (!tonemapping.detectPaperWhite.value)
{
paperWhite = tonemapping.paperWhite.value;
}
if (!tonemapping.detectBrightnessLimits.value)
{
minNits = tonemapping.minNits.value;
maxNits = tonemapping.maxNits.value;
}
}
// Pass luminance data to the material, use these to interpret the range of values the
// input will be in.
material.SetFloat("_MinNits", minNits);
material.SetFloat("_MaxNits", maxNits);
material.SetFloat("_PaperWhite", paperWhite);
}
현재 색 공간의 색 영역을 가져와 머티리얼에 전달합니다.
// Pass luminance data to the material, use these to interpret the range of values the
// input will be in.
material.SetFloat("_MinNits", minNits);
material.SetFloat("_MaxNits", maxNits);
material.SetFloat("_PaperWhite", paperWhite);
// Pass the color gamut data to the material (colorspace and transfer function).
HDROutputUtils.GetColorSpaceForGamut(cameraData.hdrDisplayColorGamut, out int colorspaceValue);
material.SetInteger("_HDRColorspace", colorspaceValue);
HDR 출력 셰이더 키워드를 활성화합니다.
// Pass the color gamut data to the material (colorspace and transfer function).
HDROutputUtils.GetColorSpaceForGamut(cameraData.hdrDisplayColorGamut, out int colorspaceValue);
material.SetInteger("_HDRColorspace", colorspaceValue);
// Enable HDR shader keywords
material.EnableKeyword(HDROutputUtils.ShaderKeywords.HDR_INPUT);
Execute() 함수에서 Setup HDR Output 메서드를 호출하여 이 스크립터블 렌더 패스가 사용 중일 때마다 HDR 출력이 계산되도록 합니다.
다음은 예시의 코드 완성본입니다.
class CustomFullScreenRenderPass : ScriptableRenderPass
{
// Leave your existing Render Pass code here
static void SetupHDROutput(ref CameraData cameraData, Material material)
{
// If post processing is enabled, color grading has already applied tone mapping
// As a result the input here will be in the display colorspace (Rec2020, P3, etc) and in nits
if (cameraData.isHDROutputActive && cameraData.postProcessEnabled)
{
var tonemapping = VolumeManager.instance.stack.GetComponent<Tonemapping>();
// Get luminance information from the display, these define the dynamic range of the display.
float minNits = cameraData.hdrDisplayInformation.minToneMapLuminance;
float maxNits = cameraData.hdrDisplayInformation.maxToneMapLuminance;
float paperWhite = cameraData.hdrDisplayInformation.paperWhiteNits;
if (tonemapping != null)
{
// Tone mapping post process can override the luminance retrieved from the display
if (!tonemapping.detectPaperWhite.value)
{
paperWhite = tonemapping.paperWhite.value;
}
if (!tonemapping.detectBrightnessLimits.value)
{
minNits = tonemapping.minNits.value;
maxNits = tonemapping.maxNits.value;
}
}
// Pass luminance data to the material, use these to interpret the range of values the
// input will be in.
material.SetFloat("_MinNits", minNits);
material.SetFloat("_MaxNits", maxNits);
material.SetFloat("_PaperWhite", paperWhite);
// Pass the color gamut data to the material (colorspace and transfer function).
HDROutputUtils.GetColorSpaceForGamut(cameraData.hdrDisplayColorGamut, out int colorspaceValue);
material.SetInteger("_HDRColorspace", colorspaceValue);
// Enable HDR shader keywords
material.EnableKeyword(HDROutputUtils.ShaderKeywords.HDR_INPUT);
}
else
{
// If HDR output is disabled, disable HDR output-related keywords
// If post processing is disabled, the final pass will do the color conversion so there is
// no need to account for HDR Output
material.DisableKeyword(HDROutputUtils.ShaderKeywords.HDR_INPUT);
}
}
}