К содержанию
fohbookбета/ TouchDesigner

GLSL: свой шейдер

Одна формула на видеокарте вместо десятка узлов. Заготовка шейдера с TDOutputSwizzle, входы, встроенные uniform, свои параметры и что делать с ошибкой компиляции.

Ветка вашего пульта:
Быстрый выбор:

GLSL TOP выполняет ваш код на видеокарте для каждого пикселя. Одна формула дешевле десятка узлов с той же математикой, а ещё так делают то, чего в готовых операторах нет.

Заготовка

Код хранится в Text DAT, на который указывает Pixel Shader, и при создании узла такой DAT с заготовкой появляется рядом. Основной язык — GLSL 4.60; 3.30 и более ранние версии убрали с переходом на Vulkan, но написанное под 3.30 на новой версии обычно работает.

layout(location = 0) out vec4 fragColor;

void main()
{
    vec2 uv = vUV.st;              // координата пикселя 0..1
    float d = length(uv - 0.5);    // расстояние от центра
    float c = smoothstep(0.5, 0.0, d);
    fragColor = TDOutputSwizzle(vec4(c, c, c, 1.0));
}

vUV.st — координата пикселя, fragColor — выход, который вы объявили сами. Каждый цвет Derivative велит пропускать через TDOutputSwizzle(): он раскладывает каналы под формат текстуры, и шейдер одинаково работает на Windows и macOS.

Входы приходят массивами по типу текстуры, 2D — как sTD2DInputs[0], sTD2DInputs[1]:

vec4 src = texture(sTD2DInputs[0], vUV.st);
vec4 mask = texture(sTD2DInputs[1], vUV.st);
fragColor = TDOutputSwizzle(src * mask.r);

Номер считается среди входов того же типа: если вторым проводом подключён 3D-TOP, следующий 2D-вход всё равно sTD2DInputs[1].

Что уже объявлено

Переменная Что это
uTDOutputInfo Разрешение выхода: uTDOutputInfo.res
uTD2DInfos[i] Разрешение каждого 2D-входа
uTDPass Номер прохода, когда на Common задано несколько Passes
sTDNoiseMap Текстура 256 × 256 со случайными значениями
TD_NUM_2D_INPUTS Сколько 2D-входов подключено

Своё разрешение руками передавать не надо. А вот времени среди встроенных нет: заводят uniform uTime с выражением absTime.seconds.

Свои параметры

На страницах Vectors, Colors, Arrays, Matrices и Constants объявляют то, что приходит из TouchDesigner, — имя и значение, в том числе выражением или экспортом из CHOP. Цвета со страницы Colors переводятся в рабочее цветовое пространство проекта. В коде uniform объявляют с тем же именем и типом:

uniform float uSpeed;
uniform vec3  uColor;
layout(location = 0) out vec4 fragColor;

void main() {
    float t = uSpeed * 0.1;
    fragColor = TDOutputSwizzle(vec4(uColor * sin(t + vUV.s * 20.0), 1.0));
}

Load Uniform Names заполняет параметры именами из кода; неиспользуемые uniform компилятор обычно выбрасывает, и их кнопка не найдёт.

Compute и соседи

Mode = Compute Shader превращает GLSL TOP в вычислительный шейдер: vUV там нет, координаты берут из gl_GlobalInvocationID, а пишут функцией TDImageStoreOutput() — так с ветки 2025.30000, прежнее sTDComputeOutputs заменено. GLSL MAT пишет материал для рендера, а у POP из той же ветки свои GLSL-операторы, и ради геометрии вычислительные шейдеры теперь пишут куда реже.

Когда стоит

Шейдер окупается, когда одна формула заменяет шесть-десять полноэкранных узлов, когда нужного алгоритма нет в операторах — SDF, raymarching, свои проекции — и когда за один проход надо прочитать несколько текстур. Не окупается, если то же делают три стандартных узла, если писать будет один человек, а поддерживать другой, и если хочется «правильности»: сеть из операторов читается и правится быстрее.

Ошибка компиляции

Error Behavior решает, что показать при ошибке: шахматку, чёрное или предыдущий удачный шейдер — на шоу последнее. Пока шейдер компилируется, кадр по умолчанию ждёт, а Compile Behavior разрешает компилировать в фоне, показывая чёрное, шахматку или прежний шейдер. Текст ошибки — в DAT с информацией рядом с узлом и в Textport, причём номер строки может не совпасть с вашим: TouchDesigner добавляет к коду свои объявления.

Shadertoy

Шейдеры оттуда переносятся почти дословно: iTime — свой uniform от absTime.seconds, fragCoord / iResolution.xy — vUV.st, mainImage становится main, результат уходит через TDOutputSwizzle() в fragColor. Быстрее способа научиться нет.

Нашли в статье ошибку, устаревшее или непонятное место?

рядом по смыслу