【节点】[SampleTexture2DArray节点]原理解析与实际应用

【Unity Shader Graph 使用与特效实现】专栏-直达

Sample Texture 2D Array 节点是 Unity Shader Graph 中一个功能强大的纹理采样工具,专门用于处理 2D 纹理数组资源。与普通的 2D 纹理采样不同,该节点能够从包含多个 2D 纹理的数组中按索引选择特定的纹理进行采样,并返回 Vector 4 格式的颜色值。这种特性使得它在处理材质变体、动画序列帧、地形混合等场景中具有独特的优势。

在 Shader Graph 中使用 Sample Texture 2D Array 节点时,您需要提供 UV 坐标来确定采样位置,同时可以通过采样器状态节点来定义纹理的过滤方式和环绕模式。节点的核心特性是索引输入端口,它决定了从纹理数组中选取哪个具体的纹理进行采样。

2D 纹理数组是一种特殊类型的纹理资源,它将多个尺寸相同的 2D 纹理组合成一个单一的资源对象。每个纹理在数组中都有一个唯一的索引值,从 0 开始顺序排列。这种数据结构在需要频繁切换纹理但保持相同采样参数的场景中特别有用,因为它避免了多次设置采样状态的性能开销。

Note

如果在包含自定义函数节点或子图形的图形中使用此节点时遇到纹理采样错误,可以通过升级到 Unity 10.3 或更高版本来解决这些问题。这些版本对纹理数组的支持更加完善,修复了早期版本中可能存在的一些兼容性问题。

创建节点菜单类别

在 Shader Graph 的创建节点菜单中,Sample Texture 2D Array 节点位于 Input -> Texture 分类下。您可以通过以下步骤找到并添加该节点:

  • 在 Shader Graph 窗口中右键点击空白区域
  • 选择 Create Node 菜单
  • 导航至 Input 类别
  • 选择 Texture 子菜单
  • 点击 Sample Texture 2D Array 即可添加节点

兼容性

Sample Texture 2D Array 节点在 Unity 的不同渲染管线中具有广泛的兼容性,具体支持情况如下:

内置渲染管线 通用渲染管线 (URP) 高清渲染管线 (HDRP)

需要注意的是,在默认设置下,此节点只能连接到 Shader Graph 的片段着色器上下文中的块节点。如果需要在顶点着色器上下文中采样纹理,您必须将 Mip 采样模式设置为​LOD​。这种限制是由于顶点着色器中缺乏自动的 mipmap 级别计算所需的屏幕空间导数信息。

输入端口详解

Sample Texture 2D Array 节点提供了多个输入端口,每个端口都有特定的功能和用途:

Texture Array 输入

Texture Array 端口接受 Texture 2D Array 类型的资源输入。这是节点的核心输入,决定了要采样的纹理数组资源。在 Unity 中创建纹理数组需要通过脚本或导入设置专门配置,无法直接将普通纹理用作纹理数组。

使用纹理数组时需要注意:

  • 所有包含的纹理必须具有相同的尺寸、格式和 mipmap 级别
  • 纹理数组在内存中是连续存储的,访问效率较高
  • 支持压缩格式,但所有纹理必须使用相同的压缩方案

Index 输入

Index 端口接受 Float 类型的输入,用于指定要采样的纹理在数组中的索引位置。索引值应该是整数,但节点也接受浮点数输入,此时会自动取整。如果提供的索引超出了数组的有效范围,行为取决于平台,通常会自动钳制到有效范围内。

索引的使用技巧:

  • 可以使用时间节点驱动索引变化来创建纹理动画
  • 结合顶点颜色或材质属性可以实现基于距离或角度的纹理切换
  • 通过噪声函数控制索引可以创建随机的纹理变化效果

UV 输入

UV 端口接受 Vector 2 类型的输入,定义了纹理采样的坐标位置。UV 坐标通常来自 UV 节点或其他纹理坐标生成节点。对于纹理数组,UV 坐标的应用方式与普通 2D 纹理完全相同。

UV 处理的注意事项:

  • UV 坐标通常在[0,1]范围内,但可以通过采样器状态设置环绕模式
  • 可以使用 Tiling And Offset 节点对 UV 进行缩放和偏移
  • 在顶点着色器中采样时,需要确保 UV 坐标在三角形面上是连续的

Sampler 输入

Sampler 端口接受 Sampler State 类型的输入,用于定义纹理采样的详细参数。如果不连接此端口,节点将使用默认的采样器状态。通过 Sampler State 节点,您可以精确控制:

  • 过滤模式(Filter Mode):点过滤、双线性过滤、三线性过滤
  • 环绕模式(Wrap Mode):重复、钳制、镜像等
  • 各向异性过滤级别
  • 比较函数(用于深度纹理)

LOD 输入

LOD 输入端口仅在 Mip 采样模式设置为 LOD 时显示。它允许您明确指定要使用的 mipmap 级别。值为 0 表示最高分辨率的 mip 级别,正值表示较低分辨率的 mip 级别。

LOD 输入的典型应用:

  • 在顶点着色器中强制使用特定 mip 级别
  • 创建自定义的 mipmap 过渡效果
  • 性能优化时手动控制纹理细节级别

Bias 输入

Bias 输入端口仅在 Mip 采样模式设置为 Bias 时可用。它用于调整自动计算的 mipmap 级别,负值偏向更高分辨率,正值偏向更低分辨率。

Bias 的使用场景:

  • 微调纹理的锐利度或模糊度
  • 创建特殊视觉效果时调整纹理细节
  • 配合动态分辨率缩放系统

DDX 和 DDY 输入

DDXDDY 输入端口仅在 Mip 采样模式设置为 Gradient 时显示。这两个端口允许您提供自定义的屏幕空间导数,用于 mipmap 级别计算,而不是使用从 UV 坐标自动计算的导数。

自定义导数的应用:

  • 在自定义 UV 映射中提供正确的导数
  • 处理投影纹理或其他非线性映射
  • 特殊渲染效果中控制 mipmap 选择

其他节点设置

Sample Texture 2D Array 节点的图表检查器中提供了多个高级设置选项,这些设置可以显著改变节点的行为:

Use Global Mip Bias 设置

Use Global Mip Bias 是一个切换选项,控制节点是否使用渲染管线的全局 mip 偏差。启用此选项时,节点会将全局 mip 偏差值纳入 mipmap 级别计算中。

  • 启用状态​:Shader Graph 使用渲染管线的全局 mip 偏差来调整采样时的纹理信息细节级别。这对于保持整个场景中纹理一致性很重要,特别是在动态分辨率渲染或特定的视觉风格需求下。
  • 禁用状态​:Shader Graph 忽略全局 mip 偏差,仅使用节点自身的设置计算 mip 级别。这在需要精确控制特定纹理外观时很有用。

Mip Sampling Mode 设置

Mip Sampling Mode 是一个下拉菜单,提供了四种不同的 mipmap 采样模式,每种模式都适用于特定的使用场景:

Standard 模式

Standard 模式下,渲染管线自动计算并选择最适合当前像素的 mipmap 级别。这是最常用的模式,适用于大多数常规纹理采样需求。

标准模式的特点:

  • 自动基于屏幕空间 UV 导数计算 mip 级别
  • 提供最佳的视觉质量和性能平衡
  • 不支持在顶点着色器中使用

LOD 模式

LOD 模式允许您为纹理采样明确指定 mipmap 级别,无论像素间的 DDX 或 DDY 计算如何,纹理始终使用指定的 mip 级别。

LOD 模式的关键特性:

  • 支持在顶点着色器上下文中采样纹理
  • 适用于需要精确控制纹理细节级别的场景
  • 可以用于创建特殊的 mipmap 过渡效果

Gradient 模式

Gradient 模式允许您提供自定义的 DDX 和 DDY 值,用于 mipmap 级别计算,而不是使用从 UV 坐标自动计算的导数。

梯度模式的应用场景:

  • 自定义 UV 映射和投影效果
  • 屏幕空间效果和后期处理
  • 需要精确控制 mipmap 选择的特殊着色器

Bias 模式

Bias 模式允许您设置一个偏差值来调整自动计算的 mipmap 级别。负值偏向更高分辨率的 mip,正值偏向更低分辨率的 mip。

偏差模式的使用技巧:

  • 微调纹理的外观而不影响其他纹理
  • 创建特定距离下的纹理优化
  • 艺术导向的纹理细节控制

输出端口

Sample Texture 2D Array 节点提供了多个输出端口,让您可以灵活地访问采样结果的不同部分:

RGBA 输出

RGBA 输出端口返回完整的 Vector 4 颜色值,包含纹理样本的红、绿、蓝和透明度通道。这是最常用的输出,适用于大多数颜色采样需求。

各通道独立输出

节点还提供了各个颜色通道的独立输出端口:

  • R​:红色通道的浮点数值
  • G​:绿色通道的浮点数值
  • B​:蓝色通道的浮点数值
  • A​:透明度 Alpha 通道的浮点数值

独立通道输出的应用:

  • 当只需要纹理的特定通道时可以减少计算量
  • 分离颜色和透明度信息进行独立处理
  • 使用单通道纹理作为数据源(如高度图、遮罩图等)

示例图形用法

基础用法示例

在以下示例中,Sample Texture 2D Array 节点采样一个包含四种不同布料法线贴图的纹理数组。通过更改传递给索引端口的数值,可以动态切换不同的法线贴图,实现材质变体效果。

动画序列帧示例

纹理数组非常适合处理动画序列帧。通过将动画的每一帧存储为纹理数组中的一个切片,然后使用时间节点驱动索引变化,可以创建流畅的纹理动画:

// 伪代码示例:使用时间控制纹理数组索引
float frameRate = 24.0; // 帧率
float totalFrames = 64.0; // 总帧数
float currentIndex = floor((Time.time * frameRate) % totalFrames);

这种方法的优势:

  • 避免频繁切换纹理资源带来的性能开销
  • 所有动画帧可以批量加载和卸载
  • 支持随机访问任意帧,便于实现暂停、倒放等效果

地形混合系统示例

在复杂的地形系统中,纹理数组可以用于管理多种地表材质。通过结合高度图、坡度图或其他遮罩信息,可以动态选择最适合当前地形的纹理:

// 伪代码示例:基于高度选择纹理
float height = World Position.Y;
float snowHeight = 50.0;
float rockHeight = 30.0;

float textureIndex;
if (height > snowHeight) {
    textureIndex = 3; // 雪地纹理
} else if (height > rockHeight) {
    textureIndex = 2; // 岩石纹理
} else {
    textureIndex = 1; // 草地纹理
}

性能优化技巧

使用纹理数组时,以下技巧可以帮助优化性能:

  • 将经常同时使用的纹理打包到同一个数组中,减少纹理切换
  • 合理设置 mipmap 级别,平衡质量和性能
  • 在移动平台上注意纹理数组的大小和格式
  • 使用纹理数组流式加载系统管理内存使用

生成代码示例

了解 Sample Texture 2D Array 节点生成的底层着色器代码有助于深入理解其工作原理,并在需要时进行自定义修改。

基础采样代码

以下 HLSL 代码展示了节点在标准模式下的典型实现:

HLSL

// 生成的着色器代码示例
float4 _SampleTexture2DArray_RGBA = SAMPLE_TEXTURE2D_ARRAY(Texture, Sampler, UV, Index);
float _SampleTexture2DArray_R = _SampleTexture2DArray_RGBA.r;
float _SampleTexture2DArray_G = _SampleTexture2DArray_RGBA.g;
float _SampleTexture2DArray_B = _SampleTexture2DArray_RGBA.b;
float _SampleTexture2DArray_A = _SampleTexture2DArray_RGBA.a;

不同采样模式的代码差异

根据选择的 mip 采样模式,生成的代码会有所不同:

LOD 模式代码

HLSL

// LOD模式下的采样代码
float4 _SampleTexture2DArray_RGBA = SAMPLE_TEXTURE2D_ARRAY_LOD(Texture, Sampler, UV, Index, LOD);

Gradient 模式代码

HLSL

// Gradient模式下的采样代码
float4 _SampleTexture2DArray_RGBA = SAMPLE_TEXTURE2D_ARRAY_GRAD(Texture, Sampler, UV, Index, DDX, DDY);

Bias 模式代码

HLSL

// Bias模式下的采样代码
float4 _SampleTexture2DArray_RGBA = SAMPLE_TEXTURE2D_ARRAY_BIAS(Texture, Sampler, UV, Index, Bias);

自定义采样器状态

当连接了自定义的 Sampler State 节点时,生成的代码会包含相应的采样器定义:

HLSL

// 自定义采样器状态的代码示例
SAMPLER(sampler_CustomSampler);
float4 _SampleTexture2DArray_RGBA = SAMPLE_TEXTURE2D_ARRAY(Texture, sampler_CustomSampler, UV, Index);

相关节点

理解与 Sample Texture 2D Array 节点相关的其他节点有助于构建更复杂的着色器效果:

Sample Texture 2D 节点

Sample Texture 2D 节点是纹理数组节点的单纹理版本,用于采样普通的 2D 纹理资源。当不需要纹理数组的多纹理管理功能时,使用此节点更加简单高效。

主要区别:

  • 不支持索引选择,只能采样单一纹理
  • 适用于静态纹理或不需要频繁切换的场景
  • 代码生成更简单,潜在性能稍好

Sample Texture 3D 节点

Sample Texture 3D 节点用于采样 3D 体积纹理,与 2D 纹理数组在概念上相似但应用场景不同。3D 纹理在三维空间中进行采样,适用于体积渲染、噪声函数等场景。

关键差异:

  • 3D 纹理是真正的体积数据,而纹理数组是 2D 切片的集合
  • 采样时使用 Vector 3 坐标而不是 Vector 2 加索引
  • 适用于不同的视觉效果和技术应用

Sampler State 节点

Sampler State 节点用于定义纹理采样的详细参数,可以与任何纹理采样节点配合使用。通过精细控制采样器状态,可以实现特定的视觉风格或性能优化。

常用配置:

  • 过滤模式设置纹理缩放时的插值方式
  • 环绕模式控制纹理坐标超出[0,1]范围时的行为
  • 各向异性过滤改善倾斜角度的纹理质量

最佳实践和故障排除

性能优化建议

使用纹理数组时,遵循以下最佳实践可以确保最佳性能:

  • 合理组织纹理数组内容,将相关纹理分组存放
  • 注意纹理数组的尺寸和格式,避免不必要的内存占用
  • 在移动平台上测试不同 mipmap 设置的影响
  • 使用纹理压缩减少内存带宽需求

常见问题解决

以下是一些使用 Sample Texture 2D Array 节点时可能遇到的常见问题及解决方案:

索引超出范围错误

  • 确保索引值在纹理数组的有效范围内
  • 使用 Clamp 节点限制索引值
  • 检查纹理数组资源的实际切片数量

纹理采样显示粉色

  • 确认纹理数组资源已正确分配
  • 检查纹理数组的导入设置和格式兼容性
  • 验证 UV 坐标是否在有效范围内

性能问题

  • 检查纹理数组的大小是否适合目标平台
  • 评估 mipmap 设置是否合理
  • 考虑使用纹理流式加载减少内存压力

顶点着色器中采样失败

  • 确保将 Mip 采样模式设置为 LOD
  • 验证 UV 坐标在顶点间的连续性
  • 检查目标平台是否支持顶点纹理采样

【Unity Shader Graph 使用与特效实现】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

posted @ 2026-03-20 10:16  SmalBox  阅读(0)  评论(0)    收藏  举报