目录
一、节点功能概述
汇聚 2D 纹理节点(Gather Texture 2D Node)是 Unity Shader Graph 中用于采样纹理相邻像素的专业工具。它通过指定采样点,提取周围 4 个相邻像素的红色通道(R 通道),并以RRRR
的形式返回(每个通道对应一个相邻像素的 R 值)。与常规纹理采样(读取 RGBA 四通道)不同,该节点专注于相邻像素的单通道信息,适用于自定义双线性插值、模糊效果、边缘检测等需要精细控制像素间过渡的场景。其核心优势在于:
- 精细像素采样:一次性获取 4 个相邻像素的 R 通道值,为像素级操作提供基础数据
- 自定义插值支持:突破常规双线性插值限制,实现个性化的像素混合逻辑
- 全管线兼容:支持内置渲染管线、URP 和 HDRP,确保跨项目一致性
二、节点结构详解
2.1 输入端口
端口名称 | 类型 | 绑定 | 描述 |
---|---|---|---|
Texture | Texture 2D | 无 | 待采样的目标纹理 |
UV | Vector 2 | UV | 采样点的 UV 坐标 |
Sampler | SamplerState | 无 | 采样状态(过滤模式、寻址模式等) |
Offset | Vector 2 | 无 | 像素级偏移量(单位为像素,非 UV 空间),用于调整采样点位置 |
2.2 输出端口
端口名称 | 类型 | 描述 |
---|---|---|
RGBA | Vector 4 | 4 个相邻像素的 R 通道值,格式为(R1, R2, R3, R4) ,对应 4 个邻居的 R 值 |
R | Float | 第一个相邻像素的 R 通道值(采样点左下邻居) |
G | Float | 第二个相邻像素的 R 通道值(采样点左上邻居) |
B | Float | 第三个相邻像素的 R 通道值(采样点右上邻居) |
A | Float | 第四个相邻像素的 R 通道值(采样点右下邻居) |
三、技术原理解析
3.1 采样逻辑基础
汇聚 2D 纹理节点的核心功能是对纹理中顶层 MIP 层级(最高分辨率)的 2×2 像素块进行采样,提取每个像素的红色通道(R),并按固定顺序返回。其采样范围与常规纹理采样的双线性插值区域一致,但不进行插值计算,而是直接返回原始像素值。
- 采样顺序:按逆时针方向返回 4 个相邻像素,起始于采样点的左下方向,顺序为:
- 左下邻居(R 输出)
- 左上邻居(G 输出)
- 右上邻居(B 输出)
- 右下邻居(A 输出)
3.2 HLSL 实现与平台适配
- 核心函数:节点基于 HLSL 的
Gather
内在函数实现,该函数专门用于提取 2×2 像素块的单通道值。 - 平台兼容性:
- 在不支持
Gather
函数的平台上,Shader Graph 会自动使用近似算法模拟效果。 - Metal 图形 API:采样 / 汇聚操作的偏移量(Offset)需为整数(int2),且范围限制在
[-8, 7]
,超出范围会被自动截断。
- 在不支持
3.3 与常规采样的差异
特性 | 汇聚 2D 纹理节点(Gather Texture 2D) | 常规 2D 纹理采样节点(Sample Texture 2D) |
---|---|---|
采样内容 | 4 个相邻像素的 R 通道(返回 RRRR) | 单像素的 RGBA 四通道 |
插值处理 | 不插值,返回原始像素值 | 双线性 / 三线性插值(取决于采样状态) |
MIP 层级使用 | 仅使用顶层 MIP(最高分辨率) | 可根据距离自动选择 MIP 层级 |
四、应用场景与实战案例
4.1 自定义模糊效果
场景:通过平均相邻像素实现简单模糊
- 需求:不依赖内置模糊函数,通过汇聚节点手动实现模糊效果
- 实现步骤:
hlsl
// 汇聚4个相邻像素的R通道值 float4 gathered = GatherTexture2DNode.RGBA; // (R1, R2, R3, R4) // 计算平均值(模糊效果) float blurredR = (gathered.r + gathered.g + gathered.b + gathered.a) / 4.0; // 扩展到RGB通道(假设纹理为灰度图或RGB通道值相同) float3 blurredColor = float3(blurredR, blurredR, blurredR);
4.2 边缘检测效果
场景:通过相邻像素差异识别边缘
- 步骤:
hlsl
// 汇聚相邻像素 float4 neighbors = GatherTexture2DNode.RGBA; // 计算像素差异(边缘处差异较大) float maxDiff = max( abs(neighbors.r - neighbors.g), abs(neighbors.b - neighbors.a) ); // 边缘阈值判断 float edge = maxDiff > _EdgeThreshold ? 1.0 : 0.0; // 应用边缘颜色 float3 finalColor = lerp(baseColor, _EdgeColor, edge);
4.3 自定义双线性插值
场景:替换默认插值逻辑,实现风格化过渡
- 实现:
hlsl
// 获取4个相邻像素R值 float r1 = GatherTexture2DNode.R; // 左下 float r2 = GatherTexture2DNode.G; // 左上 float r3 = GatherTexture2DNode.B; // 右上 float r4 = GatherTexture2DNode.A; // 右下 // 自定义插值权重(基于UV小数部分) float2 uvFrac = frac(uv * _TextureSize); // UV的小数部分(0~1) float w1 = (1 - uvFrac.x) * (1 - uvFrac.y); // 左下权重 float w2 = (1 - uvFrac.x) * uvFrac.y; // 左上权重 float w3 = uvFrac.x * uvFrac.y; // 右上权重 float w4 = uvFrac.x * (1 - uvFrac.y); // 右下权重 // 自定义插值结果 float customLerpR = r1*w1 + r2*w2 + r3*w3 + r4*w4;
4.4 动态模糊 / 清晰切换
场景:通过 Lerp 节点混合原始纹理与模糊纹理
- 核心逻辑:
hlsl
// 原始纹理采样 float3 originalColor = SampleTexture2DNode.Out; // 汇聚节点生成的模糊纹理 float3 blurredColor = float3(blurredR, blurredR, blurredR); // 动态切换(T=0为原始,T=1为模糊) float3 finalColor = lerp(originalColor, blurredColor, _BlurAmount);
五、使用技巧与注意事项
5.1 偏移量(Offset)的合理使用
- 作用:调整采样点的位置,用于偏移采样区域(如模拟运动模糊的拖影效果)。
- 示例:
Offset = float2(1, 0)
表示向右偏移 1 个像素采样。 - 限制:Metal 平台需使用整数偏移,且范围为
[-8, 7]
,其他平台可使用小数但实际效果为整数偏移。
5.2 与其他节点的配合策略
-
与 UV 节点配合:通过 UV 缩放 / 偏移控制汇聚区域,例如:
hlsl
float2 scaledUV = uv * _Scale + _UVOffset; // 缩放UV扩大采样范围 float4 gathered = GatherTexture2DNode.Out; // 使用缩放后的UV采样
-
与 Lerp 节点配合:动态混合原始纹理与汇聚处理后的效果(如模糊 / 清晰切换),参考 4.4 案例。
5.3 性能优化建议
- 减少采样次数:单次汇聚节点即可获取 4 个像素信息,避免多次调用常规采样节点。
- 限制采样范围:避免在大纹理或高频调用中使用,汇聚操作的计算成本高于常规采样。
- 配合 MIP 裁剪:若纹理存在多层 MIP,可手动限制为顶层 MIP(通过采样状态设置),减少层级判断开销。
六、总结与拓展应用
汇聚 2D 纹理节点通过提供 4 个相邻像素的原始 R 通道值,为 Shader 开发提供了精细化控制像素交互的能力,其核心价值在于:
- 自定义插值自由:突破内置采样的插值限制,实现风格化像素过渡效果。
- 轻量特效实现:无需复杂后处理,直接在片段着色器中实现模糊、边缘检测等效果。
- 跨平台兼容性:自动适配不同图形 API,降低多平台开发成本。
拓展方向:
- 实现运动模糊:结合时间偏移(_Time)和 Offset 参数,采样不同时刻的相邻像素。
- 开发风格化滤镜:通过自定义权重混合相邻像素,模拟油画、像素化等效果。
- 优化碰撞检测:在 GPU 中通过像素差异判断物体边缘,辅助物理碰撞计算。