UE材质的Custom本身会构建为函数,所以并不能在Custom定义函数,但当然还是有办法的
总结一些在custom写函数的方法
常规办法
常规办法就是使用结构体作为函数使用
以一个Lerp功能函数演示
让我们看看写法:
cpp
struct VolBlendFunc //定义结构体
{
//在结构体中新建"结构体变量",这里的变量名和 Custom 输入的变量无关
float A;
float B;
//新建一个"函数",这里的写法和函数基本一样
float Blend(float Pos)
{
return lerp(A, B, Pos);
}
};
VolBlendFunc VolSample; //为结构体"起名"
//使用:
VolSample.A = A; //将"参数A"设置到"结构体变量A"
VolSample.B = B;
return VolSample.Blend(x);//和使用函数的方式基本一样,这里的x是custom输入的x,设置到了Pos
根据用法还有很多写法,这是另一种写法
cpp
struct BaseNumFunc //定义一个结构体。
{
float a;
float2 b;
float3 c;
float4 d;
BaseNumFunc Num() //定义一个函数块。
{
BaseNumFunc l; //将结构体命名为l方便后续调用结构体中的变量;
l.a = 1;
l.b = float2(0.5,0.1);
l.c = float3(1,1,0);
l.d = float4(1,0,1,1);
return l;
}
}BaseNum; //返回结构体的名字。
a = BaseNum.Num().a;
b = BaseNum.Num().b;
d = BaseNum.Num().d;
return BaseNum.Num().c; //调用结构体中的函数里设置的数据。
泡芙注入
原理
这是一种利用Custom特性,用作弊手法将任何东西写入HLSL的实现。
先看看原理,例如你写了一个:
cpp
float C= lerp(A, B, X);
return C;
它会被编译为一个函数CustomExpression
但如果我们这么写呢?
cpp
return 0;}
float Blend(float Pos)
{
return lerp(A, B, Pos);
会发现他是原样写在了这里
但你会注意到在格式上,Custom生成的CustomExpression被我们直接结束了,下面的内容形成了新的函数
这种作弊方法正是利用了这个特性,把任何东西写入HLSL,包括函数写入
只需要先写上return 0;}
,后面随便写任何HLSL的东西,最后记得编译器会补一个"}
"
cpp
return 0;}//先手一个大比斗将其扇懵
float FA(float Pos)//写一个函数
{
return lerp(A, B, Pos);
}
float FB(float Pos) //又写一个函数
{
return lerp(A, B, Pos);
//最后一个"}"不写,等编译器自动补
使用
那么实际使用时就是这样
"加法"是为了在编译时会带着这个custom,这个custom输出0(大比兜的值)
一个+0的操作没有性能损耗,如果不连接这个Csutom,会作为无用节点被优化掉的
cpp
return 0;}//先手一个大比斗将其扇懵,然后对HLSL进行疯狂的注入
/**接下来你可以在HLSL里写任何东西,不限于函数
//例如你可以写:
#if !MATERIAL_LWC_ENABLED
#define UE_DF_FORCE_FP32_OPS 1
#endif
//也可以加include
#include "/Engine/Private/xxxx.ush"
**/
//用注释画画都行,把hlsl疯狂注入成泡芙
float MyFLerp(float X, float Y, float Pos)//写多少函数都行
{
return lerp(X, Y, Pos);
//总之切记,最后一个"}"不写,编译器需要补一个
Shader:
泡芙↓