VisualShader: граф, цвет и прозрачность
Рабочий граф C#, параметры материалов, Alpha, сохранение и диагностика.
VisualShader хранит типизированный граф и генерирует из него код языка шейдеров движка. Это ресурс Shader для ShaderMaterial, а не иерархия Entity и не автоматическая оптимизация производительности. Элементы графа в SDK остаются объектами VisualShaderNode.
Создайте первый материал
- Создайте ShaderMaterial у объекта, который должен показывать эффект.
- Назначьте новый ресурс VisualShader в его свойство Shader.
- Выберите режим по цели: CanvasItem для ColorRect/Sprite2D в 2D, Spatial для поверхности 3D. Затем выберите редактируемый этап, например Fragment.
- Откройте граф и добавьте ColorParameter с именем tint. Включите DefaultValueEnabled и задайте непрозрачный красный DefaultValue.
- Подключите RGB к входу Color выхода Fragment. Отдельно извлеките четвёртую компоненту и подключите к Alpha.
- Назначьте материал видимому объекту и проверьте реальный рендеринг, не только предпросмотр графа.
В текущем исходнике редактора кнопка добавления называется Add Entity.... В этой панели она создаёт узлы графа шейдера, не Entity дерева проекта. Просмотр сгенерированного кода и материала — разные элементы управления; не ищите их по старому порядковому номеру в панели.
У проверенного CanvasItem Fragment вход Color имеет номер 0, Alpha — 1. Раскладка портов зависит от режима, этапа и настроек узла; эти номера не универсальны для всех выходов.
Полное создание из C#
Сохраните помощник как VisualColorGraph.cs:
using System;
using Reckfell;
public static class VisualColorGraph
{
public static VisualShader Create()
{
var shader = new VisualShader();
shader.SetMode(Shader.Mode.CanvasItem);
var stage = VisualShader.Type.Fragment;
var color = new VisualShaderNodeColorParameter
{
ParameterName = "tint",
DefaultValueEnabled = true,
DefaultValue = Colors.Red,
};
int colorId = shader.GetValidNodeId(stage);
shader.AddNode(stage, color, new Vector2(0, 0), colorId);
var split = new VisualShaderNodeVectorDecompose
{
OpType = VisualShaderNodeVectorBase.OpTypeEnum.Vector4D,
};
int splitId = shader.GetValidNodeId(stage);
shader.AddNode(stage, split, new Vector2(250, 120), splitId);
Connect(shader, colorId, 0, 0, 0);
Connect(shader, colorId, 0, splitId, 0);
Connect(shader, splitId, 3, 0, 1);
return shader;
}
private static void Connect(VisualShader shader, int from, int fromPort, int to, int toPort)
{
var stage = VisualShader.Type.Fragment;
if (!shader.CanConnectNodes(stage, from, fromPort, to, toPort))
throw new InvalidOperationException("Incompatible graph connection.");
if (shader.ConnectNodes(stage, from, fromPort, to, toPort) != Error.Ok)
throw new InvalidOperationException("Graph connection failed.");
}
}Создайте ShaderMaterial с Shader = VisualColorGraph.Create() и назначьте белому ColorRect. Проверка использует карточки 64×64. По умолчанию карточка красная. Вызов material.SetShaderParameter("tint", new Color(0, 1, 0, 1)) делает этот материал зелёным. Два отдельных материала могут использовать один VisualShader с независимыми значениями tint.
Граф удерживает ссылки на свои узлы. Не помещайте живые узлы в using и не освобождайте заимствованную оболочку узла, пока граф её использует, особенно при поведении пользовательского узла C#. Собственный граф/материал освобождайте после прекращения использования потребителями.
Следите за типами, включая Alpha
У ColorParameter в этом SDK один выход vec4/RGBA. Пример подключает его к Color типа vec3, а также к VectorDecompose в режиме Vector4D. Выход 3 Decompose — W/Alpha — подключается к скалярному входу Alpha.
Подключение RGBA только к Color отбрасывает четвёртую компоненту в этой связи. Прямое подключение всего вектора к scalar не извлекает альфа и не усредняет компоненты: текущее числовое преобразование берёт X. Проверка GPU задаёт красный с alpha=0: явный путь W скрывает карточку, путь vector→scalar X делает её непрозрачно красной.
Читайте типы/размерности портов, а не только цвет проводов. Scalar, целочисленный scalar, vec2/3/4, boolean, transform и sampler задают разные контракты. Числовое преобразование может быть разрешено, но менять смысл. Для нужного алгоритма явно используйте разложение, сборку, dot или другую подходящую операцию. Раскрытие портов и смена режима узла могут менять раскладку.
ID узла принадлежит графу одного этапа; GetValidNodeId выбирает свободный ID именно там. ID 0 — встроенный Output. До ConnectNodes используйте CanConnectNodes и проверяйте Error. Проверка отбрасывает отсутствующие узлы, неверные порты, дублирование/самосвязи, несовместимые/циклические связи; она не доказывает корректность любого выражения и скорость эффекта.
Параметры, значения по умолчанию и общие ресурсы
ColorConstant меняет сгенерированный код. ColorParameter создаёт uniform шейдера, который обновляется у каждого ShaderMaterial. Значение по умолчанию в графе отличается от значения, заданного материалом. Изменение первого действует на материалы без собственного значения; передача Nil в SetShaderParameter возвращает значение из графа.
ParameterName — имя uniform, не ID или подпись узла. Сохраняйте уникальность имён и проверяйте фактическое имя после редактирования/добавления. После переименования обновите вызовы SetShaderParameter и сохранённые материалы. Выбор этапа графа отличается от режима шейдера, а оба — от квалификатора material/global/instance параметра.
Global/instance требуют своего реестра или настройки экземпляра; это не автоматические параметры обычного материала. См. области uniform. После смены режима шейдера не считайте старые связи автоматически подходящими.
Организуйте большой граф осмысленно
| Элемент | Назначение и граница |
|---|---|
| Group, GroupInput, GroupOutput | Переиспользуемый ресурс подграфа с объявленными входами/выходами. Согласуйте типы интерфейса; это больше, чем визуальная рамка. |
| Frame | Визуальная организация узлов, а не обещание отдельной функции шейдера или ускорения. |
| Expression / GlobalExpression | Код в соответствующем контексте портов/глобальных объявлений. Нужны допустимый синтаксис языка шейдеров и правила этапа. |
| Reroute | Организация проводов/распространение типа, не математическое преобразование любого ресурса. |
| Boolean, If, Switch | Логические значения и выбор. Согласуйте типы; визуальная ветка сама по себе не гарантирует меньше инструкций GPU. |
| Fresnel | Вес края по направлению взгляда/нормали в подходящем контексте, не полная система отражений или физического материала. |
| Particle MeshEmitter | Данные испускания из геометрии в подходящем графе/этапе частиц; не фабрика игровых Entity и не обычный fragment-эффект. |
Сначала соберите и проверьте небольшой путь до Output, затем добавляйте группы/выражения. Неподключённые вычисления не обязательно входят в сгенерированный код. Для пользовательских узлов C# используйте отдельное руководство: там разобраны методы обратного вызова, значения по умолчанию и время жизни.
Сохраняйте граф и осознанно переводите в текст
Сохраняйте VisualShader как ресурс графа, например ResourceSaver.Save(graph, "asset://ColorGraph.rdata"). Проверка загружает независимый VisualShader через CacheMode.Ignore, сверяет ID/связи и отрисовывает сохранённое значение по умолчанию. Загрузка текстового кода не восстанавливает топологию графа.
GetCode возвращает сгенерированный текст для изучения или намеренного создания текстового шейдера. Для простого графа new Shader { Code = graph.GetCode() } даёт тот же результат, сохраняя исходный граф. Текстовый Shader от этого не получает редактирование прежних узлов.
Общее преобразование не является безусловно полным: текущий конвертер редактора отклоняет встроенные подресурсы и предупреждает, что внешние ссылки могут потребовать перепривязки на материале. Сохраняйте исходный граф и проверяйте зависимости, не предполагая конвертацию любого графа одним нажатием.
Если граф рисует неправильно
| Симптом | Что проверить |
|---|---|
| Граф меняется, объект нет | Нужный экземпляр материала/графа, режим/этап, путь к Output и видимость объекта. |
| Цвет работает, прозрачность нет | Вход Alpha и явное извлечение W; vec4→scalar здесь берёт X. |
| Два объекта меняются вместе | Проверьте, не назначен ли обоим объектам один ShaderMaterial вместо двух материалов с общим Shader. |
| Параметр не действует | Точное ParameterName, квалификатор и участие выхода в активном пути. |
| Правка значения по умолчанию не видна | Проверьте, не задано ли собственное значение у материала или экземпляра. |
| Ошибка после изменения порта/типа | Сгенерированный код и совместимость затронутых связей. |
| После загрузки потерян нужный граф | Сохраняйте ресурс VisualShader, не только текст; сохраняйте внешние ресурсы и зависимости пользовательских узлов. |
В установленном Windows Forward+/Vulkan проверены пиксели цвета/альфа, независимые материалы, изменение значений по умолчанию, сохранение графа, простое преобразование в текст и редактирование связей. Управление редактором и роли специальных узлов выше сверены по исходникам; новые UI-снимки, произвольные group/expression/mesh-emitter эффекты, все преобразования, другие рендереры/экспорты и скорость здесь не проверялись.