Устранение неисправностей с сценариями отображения с выходом HDR в URP
Выход с высоким динамическим диапазоном (HDR) изменяет входные данные для вашего скриптируемого прохода рендеринга, когда он применяет отображение тонов и преобразование цветового пространства. Эти изменения могут привести к тому, что ваш скриптируемый проход рендеринга даст неправильные результаты. Это означает, что при использовании HDR Output и скриптируемого прохода рендеринга, который происходит в точке впрыска AfterRenderingPostProcessing или после нее, вам необходимо учитывать изменения, которые производит HDR Output. Это также относится к случаям, когда вы хотите добавить накладки во время или после пост-обработки, например, UI или выход из других камер, потому что вам нужно работать с цветовой гаммой, полученной из HDR Output. Чтобы скриптируемый проход рендеринга работал с изменениями, которые производит HDR Output, вы должны вручную выполнить отображение тонов и преобразовать цветовое пространство в скрипте.
Однако, если вы добавите свой скриптируемый проход рендеринга в точке введения BeforeRenderingPostProcessing или до нее, вам не нужно вносить никаких изменений для совместимости с HDR Output. Это потому, что Unity выполняет ваш скриптируемый проход рендеринга до того, как он рендерингирует HDR Output.
Примечание: Вы можете избежать этой проблемы, если используете стек камер для рендеринга вывода камеры до того, как Unity выполнит отображение тонов. Unity затем применяет обработку вывода HDR к последней камере в стеке. Чтобы узнать, как настроить стек камер, см. Наложение камер.
Отображение тонов и преобразование цветового пространства в сценарии
Для того, чтобы скриптируемый проход рендеринга работал с изменениями, которые HDR Output делает в цветовом пространстве и динамическом диапазоне, используйте функцию SetupHDROutput для применения отображения тонов и преобразования цветового пространства к материалу, измененному скриптируемым проходом рендеринга:
Откройте скрипт C#, который содержит Scriptable Render Pass, который вы хотите использовать с HDR Output.
-
Добавить метод с именем
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 Output и включена ли на камере пост-обработка. Если ни одно из условий не выполнено, отключите ключевые слова шейдера HDR Output, чтобы уменьшить использование ресурсов.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); } -
Получить компонент тонового отображения из Volume Manager.
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 Output shader.
// 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); Вызывайте метод SetupHDROutput в вашей функции Execute(), чтобы убедиться, что Выход HDR учитывается всякий раз, когда используется этот Scriptable Render Pass.
Полный пример скрипта
Ниже приведен полный код из примера:
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);
}
}
}