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);
}

VEX

Язык

Следующие шаги

Справочная информация