On this page |
Начиная с Houdini 12.5, функции шейдера VEX могут вызывать другие функции шейдера. Этот метод позволяет оптимизировать компилятор VEX и производительность оптимизатора для больших шейдеров, посколько код, который вызывается несколько раз в шейдере или других шейдерах, может быть создан один раз и использоваться многократно без дополнительных временных затрат.
Ключевое слово import
Ключевое слово import
импортирует другую функцию шейдера по имени в текущий шейдер. Импортированный шейдер должен быть доступен в пути houdini для успешной компиляции - если он не найден, компиляция шейдера завершится неудачно. Поэтому при создании шейдеров, которые вызывают другие шейдеры, вам нужно будет создать шейдеры в порядке зависимости - вызываемые шейдеры, а затем их вызывающие. Циклические вызовы возможны, но вам нужно будет добавить ключевое слово import вызывающему шейдеру после создания первого вызывающего шейдера.
Например, импорт шейдера пластика:
import plastic;
Шейдеры могут называть себя рекурсивно - в этом случае ключевое слово import не требуется.
Вызов шейдера
Шейдеры вызываются по имени с передачей именованных аргументов - пар строка/значение, которые идентифицируют аргументы, которые должны быть переданы или получены из вызванного шейдера. Можно задать только некоторые параметры, в этом случае вызываемый шейдер будет использовать значения по умолчанию для тех параметров, которые не были заданы. Кроме того, необходимо задать только подмножество экспорта из вызываемого шейдера. В данном случае оптимизатор VEX уберет любой мертвый код, который вычисляет экспорт, но не требуется, что приведет к повышению производительности.
Например, этот код вызывет пластиковый шейдер, запрашивающий экспорт Cf
и передающий вход diff
:
import plastic; surface caller(vector diff = {1,0.5,0}) { plastic("diff", diff, "Cf", Cf); }
VCC проверит все переменные аргументы, переданные вызываемому шейдеру, чтобы убедиться, что они соответствуют аргументу или экспорту, которые существуют в списке параметров вызываемого шейдера - если тип или режим доступа не совпадают, будет сообщено об ошибке.
Контекст вызываемого шейдера
В настоящее время шейдеры могут вызывать только шейдеры, имеющие соответствующий тип контекста. Для контекстов с глобальными переменными, любые глобальные переменные, которые явно не переданы шейдеру как именованные аргументы, копируются без изменений из вызывающего шейдера в вызываемый шейдер. Для контекстов, несущих дополнительную непрозрачную информацию о состоянии (таких как surface
контекст, который поддерживает состояние о поверхностных попаданиях (hit surface)), эта информация также сохраняется в вызванном шейдере, так что вызывающие методы, такие как getraylevel()
, будут давать один и тот же результат в вызывающем и вызываемом шейдерах.
Примеры
Вызываемый шейдер:
cvex callee(export int mval = 0; int rval = 0; export int wval = 0; float castval = 0) { mval *= 2; wval = rval; }
Вызывающий шейдер:
import callee; cvex caller() { int mval = 1; int rval = 2; int wval = 1; callee("mval", mval, "rval", rval, "wval", wval, "castval", 1); printf("%d %d %d\n", mval, rval, wval); }
Рекурсивный шейдер:
cvex fib(int i = 0; export int rval = 0) { if (i >= 2) { int v1, v2; fib("i", i-1, "rval", v1); fib("i", i-2, "rval", v2); rval = v1 + v2; } else rval = i; printf("%d: %d\n", i, rval); }