1. 把ShaderGraph当"搭积木"之前,先理解三件事
很多兄弟拿到ShaderGraph的第一步,是照着官方案例或者B站教程把节点拖出来,连完了跑起来,效果是有的,但脑子里其实没有形成"这玩意儿是怎么想出来的"的底层逻辑。等到换个需求,比如把教程里的溶解改成边缘光,把UV扭曲改成极坐标扭曲,马上就卡住了。我自己在项目里带过好几个新人,几乎无一例外会在这一步栽跟头。
所以这篇"Unity官方ShaderGraphNode案例(一)",我打算换个讲法,不按节点面板顺序一个节点一个节点地过,而是先带你建立一套"数据流"的思维方式,再把官方节点库里那些出场率最高的节点逐个拆开,讲清楚每个节点到底在算什么、输出的是什么范围的数据、适合接在哪条线上。这一篇先把数学、UV、纹理、Fresnel这几大核心家族讲透,配上两个可以直接抄作业的实战案例。
在正式开始之前,有三件事必须刻在脑子里。
第一,ShaderGraph的本质是一张"数据流图",不是"操作步骤图"。 很多人习惯性地从左往右看节点图,觉得左边是输入、右边是输出,连线是从上到下执行的。不对。ShaderGraph最终会被编译成一段HLSL代码,节点和节点之间的连线,描述的是数据的依赖关系,而不是执行先后顺序。GPU在跑的时候,是并行地计算每个像素的,编译器会根据连线关系生成一份拓扑排序后的代码。所以你在面板里把节点摆得多乱都没关系,编译出来的代码顺序不会变。这一点决定了你排查问题的方式:你要追踪的是"数据从哪个节点来、经过了什么样的运算、最终到哪里去",而不是"哪个节点先执行"。
第二,节点按功能可以分成四大类,这个分类决定了你排查问题的思路。 第一类是数学类节点,Add、Multiply、Lerp、Smoothstep、Clamp这些,它们的本质是对数值做运算;第二类是输入类节点,UV、Position、Time、Vertex Color、Camera这些,它们从渲染管线里取数据进来;第三类是纹理采样类节点,Sample Texture 2D、Texel Size、Flipbook,它们负责从贴图里取数据;第四类是操作类节点,比如Transform、Split、Combine、Remap,它们负责数据的格式转换和范围映射。你去看官方那套节点库,翻来覆去其实就这么几类。一旦你建立了这个分类,看到一张复杂节点图的时候,就能快速判断出哪一块是"取数据"、哪一块是"算数据"、哪一块是"转格式"。
第三,ShaderGraph里所有节点输出的数值,回到GPU层面都是0到1之间或者-1到1之间的浮点数,但不同节点的输出范围完全不一样,这个范围决定了你下一步该接什么节点。 比如UV节点的输出是0到1,Fresnel节点的输出也是0到1,但Position节点的输出可能是-5到5甚至更大,噪声节点的输出是0到1,法线节点的输出是-1到1。很多效果做不出来,就是因为没搞明白当前这条线上数据的范围,把一个0到1的数据直接接到一个需要大数值的输入上,结果整个画面变成纯黑或者纯白。调试的时候,最常用的手段就是盯住中间某个节点的输出,在Preview窗口里看它的灰度图或者颜色图,判断当前数据大概在什么范围。
这三件事,是这一整个系列的基础。下面开始逐个拆节点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数学节点才是ShaderGraph的"编程语言":从Lerp到Smoothstep
说实话,ShaderGraph里最容易被人忽略、但恰恰最核心的,就是数学节点那一栏。很多人一上来就去找"看起来高级"的节点,比如Voronoi、Fresnel、Triplanar,结果效果做不出来,兜兜转转发现最后还是要回到Lerp和Smoothstep上来。数学节点就是ShaderGraph的编程语言,你写C#的时候不可能不用if、不用for,你在ShaderGraph里就不可能不用Add、Multiply、Lerp这些东西。
2.1 Lerp:ShaderGraph里最重要的一条公式
Lerp的全称是Linear Interpolation,线性插值。它的数学本质是a + (b - a) * t。a和b是两个输入值,t是插值因子,范围在0到1之间。当t等于0的时候,输出完全等于a;当t等于1的时候,输出完全等于b;t在0.5的时候,输出是a和b的中点。
就这么简单的一条公式,能玩出花来。我举一个最常见的例子:颜色混合。要做"根据视角距离切换颜色"的效果,比如武器靠近敌人时从银白色变成红色警告色,你可以把DistFromCamera这个值经过Smoothstep映射到0到1的范围,然后接Lerp的两个颜色输入,输出就是两种颜色随距离渐变。本质上,Lerp就是三路输入、一路输出的一个混音台,t是推子。
但这里有一个特别容易踩的坑,就是t的值域。Lerp本身不会帮你把t限制在0到1之间。如果t是1.5,那输出的结果就是a + (b - a) * 1.5,相当于超出了b,继续往b的方向"外插"了,得到的结果可能大于b,这在颜色上通常会导致过曝或者奇怪的颜色溢出。在位置偏移上可能导致模型外翻。所以你在接t输入之前,一定要确认这个数据是不是已经限制在0到1范围了,没有的话先接一个Saturate或者Clamp。项目里很多"颜色不对、莫名偏亮"的bug,最后查到都是这里出的问题。
2.2 Smoothstep:做"自然过渡"的首选工具
Smoothstep在ShaderGraph里的输入有Edge1、Edge2和In三个。它的作用是:当In小于等于Edge1的时候输出0,大于等于Edge2的时候输出1,在两者之间做一个三次平滑曲线过渡。和Lerp的线性过渡不同,Smoothstep在两端是缓入缓出的,不会有那种机械的"咔一下"的突变感。
我刚接触ShaderGraph的时候,一直分不清Smoothstep和Lerp到底该用哪个。后来总结出一个经验:Lerp适合做"量"的混合,Smoothstep适合做"区间的判断和过渡"。举个例子,做溶解效果的时候,你需要把噪声值和一个阈值对比,低于阈值就消失、高于阈值就保留。如果直接用Step节点,边缘会非常生硬,是硬切的锯齿感;如果换成Smoothstep,设定边缘宽度,就能得到一个渐渐溶解的过渡带。Smoothstep的输出天然就在0到1之间,可以直接接Lerp的t,也可以接Alpha。这一点在第六章的实战案例里会再用到。
另外提一句,ShaderGraph里Smoothstep对应的底层HLSL是smoothstep(min, max, x),内部实现是
