你可曾思索过,一个简简单单的,叫作‘取反’的操作,怎样在游戏画面里营造出流动着的光芒,以及颠倒过来的世界,或者是精准无误的撞击特效呢?在Unity URP渲染管线当中,Negate节点就是这样东西,它看似颇为平凡,实则具备强大功能,是个十足的数学工具。
Negate节点,是Shader Graph里极为基础的数学运算节点当中的一个。它核心功能在于,对输入数值开展符号翻转操作,让正数转变为负数,有着负数的数转变为正数。在Unity 2022 LTS以及更高版本的URP项目里,你能够在Math菜单之下的Derivatives类别之中找到它。
该节点的界面设计简洁至极,只含有一个“In”输入端口,以及一个“Out”输出端口。这样的极简设计使得初学者能够在5分钟内上手使用。不管你输入的是单个浮点数,或者是二维向量,又或者是四维颜色值,节点都会针对每个分量单独执行符号翻转操作。
有这样一种节点,它被称作Negate节点,此节点支持着多种数据类型,这些数据类型涵盖了float,还有float2,再者float3,另外float4,以及vector类型。这所表达的意思是,你具备直接针对UV坐标,或者法线方向,又或者颜色值,甚至世界位置去开展取反操作的能力。
当把输入设定成维度为三的向量,其具体元素是(1, 0, 0)时,相应节点所给出的输出结果是(-1, 0, 0),在这样的情况下,就会使得方向发生翻转改变。对于给定的颜色值,具体是(0.2, 0.5, 0.8),此时输出的结果就变成了(-0.2, -0.5, -0.8)。这样一种按照每一个分量来进行处理的机制,切实保证了向量的方向能够被完整地实现反转,而并非仅仅是在数值符号方面出现改变。
在光照的计算这个事儿里头,Negate节点呢,常常被用来对法线的方向进行调整。要是有制作双面渲染的那种植物叶片的需求出现了,你能够借由把背面的法线给翻转过来,以此达成让光线从另外一侧去照射的目的,进而实现更为自然的半透明效果。
于纹理动画范畴内,Negate节点同Time节点相协同进而能够变换UV的滚动方向,举例而言,在制作河流流动效果时间,把Time输出连至Negate节点,接着再连至UV的X分量,如此便能够使水流方向由向右转变为向左,此类技巧在2023年的《原神》须弥地图的水体渲染当中存在典型应用。
对于现代GPU而言,符号翻转操作的执行效率是极高的。依据NVIDIA以及AMD的官方文档来看,单个negate指令仅仅占用1个时钟周期。在RTX 3060级别显卡的情况下,每秒能够执行超过100亿次这样的操作。
Unity会把Negate节点编译成对应的HLSL代码,对于float4类型输入,所生成的函数是void Unity_Negate_float4(float4 In, out float4 Out) { Out = -1 * In; },对于标量、二维和三维向量,Unity会分别生成对应的函数变体,以此确保类型安全。
HLSL
void Unity_Negate_float4(float4 In, out float4 Out)
{
Out = -1 * In;
}
Negate节点呢,常常会跟Multiply节点一块儿协同开展工作,把Negate的输出连接到Multiply的B输入那儿,再搭配上一个处于0到1范围之间的控制值即可,如此便能达成渐变式的方向反转效果,而这在制作角色受击时的那个闪白特效里是极为实用的哟。
HLSL
void Unity_Negate_float(float In, out float Out)
{
Out = -1 * In;
}
当跟Branch节点相组合之际,Negate能够依据某一条件的真假状况来判定是不是翻转数值,举例来说,在着手制作昼夜进行切换的天空盒之时,你能够凭借时间值去判断当下所处时段,进而动态地反转太阳光的方向向量,以此达成日出日落的完整循环过程。
HLSL
void Unity_Negate_float2(float2 In, out float2 Out)
{
Out = -1 * In;
}
HLSL
void Unity_Negate_float3(float3 In, out float3 Out)
{
Out = -1 * In;
}
在一个完整的URP着色器里头,Negate函数相应的调用方式是这般的:先是去定义原始值float4 originalColor = float4(0.3, 0.6, 0.9, 1.0); ,紧接着声明输出变量float4 invertedColor; ,最终调用Unity_Negate_float4(originalColor, invertedColor);。执行完毕之后,invertedColor这个值呈现为,负零点三,负零点六,负零点九,负一点零。
HLSL
// 在片元着色器或顶点着色器中调用Negate函数
float4 originalValue = float4(1.0, -2.0, 3.0, -4.0);
float4 negatedValue;
// 调用生成的Negate函数
Unity_Negate_float4(originalValue, negatedValue);
// 此时negatedValue的值为(-1.0, 2.0, -3.0, 4.0)
这个操作和任何纹理采样没有关联,也不涉及复杂数学计算,所以即便在高画质游戏里,每帧要处理数百万个片元,其性能损耗几乎能够忽略不计。这同样是许多AAA游戏在进行特效优化时,会优先考虑运用Negate节点,而非采用更复杂算法的原因。
你可晓得哪些看上去貌似简易实际上却能够缔造出惊人炫目的成效的Shader节点?欢迎于评论场区去分享你运用所获得的心得体会,点赞数量超过100的话我就会接着去更新数学运算节点系列教程!
![【节点】[Negate节点]原理解析与实际应用 【节点】[Negate节点]原理解析与实际应用](https://cdn.pixabay.com/photo/2017/03/07/20/53/cog-wheels-2125183_1280.jpg)