【UE5】在材质Custom写函数的方法

UE材质的Custom本身会构建为函数,所以并不能在Custom定义函数,但当然还是有办法的
总结一些在custom写函数的方法

常规办法

常规办法就是使用结构体作为函数使用

以一个Lerp功能函数演示
在这里插入图片描述

让我们看看写法:

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

根据用法还有很多写法,这是另一种写法
在这里插入图片描述

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的实现。
先看看原理,例如你写了一个:
在这里插入图片描述

float C= lerp(A, B, X);
return C;

它会被编译为一个函数CustomExpression+Index
在这里插入图片描述

正常来说,后续你可以通过CustomExpression0来调用这个函数,但在编译时是无法控制编译器会将哪个Custom编译到什么index,导致风险相当大

但如果我们这么写呢?
在这里插入图片描述

return 0;}
float Blend(float Pos)
{
    return lerp(A, B, Pos);

会发现他是原样写在了这里
在这里插入图片描述

但你会注意到,Custom自动生成的CustomExpression0看上去被我们直接 结束 了,而下面的内容刚好构成了 新的函数
在这里插入图片描述
这种作弊方法正是利用了这个 特性 ,把 任何 东西写入HLSL,包括函数写入

只需要先写上return 0;},后面随便写任何HLSL的东西
最后,记得编译器在生成CustomExpression时会补一个"}“,因此最后一个”}"不写

return 0;}//先手一个大比斗将其扇懵

float FA(float Pos)//写了一个函数
{
    return lerp(A, B, Pos);
}

float FB(float Pos) //又写一个函数
{
    return lerp(A, B, Pos);

//最后一个“}”不写,等编译器自动补

使用

连法1:“+0法”

那么实际使用时就是这样
“加法”是为了在编译时会带着这个custom,这个custom输出0(大比兜的值)
一个+0的操作没有性能损耗,如果不连接这个Custom,会作为无用节点被优化掉的
在这里插入图片描述

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

//总之切记,最后一个“}”不写,编译器需要补一个

连法2:“引脚法”

还有一种方式,在使用函数的CustomB,开放一个没用的函数输入(引脚名无所谓),将泡芙CustomA连上,也是可以防止CustomA被优化掉:
在这里插入图片描述

相比+0的方法,优点是减少了一次+0。缺点是让Custom节点之间,有了某种实际上不存在因果关系
取决于你的喜好了。


如果注入的并不是函数

如果你注入的内容不包括函数,需要对结尾进行设计,因为Custom必补一个"}"

我喜欢用" void(){ "收尾

例如想在这画个画,Custom效果如下::
在这里插入图片描述

编译结果:
在这里插入图片描述


其他玩法

切换函数

因为Switch是静态切换(在实际编译前),所以能做到这样的事。
在这里插入图片描述


啊,为啥叫泡芙注入啊?

Shader:
在这里插入图片描述

这是泡芙↓
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值