Реализовать HDR Выход совместимые пользовательские накладки в URP
На этой странице показано, как создать компонент скриптового рендерера, выполняющий следующие действия:
- Композиция выхода одной камеры на другую камеру.
- Применяет тоновое отображение, чтобы сделать настраиваемое наложение совместимым с эффектами выхода HDR.
Это включает в себя шейдер, который применяет тоновое отображение к накладке, в зависимости от порядка кадров.
См. Введение в функции скриптового рендеринга и Введение в скриптовые рендеринговые проходы для более подробной информации.
Этот пример разделен на следующие разделы:
- Предварительные условия
- Настройка сцены
- Создание настраиваемого наложения Render Pass
- Реализация метода RecordRenderGraph
- Создание настраиваемой функции рендеринга накладок
- Создать пользовательский шейдер наложения
- Завершить пользовательские накладки
- Полные образцы кода
- Настраиваемое наложение Рендер код прохода
- Настраиваемый рендер накладок Код функции
- Настраиваемый код шейдера наложения
Предварительные условия
В этом примере предполагается следующее:
- Проект Unity использует URP в качестве активного конвейера отображения.
- Проект настроен для рендеринга HDR со следующими настройками:
- Активный ресурс URP имеет режим Режим сортировки установлен на High Dynamic Range.
- У активного ассета URP включены HDR.
- Установки Project включают HDR Вывод.
Настройка сцены
Для того, чтобы пример работал правильно, вы должны сначала настроить примерную сцену, как показано в следующих инструкциях.
Создайте куб GameObject и установите его позицию в точке начала сцены (X: 0, Y: 0, Z: 0).
Выравнить
Main Cameraтак, чтобы куб был четко виден.Создать новую камеру и назвать ее Оверлей Camera.
Расположите накладную камеру справа от
Main Cameraи выравнивайте ее так, чтобы куб был четко виден.Установите свойство накладной камеры Тип фона на Твердый цвет в окне Inspector.
Установите цвет фона накладки камеры на чисто чёрный с RGBA значениями
0, 0, 0, 0.-
Создайте текстуру рендеринга и назовите ее OverlayRenderTexture. Чтобы создать текстуру рендеринга, перейдите в Ассеты > Создать > Рендеринг > Render Texture.
Примечание: Для лучшей точности HDR используйте формат текстуры рендеринга с плавающим знаком. Для этого выберите текстуру рендеринга, а затем в окне Inspector измените Формат цвета на формат с суффиксом
_SFLOAT. Назначьте текстуру рендеринга накладки свойству Output Texture накладной камеры. Для этого откройте
Overlay Cameraв Inspector и перейдите в Выпуск > Output Texture и выберите OverlayRenderTexture из списка ассетов.Создайте новый ассет Universal Renderer для накладной камеры и назовите его OverlayRenderer. Для этого перейдите в Ассеты > Создать > Рендеринг > URP Universal Renderer.
Выберите активный ресурс URP, затем в окне Inspector перейдите в Рендирование > Список рендереров > +. Выберите OverlayRenderer. Это добавит рендерер накладки в список рендереров.
Выберите накладную камеру, затем в окне Inspector перейдите в Рендеринг > Рендерер. Выберите OverlayRenderer. Это настроит накладную камеру на использование накладного рендера.
Сцена теперь готова для создания настраиваемого наложения с помощью Scriptable Renderer Features.
Создание настраиваемого наложения Render Pass
Чтобы создать настраиваемое наложение, совместимое с HDR Output, необходимо использовать Scriptable Render Pass для создания наложения. HDR Output применяет тоновое отображение к выводу главной камеры во время пост-обработки. В результате выход главной камеры и накладной камеры имеет разное тоновое отображение. Этот проход рендеринга затем происходит после пост-обработки для применения тонового отображения к выводу накладной камеры.
Чтобы создать проход отображения для данного примера, выполните следующие действия:
Создайте скрипт C# и назовите его
CustomOverlayRenderPass.В скрипте удалите код, который Unity вставил в
CustomOverlayRenderPassclass.-
Добавьте следующие директивы
using.using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.Rendering.RenderGraphModule; -
Создать новый
CustomOverlayRenderPassкласс, наследующийScriptableRenderPassкласс и имеет атрибут[SupportedOnRenderer(typeof(UniversalRendererData) -->.[SupportedOnRenderer(typeof(UniversalRendererData))] --> public class CustomOverlayRenderPass : ScriptableRenderPass { } -
Добавьте свойства
Material passMaterialиRTHandle passOverlayTextureв проход рендеринга, как показано ниже.[SupportedOnRenderer(typeof(UniversalRendererData))] --> public class CustomOverlayRenderPass : ScriptableRenderPass { Material passMaterial; RTHandle overlayTextureHandle; } -
Создайте метод конструктора, который принимает материал в качестве параметра и присваивает его
passMaterial. Этот метод также создает профилирующий семплер для прохождения рендеринга и настраивает его на запуск при событииAfterRenderingPostProcessing.public CustomOverlayRenderPass(Material material) { passMaterial = material; profilingSampler = new ProfilingSampler(nameof(CustomOverlayRenderPass)); renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; } -
Добавьте метод
Setupдля прохода рендеринга. Используйте этот метод и параметр для созданияRTHandleиз текстуры накладки, как показано ниже. ИспользованиеRTHandleпозволяетRenderPassAPI взаимодействовать с текстурой рендеринга накладки.public void Setup(Texture overlayTex) { if (overlayTextureHandle != overlayTex) { overlayTextureHandle?.Release(); overlayTextureHandle = RTHandles.Alloc(overlayTex); } } -
Реализация метода
Disposeдля освобождения текстуры накладки при уничтожении прохода рендеринга.public void Dispose() { overlayTextureHandle?.Release(); } -
Создайте две структуры, одну с названием
CopyDataи другую с названиемPassData, которые содержат свойства, показанные ниже. Эти структуры содержат ключевые свойства, необходимые URP для реализации прохода рендеринга.struct CopyData { public TextureHandle source; } struct PassData { public TextureHandle source; public TextureHandle overlayTexture; public TextureHandle internalLut; public Vector4 lutParams; public Material material; } -
Добавьте метод
RecordRenderGraph, как показано ниже.public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { }
Реализация метода RecordRenderGraph
Добавить код из следующих шагов в рамках RecordRenderGraph метода CustomOverlayRenderPass class.
-
Получить данные о пост-обработке, ресурсе и камере из данных кадра.
UniversalPostProcessingData postProcessingData = frameData.Get<UniversalPostProcessingData>(); UniversalResourceData resourceData = frameData.Get<UniversalResourceData>(); UniversalCameraData cameraData = frameData.Get<UniversalCameraData>(); -
Получить текстуру активного цвета из данных ресурса.
TextureHandle activeCameraColor = resourceData.activeColorTexture; -
Создание текстуры для хранения цвета активного объекта камеры.
RenderTextureDescriptor colorCopyDescriptor = cameraData.cameraTargetDescriptor; colorCopyDescriptor.depthBufferBits = (int) DepthBits.None; TextureHandle copiedColor = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorCopyDescriptor, "_CustomCameraColorCopy", false); -
Создайте
RasterRenderPass, чтобы скопировать цветовую цель активной камеры в текстуру. Копия будет использоваться для обработки смешивания.using (var builder = renderGraph.AddRasterRenderPass<CopyData>("Custom Overlay Render Pass - Copy Camera", out var passData)) { passData.source = activeCameraColor; builder.UseTexture(passData.source, AccessFlags.Read); builder.SetRenderAttachment(copiedColor, 0, AccessFlags.WriteAll); builder.SetRenderFunc((CopyData data, RasterGraphContext context) => { Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), 0.0f, false); }); } -
Создайте еще один
RasterRenderPass, чтобы скопировать текстуру наложения на цветовую цель активной камеры с пользовательским материалом. Это контейнер для остальной части кода, который вы добавляете в этом разделе руководства.using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData)) { } -
Настройте свойства, которые необходимы для того, чтобы проход рендеринга смог очистить текстуру накладки, как показано ниже.
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData)) { passData.material = passMaterial; builder.SetRenderAttachment(activeCameraColor, 0, AccessFlags.Write); passData.source = copiedColor; builder.UseTexture(passData.source, AccessFlags.Read); } -
Импорт текстуры в графическую систему рендеринга, а затем установить текстуру в качестве входа.
passData.overlayTexture = renderGraph.ImportTexture(passOverlayTexture); builder.UseTexture(passData.overlayTexture, AccessFlags.Read); -
Проверьте постобработку и цветокоррекцию HDR. Если конфигурация подходит для вывода в HDR, задайте внутреннюю текстуру цветовой LUT, которую HDR принимает на вход, и передайте её параметры в шейдер.
if (postProcessingData.gradingMode == ColorGradingMode.HighDynamicRange && cameraData.postProcessEnabled) { passData.internalLut = resourceData.internalColorLut; builder.UseTexture(passData.internalLut, AccessFlags.Read); int lutHeight = postProcessingData.lutSize; int lutWidth = lutHeight * lutHeight; float postExposure = 1.0f; ColorAdjustments colorAdjustments = VolumeManager.instance.stack.GetComponent<ColorAdjustments>(); if (colorAdjustments != null) { postExposure = Mathf.Pow(2.0f, colorAdjustments.postExposure.value); } passData.lutParams = new Vector4(1f / lutWidth, 1f / lutHeight, lutHeight - 1f, postExposure); }Примечание: Если пост-обработка отключена, то преобразование цвета HDR будет применено после этого прохода рендеринга, и ожидаемое цветовое пространство для вывода камеры будет по умолчанию Rec709. Код в этом примере использует инструкцию
if, чтобы предотвратить изменение вывода накладной камеры этим проходом рендеринга до применения HDR. -
Установите ключевое слово на шейдере, чтобы включить отображение тонов, и добавьте команду для переноса текстуры накладки на цветовую цель активной камеры.
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) => { data.material.SetTexture("_OverlayTexture", data.overlayTexture); bool tonemappingActive = data.internalLut.IsValid(); CoreUtils.SetKeyword(data.material, "TONEMAPPING", tonemappingActive); if (tonemappingActive) { data.material.SetTexture("_InternalLut", data.internalLut); data.material.SetVector("_InternalLut_Params", data.lutParams); } Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0); });
Это завершает скрипт CustomOverlayRenderPass, готовый для добавления в рендерер с помощью функции Scriptable Renderer Feature.
Полный код для этого раздела см. в Код пользовательского Render Pass для наложения.
Создание настраиваемого наложения Скриптовый отображатель
Чтобы добавить CustomOverlayRenderPass в рендерер, необходимо создать Scriptable Renderer Feature, выполнив следующие действия.
Создайте скрипт C# и назовите его
CustomOverlayRendererFeature.В скрипте удалите код, который Unity вставил в
CustomOverlayRendererFeatureclass.-
Добавьте следующие директивы
using.using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; -
Настройка нового
CustomOverlayRendererFeatureкласс, наследующийScriptableRendererFeatureclass.public class CustomOverlayRendererFeature : ScriptableRendererFeature { } -
Добавьте следующие свойства, чтобы содержать ассеты и данные, необходимые для прохождения отображения.
public class CustomOverlayRendererFeature : ScriptableRendererFeature { public Shader hdrShader; public RenderTexture passOverlayTexture; Material passMaterial; CustomOverlayRenderPass overlayRenderPass = null; } -
Создайте метод
AddRenderPassesи используйте его для применения наложения только в представлении Game и к последней камере в стеке камер.public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget) return; } -
После инструкции
ifпередать текстуру наложения в проход рендеринга наложения и поставить проход рендеринга в очередь.public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget) return; overlayRenderPass.Setup(passOverlayTexture); renderer.EnqueuePass(overlayRenderPass); } -
Добавьте метод
Createи создайте экземплярCustomOverlayRenderPassс новым материалом, который используетhdrShader.public override void Create() { passMaterial = CoreUtils.CreateEngineMaterial(hdrShader); overlayRenderPass = new CustomOverlayRenderPass(passMaterial); } -
Реализуйте метод
Disposeдля высвобождения ресурсов, созданных функцией рендеринга после того, как она применила проход рендеринга.protected override void Dispose(bool disposing) { CoreUtils.Destroy(passMaterial); overlayRenderPass.Dispose(); }
Полный код для этого раздела см. в Настраиваемое наложение Скриптовый код функции рендеринга.
Создание настраиваемого накладного шейдера
Материал, созданный CustomOverlayRendererFeature, требует настраиваемого шейдера для обработки наложения и изменений выхода HDR. Следующие шаги демонстрируют, как создать шейдер, способный на это.
Создайте новый шейдер и назовите его
CustomOverlayBlit.-
Удалить код шейдера Unity генерируется автоматически и установить очертания шейдера, как показано ниже.
Shader "Custom/CustomOverlayBlit" { SubShader { Tags{ "RenderPipeline" = "UniversalPipeline" } Pass { ZWrite Off ZTest Always Blend Off Cull Off HLSLPROGRAM #pragma target 2.0 #pragma editor_sync_compilation #pragma vertex Vert #pragma fragment Frag #pragma multi_compile_local_fragment _ TONEMAPPING #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" TEXTURE2D(_InternalLut); TEXTURE2D_X(_OverlayTexture); float4 _InternalLut_Params; #define LutParams _InternalLut_Params.xyz #define PostExposure _InternalLut_Params.w ENDHLSL } } } Создайте метод с именем
ApplyTonemappingи типом возвратаhalf3. Этот метод должен иметь следующие параметры:half3 input,TEXTURE2D_PARAM(lutTex, lutSampler),float3 lutParams,float exposure.-
В методе
ApplyTonemappingумножайтеinputна значениеexposure, затемsaturateна изменённоеinput.half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure) { input *= exposure; float3 inputLutSpace = saturate(LinearToLogC(input)); } -
Примените изменения тонального отображения с помощью
ApplyLut2Dи возвратите результат.half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure) { input *= exposure; float3 inputLutSpace = saturate(LinearToLogC(input)); return ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), inputLutSpace, lutParams); } -
Создайте стандартный метод
Frag, как показано ниже. Поместите этот метод внутрь методаHLSLPROGRAM, но после методаApplyTonemapping.half4 Frag(Varyings input) : SV_Target { } -
В методе
Fragизвлекается оригинальный цвет камеры и цвет наложения.half4 Frag(Varyings input) : SV_Target { half4 color = FragBlit(input, sampler_LinearClamp); half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord); } -
Создайте инструкцию
ifдля проверки, должен ли шейдер применять тоновое отображение. Если шейдер должен применять тоновое отображение, используйте методApplyTonemappingдля его применения к накладке.half4 Frag(Varyings input) : SV_Target { half4 color = FragBlit(input, sampler_LinearClamp); half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord); #if TONEMAPPING overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure); #endif } -
Смешать накладку с оригинальным цветом камеры и вернуть результат.
half4 Frag(Varyings input) : SV_Target { half4 color = FragBlit(input, sampler_LinearClamp); half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord); #if TONEMAPPING overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure); #endif color.rgb = color.rgb * (1.0 - overlay.a) + overlay.rgb * overlay.a; return color; }
Сейдер теперь завершен и готов для использования в скриптах CustomOverlayRenderPass и CustomOverlayRendererFeature.
Чтобы увидеть полный код для этого раздела, см. Настраиваемый код шейдера наложения.
Завершение настраиваемого наложения
Чтобы завершить создание настраиваемого наложения, вы должны настроить созданные вами скрипты, чтобы применить их эффекты к рендерам в сцене. Следующие шаги демонстрируют, как это сделать.
- Найдите и выберите основной рендерер, используемый активным ассетом URP.
- В окне Inspector выберите Добавить функцию рендерера > Настраиваемая функция рендерера накладок, чтобы добавить скрипт
CustomOverlayRendererFeature. - Назначьте шейдер
CustomOverlayBlitсвойству Шейдер настраиваемого наложения Scriptable Renderer Feature. - Назначьте
OverlayRenderTextureсвойству Overlay Texture настраиваемого элемента Scriptable Renderer Feature.
Настраиваемое наложение теперь завершено и должно появиться над основным выходом камеры в режиме воспроизведения. Наложение должно быть тонировано так же, как и основной выход камеры, без видимых различий. Это должно быть похоже на скриншот ниже.

Куб в середине Game с кубом под другим углом в качестве наложения, тональное отображение для соответствия HDR Выход.
Примечание: Конечный результат может отличаться в зависимости от расположения накладной камеры.
Полные образцы кода
Настраиваемый пароль отображения накладок
Ниже приведен полный образец кода для Scriptable Render Pass из примера.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
[SupportedOnRenderer(typeof(UniversalRendererData))] -->
public class CustomOverlayRenderPass : ScriptableRenderPass
{
Material passMaterial;
RTHandle overlayTextureHandle;
public CustomOverlayRenderPass(Material material)
{
passMaterial = material;
profilingSampler = new ProfilingSampler(nameof(CustomOverlayRenderPass));
// The render pass is executed after post processing, so the main camera target has been tonemapped but not the overlay texture
renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public void Setup(Texture overlayTex)
{
//Create an RTHandle from the overlay texture, to import it into the render graph system
if (overlayTextureHandle != overlayTex)
{
overlayTextureHandle?.Release();
overlayTextureHandle = RTHandles.Alloc(overlayTex);
}
}
public void Dispose()
{
overlayTextureHandle?.Release();
}
class CopyData
{
public TextureHandle source;
}
class PassData
{
public TextureHandle source;
public TextureHandle overlayTexture;
public TextureHandle internalLut;
public Vector4 lutParams;
public Material material;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
UniversalPostProcessingData postProcessingData = frameData.Get<UniversalPostProcessingData>();
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
TextureHandle activeCameraColor = resourceData.activeColorTexture;
// Create a texture to copy the active camera color target into
RenderTextureDescriptor colorCopyDescriptor = cameraData.cameraTargetDescriptor;
colorCopyDescriptor.depthBufferBits = (int) DepthBits.None;
TextureHandle copiedColor = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorCopyDescriptor, "_CustomCameraColorCopy", false);
// Copy the active camera color target into the texture
using (var builder = renderGraph.AddRasterRenderPass<CopyData>("Custom Overlay Render Pass - Copy Camera", out var passData))
{
passData.source = activeCameraColor;
builder.UseTexture(passData.source, AccessFlags.Read);
builder.SetRenderAttachment(copiedColor, 0, AccessFlags.WriteAll);
builder.SetRenderFunc((CopyData data, RasterGraphContext context) =>
{
Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), 0.0f, false);
});
}
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData))
{
passData.material = passMaterial;
builder.SetRenderAttachment(activeCameraColor, 0, AccessFlags.Write);
passData.source = copiedColor;
builder.UseTexture(passData.source, AccessFlags.Read);
// Import the overlay texture that will be copied onto the camera color, and set it as an input
passData.overlayTexture = renderGraph.ImportTexture(overlayTextureHandle);
builder.UseTexture(passData.overlayTexture, AccessFlags.Read);
// If post-processing is enabled on the main camera, apply the tonemapping to the overlay texture as well
// If post processing is disabled, the HDR color conversion will be applied after this render pass and the expected colorspace for the cameras output is the default Rec709
if (postProcessingData.gradingMode == ColorGradingMode.HighDynamicRange && cameraData.postProcessEnabled)
{
// Import the internal color LUT texture used for HDR color grading and tonemapping
// This includes any HDR color conversion URP needs for the display, so the output of the camera is in the display's color gamut
passData.internalLut = resourceData.internalColorLut;
builder.UseTexture(passData.internalLut, AccessFlags.Read);
// Pass LUT parameters to the shader
int lutHeight = postProcessingData.lutSize;
int lutWidth = lutHeight * lutHeight;
float postExposure = 1.0f;
ColorAdjustments colorAdjustments = VolumeManager.instance.stack.GetComponent<ColorAdjustments>();
if (colorAdjustments != null)
{
postExposure = Mathf.Pow(2.0f, colorAdjustments.postExposure.value);
}
passData.lutParams = new Vector4(1f / lutWidth, 1f / lutHeight, lutHeight - 1f, postExposure);
}
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
{
// Pass parameters to the shader
data.material.SetTexture("_OverlayTexture", data.overlayTexture);
// Set a keyword on the shader to enable tonemapping
bool tonemappingActive = data.internalLut.IsValid();
CoreUtils.SetKeyword(data.material, "TONEMAPPING", tonemappingActive);
if (tonemappingActive)
{
data.material.SetTexture("_InternalLut", data.internalLut);
data.material.SetVector("_InternalLut_Params", data.lutParams);
}
// Blit the overlay texture onto the camera color
Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
});
}
}
}
Настраиваемое наложение Скриптовый рендер Код функции
Ниже приведен полный образец кода для функции Scriptable Renderer Feature из примера.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class CustomOverlayRendererFeature : ScriptableRendererFeature
{
public Shader hdrShader;
public RenderTexture passOverlayTexture;
Material passMaterial;
CustomOverlayRenderPass overlayRenderPass = null;
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
// Render the overlay onto the main camera during Game view rendering only, for the last camera in the camera stack
if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget)
return;
// Pass the overlay texture at runtime in case it changes
overlayRenderPass.Setup(passOverlayTexture);
// Enqueue the render pass to be executed
renderer.EnqueuePass(overlayRenderPass);
}
public override void Create()
{
// Create a blit material from the given shader
passMaterial = CoreUtils.CreateEngineMaterial(hdrShader);
// Create the render pass
overlayRenderPass = new CustomOverlayRenderPass(passMaterial);
}
protected override void Dispose(bool disposing)
{
// Destroy the render pass resources
CoreUtils.Destroy(passMaterial);
overlayRenderPass.Dispose();
}
}
Настраиваемый код шейдера наложения
Ниже приведен полный образец кода для шейдера из примера.
Shader "Custom/CustomOverlayBlit"
{
SubShader
{
Tags{ "RenderPipeline" = "UniversalPipeline" }
Pass
{
ZWrite Off ZTest Always Blend Off Cull Off
HLSLPROGRAM
#pragma target 2.0
#pragma editor_sync_compilation
#pragma vertex Vert
#pragma fragment Frag
#pragma multi_compile_local_fragment _ TONEMAPPING
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
TEXTURE2D(_InternalLut);
TEXTURE2D_X(_OverlayTexture);
float4 _InternalLut_Params;
#define LutParams _InternalLut_Params.xyz
#define PostExposure _InternalLut_Params.w
half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure)
{
input *= exposure;
float3 inputLutSpace = saturate(LinearToLogC(input)); // LUT space is in LogC
return ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), inputLutSpace, lutParams);
}
half4 Frag(Varyings input) : SV_Target
{
// Get the original camera color
half4 color = FragBlit(input, sampler_LinearClamp);
// Get the overlay color
half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord);
// Tonemap the overlay
#if TONEMAPPING
overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure);
#endif
// Blend overlay and color
color.rgb = color.rgb * (1.0 - overlay.a) + overlay.rgb * overlay.a;
return color;
}
ENDHLSL
}
}
}