reckfellENGINE

Экранные шейдеры: чтение кадра и цепочка эффектов

Обесцветить показанное изображение и правильно передать результат следующему проходу.

На этой странице

Запустить пример

Скачать проект. Нужны Reckfell 1.0.0 с C# SDK и Forward+/Vulkan. Откройте project.reckfell, соберите C# и запустите Main.rscene. Для исходной комнаты выберите Preview=Original, для обесцвечивания — Grayscale, для диагностической цепочки — Chained. Во время выполнения вызывайте SetPreview(mode) после _Ready.

Комната рендерится в отдельном SubViewport и показывается через TextureRect. Затем canvas_item shader читает уже показанное изображение. Создание источника и полный C#-контроллер — в руководстве по живой текстуре.

Исходное изображение:

Исходная живая текстура комнаты до экранного эффекта

Та же текстура, обесцвеченная экранным shader:

Чтение screen_texture и обесцвечивание в canvas_item

Читать координаты экрана

Файл ScreenTone.reckfellshader:

Шейдер
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear;
uniform float desaturate : hint_range(0.0, 1.0) = 0.0;
void fragment() {
    vec4 source = textureLod(screen_texture, SCREEN_UV, 0.0);
    float gray = dot(source.rgb, vec3(0.2126, 0.7152, 0.0722));
    COLOR = vec4(mix(source.rgb, vec3(gray), desaturate), source.a);
}

hint_screen_texture привязывает sampler к копии экрана текущего viewport. SCREEN_UV задаёт координаты этого экрана; UV относится к геометрии самого ColorRect. При перемещении или уменьшении прямоугольника SCREEN_UV сохраняет совпадение с изображением позади него.

repeat_disable отключает повтор текстуры за её краями, filter_linear задаёт линейную выборку. textureLod(..., 0.0) здесь читает базовый уровень. Пример не использует mipmap blur; увеличение LOD само по себе без подходящего фильтра не является законченным решением размытия.

При desaturate=0 shader возвращает исходный цвет. При 1 все RGB-каналы равны взвешенному серому значению. Alpha источника сохраняется. ColorRect должен быть нарисован после TextureRect и покрывать область эффекта; белый ColorRect без назначенного ShaderMaterial просто закроет изображение.

Соединить два прохода

Второй shader ScreenInvert.reckfellshader:

Шейдер
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear;
void fragment() {
    vec4 source = textureLod(screen_texture, SCREEN_UV, 0.0);
    COLOR = vec4(vec3(1.0) - source.rgb, source.a);
}

При первом 2D-элементе с hint_screen_texture движок получает копию экрана, если её ещё не подготовил BackBufferCopy. Следующий screen-reading shader обычно использует эту же копию. Он не получает результат предыдущего эффекта автоматически.

Порядок в примере при одинаковом z_index:

  1. Display показывает живую текстуру комнаты.
  2. TonePass обесцвечивает её.
  3. Copy с CopyMode=Viewport копирует уже обесцвеченный кадр.
  4. InvertPass читает обновлённую копию и инвертирует её.

Если отключить Copy, инверсия читает исходную цветную комнату, а не серый результат TonePass. Это проверено по пикселям: второй проход снова содержит цвет. В режиме Chained копирование включено, поэтому результат остаётся серым.

Диагностическая инверсия после обесцвечивания; не цветокоррекция готовой игры:

Два последовательных прохода: серое изображение, затем диагностическая инверсия

Копировать только нужную область

CopyMode=Rect использует Copy.Rect в локальных координатах BackBufferCopy. В проверенном случае Copy находится в начале координат, Rect=(0, 0, 1280, 1440), а второй ColorRect рисует только левую половину кадра. Внутри неё он видит результат TonePass; справа остаётся первый проход.

Не выбирайте texel вне реально скопированной области: там нет гарантии актуального результата. Если shader смещает координаты выборки, область копирования должна учитывать это смещение. Для начала используйте Viewport и сужайте область после получения правильного результата.

Диагностика

СимптомПроверка
эффект не виденcanvas_item, назначенный ShaderMaterial, размер и порядок ColorRect
части изображения повторяются или съезжаютSCREEN_UV вместо локальных UV, repeat_disable
второй эффект теряет первыйBackBufferCopy между проходами и CopyMode не Disabled
после добавления UI цепочка измениласьфактический порядок рисования, z_index и CanvasLayer
по краям эффекта старые пикселиRect слишком мал для области выборки
3D shader ведёт себя иначеэтот пример выполняет 2D-обработку уже показанной текстуры, а не spatial screen-reading

Проверено в текущем Forward+/Vulkan: живая сцена, нейтральный проход, обесцвечивание, SCREEN_UV на половине экрана, повторное использование копии, полный и прямоугольный BackBufferCopy. Глубина/нормали 3D, mipmap blur, Compatibility и производительность этой цепочки не проверены. Для spatial-эффектов нужен отдельный разбор 3D-постобработки.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.