# 結論
* Customノードは関数、頑張れば別のCustomノードで呼び出して使える
* MaterialFunctionは展開される。Customノードからの呼び出しはできない
# 実験
1. Customノードを関数として呼び出してみる
以下の条件を満たすときこれが可能。
* 呼び出されるCustom関数が実際に使われている(使われていないとコードから除外される)
* 呼び出されるCustom関数が呼び出し部分より手前で定義されている
こんなのを作った。
sin_custom の中身
sin(x)
test_customの中身
CustomExpression0(Parameters, x)
sin_customには0を入力しているので出力も0.
それをAddに使っているので実際には何の効力もないが、
無理やりにでも使っておかないとコードが生成されないのでこんな感じにした。
test_customの中身が今回のミソで、
Customノードがシェーダーコードに変換されるとき、
* CustomExpressionX(Xには0から順に整数が割り当てられる)という名前の関数になる
* Parametersという名前の引数が最初に付加される
ということを反映している。
実際のコードはWindow->HLSL Code で見ることができ、
今回のsin_customについては以下のようなコードに変換されていた。
MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters,MaterialFloat x)
{
return sin(x);
}
関数名につく数字はシェーダーコードが生成されるたびに割り当てなおされるので、
マテリアルをいじると変わる場合がある。
したがってこの呼び出し方はよほどの事情がない限り行わない方がよい。
なお、WorldPositionOffsetなど頂点シェーダーとして解釈される部分についてはParametersの型が異なってくるため、ピクセルシェーダー側との互換性が無い。
2. MaterialFunctionノードによるシェーダーコードの検証
こんなのを作った。
コードを見つけやすいように0.12345という変な値を入れておいた。
出てきたシェーダーコードがこれ。
half3 GetMaterialEmissiveRaw(FMaterialPixelParameters Parameters)
{
MaterialFloat Local0 = (MaterialFloat2(0.00000000,0.00000000).r * MaterialFloat2(0.12345000,0.00000000).r);
MaterialFloat Local1 = (MaterialFloat2(0.00000000,0.00000000).g * MaterialFloat2(0.12345000,0.00000000).g);
MaterialFloat Local2 = (Local0 - Local1);
MaterialFloat Local3 = (MaterialFloat2(0.00000000,0.00000000).r * MaterialFloat2(0.12345000,0.00000000).g);
MaterialFloat Local4 = (MaterialFloat2(0.00000000,0.00000000).g * MaterialFloat2(0.12345000,0.00000000).r);
MaterialFloat Local5 = (Local3 + Local4);
MaterialFloat3 Local6 = (MaterialFloat3(MaterialFloat2(Local2,Local5),0) + Material.VectorExpressions[0].rgb);
return Local6;;
}
どう見ても展開されている。
MF_MultComplex はVector2を複素数と見なして乗算した結果を返すもので、
一応載せておくと下のようなもの。
実装内容によって展開されないこともあるのかもしれないが、
試した限りではこういう結果になった。