HLSL生成逻辑
在新建一个Custom节点并转义为HLSL后,代码是这样的:
MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters) { return 1; }
这样我们大体知道UE会默认生成一个函数体,并将我们节点内的代码放到这个函数体内。因此我们可以根据这个流程来做一些特殊处理来编写更多函数。
在名字为Global的节点内编写
return 1; } float Get() { return 3;
这样把节点内的代码生成到上面的函数体内,HLSL就会生成为:
MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters) { return 1; } float Get() { return 3; }
我们就成功的多编写了一个函数。
但是其他节点无法直接使用这个名为Global节点内的Get函数,如果一个节点没有被连接则是无法编译的,所以想使用这个Get函数的其他Custom只要输入来自这个节点即可。如还有其他输入端可以通过直接相乘来解决,如图所示:
并且Global节点返回值为1不会影响乘法结果,仅仅是把函数体生成了过去,Using节点就可以使用Get函数了。
另外需要注意一点是CustomNode的输入端口如果没有名字的话是不会被使用的,所以这里给Using节点的输入起名为A。
表达式与函数体的两种处理方式
这里是UE将custom节点编译为HLSL时部分的代码
FStringView FunctionCode; if (Code.Contains(TEXT("return"))) { FunctionCode = Code; } else { TStringBuilder<8 * 1024> FormattedCode; FormattedCode.Appendf(TEXT("return %s;"), *Code); ... }
可以看到,UE非常粗暴的判断了代码内是否含有return字符串,也就是说,你不可以在HLSL出现return的字样,这包括如变量is_return,注释//return等。如果代码内出现return的字样,那就会判定该节点将以函数体方式转义。如果代码内没有return字样,那么就会以表达式方式转义。
也就是说,如果输入表达式:3, 那么会生成return 3
如果输入返回值 reutnr 1,那么会生成return 1
但如果输入了表达式returned(3); 因为判定returned字符内含有return,所以会生成returned(3); 结果无返回值错误
返回欺骗
如果在节点属性上写Include,那么这个Include的文件只会生成到函数体前面,如果需要include的这个文件内只是一段代码实现,比如:return 0.5; (AAAImpl.usf),那么我们就可以用上面的return逻辑来欺骗
include "/Engine/AAAImpl.usf" //return
只要有return字样就可以让UE把这段代码视为函数体,从而不去生成return语句。