Sample Virtual Texture 节点是 Unity URP Shader Graph 中用于处理虚拟纹理采样的核心节点。虚拟纹理技术是一种先进的纹理流送系统,它允许开发者使用超出传统 GPU 内存限制的超高分辨率纹理,同时保持高效的内存使用和渲染性能。该节点通过智能的纹理流送机制,仅加载当前视锥体内可见的纹理部分,为现代游戏和实时渲染应用提供了处理大规模纹理数据的能力。
在 Shader Graph 中使用 Sample Virtual Texture 节点,开发者可以轻松集成虚拟纹理系统,而无需深入了解底层复杂的实现细节。该节点支持最多四个纹理层的采样,每个层可以包含不同类型的纹理数据,如基础颜色、法线、高度或金属度等材质属性。这种多层架构使得单个虚拟纹理资产能够替代多个传统纹理,简化材质设置并提高渲染效率。
虚拟纹理系统的核心优势在于其动态流送能力。当摄像机移动或物体在场景中变换时,系统会自动检测需要的高分辨率纹理块,并在后台异步加载它们。这种机制特别适合开放世界游戏、建筑可视化和其他需要大量高分辨率纹理的应用场景。Sample Virtual Texture 节点作为这一系统在 Shader Graph 中的接口,提供了直观的方式来访问这些高级功能。
描述
Sample Virtual Texture 节点专门设计用于对虚拟纹理属性进行采样操作。它接收 UV 坐标作为输入,并返回最多四个 Vector 4 类型的颜色值,这些值对应虚拟纹理中不同层的采样结果。每个输出通道可以提供独立的材质属性,使得单个采样操作能够获取完整的表面材质信息。
虚拟纹理与传统纹理的根本区别在于其存储和访问方式。传统纹理需要完整加载到 GPU 内存中,而虚拟纹理则按需加载纹理的特定区域和 mip 级别。这种按需加载机制使得虚拟纹理能够处理极端高分辨率的纹理数据,比如 16K、32K 甚至更高分辨率的纹理,而不会耗尽可用的 GPU 内存资源。
在 Shader Graph 中使用 Sample Virtual Texture 节点时,需要注意其默认只能在片元着色器阶段使用。这是因为虚拟纹理采样依赖于屏幕空间导数来计算适当的 mip 级别,而这些导数在顶点着色器中不可用。不过,通过特定的配置,也可以在顶点着色器中使用该节点,但这通常需要手动指定 LOD 级别,而不是依赖自动计算。
当项目中禁用了虚拟纹理功能时,Sample Virtual Texture 节点会自动回退到标准的 2D 纹理采样行为。这种向后兼容性确保了着色器在不同项目配置下的可移植性,无需为支持或不支持虚拟纹理的系统创建两套独立的着色器。
Sample Virtual Texture 节点必须连接到 Shader Graph 资源中的 Virtual Texture 属性才能正常工作。如果节点未连接到任何虚拟纹理属性,Shader Graph 编译器会报错,提示需要建立连接。这种设计确保了资源的正确引用和流送系统的正常初始化。
对于法线贴图的处理,Sample Virtual Texture 节点提供了专门的配置选项。要为特定层启用法线贴图采样,需要在 Graph Inspector 中选择该层,并将 Layer Type 从 Default 改为 Normal。这一设置会确保法线向量被正确解码和转换,从切线空间到世界空间或视图空间,具体取决于着色器的需求。
虚拟纹理的工作原理
虚拟纹理系统通过将超大纹理分割成固定大小的图块(通常为 128x128 或 256x256 像素)来工作。这些图块根据摄像机的距离和视角动态流送。系统维护一个物理纹理缓存,其中包含当前可见区域所需的图块。当需要访问尚未加载的图块时,系统会触发异步加载请求,并从磁盘或网络存储中获取所需数据。
Sample Virtual Texture 节点在这一过程中扮演关键角色,它处理以下任务:
- 将输入的 UV 坐标映射到虚拟纹理空间
- 确定当前采样所需的 mip 级别
- 检查所需图块是否已加载到物理缓存中
- 如果图块未加载,触发回退机制(如使用较低 mip 级别)
- 从缓存中获取最终采样数据并返回
性能考量
使用 Sample Virtual Texture 节点时,性能是需要重点考虑的因素。虽然虚拟纹理可以减少总体内存使用,但采样操作本身可能比传统纹理采样更昂贵,因为它涉及额外的间接查找。优化建议包括:
- 尽量减少单个着色器中的虚拟纹理采样次数
- 合理设置虚拟纹理的图块大小和缓存尺寸
- 使用适当的 mip 映射偏置来平衡质量和性能
- 在移动平台上谨慎使用,考虑其有限的带宽和计算资源
端口

Sample Virtual Texture 节点提供了一系列输入和输出端口,用于控制采样过程和获取结果。理解每个端口的功能和适用场景对于有效使用该节点至关重要。
输入端口
UV 输入端口接收 Vector 2 类型的坐标值,用于指定虚拟纹理上的采样位置。这个端口通常连接到 UV 节点或经过变换的坐标值。UV 端口的绑定类型为 UV,意味着它可以自动适应不同的 UV 通道,但也可以手动提供自定义的坐标值。
VT 输入端口是 Sample Virtual Texture 节点的核心输入,它必须连接到 Shader Graph 中的 Virtual Texture 属性。这个连接确保了虚拟纹理系统能够正确初始化和流送所需的纹理数据。VT 端口不绑定到特定的纹理类型,而是引用整个虚拟纹理资产,其中可能包含多个纹理层。
输出端口
Out 输出端口提供虚拟纹理中第 1 层的 RGBA 采样结果。这个端口通常用于基础颜色或漫反射纹理,是大多数材质着色器的主要输入。输出值的范围取决于纹理数据的编码方式,通常是 0 到 1 的线性空间值,但也可能是其他颜色空间,如 sRGB。
Out2 输出端口提供第 2 层的采样结果,常用于存储如粗糙度、金属度或环境光遮蔽等材质属性。在多图层虚拟纹理中,这一层可能包含单通道或双通道数据,但输出始终是四分量向量,未使用的通道通常填充为 0 或 1。
Out3 输出端口在虚拟纹理至少包含三层时可用,提供第 3 层的采样数据。这一层可能用于高度图、发射图或其他特殊用途的材质属性。使用前应确保虚拟纹理资产确实包含三层或以上,否则该端口可能输出默认值或导致编译错误。
Out4 输出端口在虚拟纹理包含四层时可用,提供最顶层的数据采样。在完整的四层虚拟纹理设置中,这四层通常构成标准的 PBR 材质属性:基础颜色、法线、金属度/粗糙度和高度/环境光遮蔽。
端口使用策略
有效使用 Sample Virtual Texture 节点的端口需要遵循一定的策略:
- 仅连接实际需要的输出端口,未使用的端口不会产生额外开销,但清晰的连接有助于提高可读性
- 确保 UV 输入提供正确的坐标空间和缩放,避免纹理拉伸或压缩
- 对于多层虚拟纹理,了解每层存储的数据类型和编码方式至关重要
- 在简单用例中,可能只需要使用 Out 端口,而更复杂的材质可能需要所有四个输出
设置
Sample Virtual Texture 节点提供了丰富的设置选项,用于精确控制采样行为和适应不同的渲染需求。这些设置可以通过 Graph Inspector 访问,当节点被选中时,相关选项会显示在 inspector 面板中。
Lod Mode
Lod Mode 设置决定了采样时如何选择 mipmap 级别。这一设置对渲染质量和性能有显著影响,特别是在处理动态摄像机移动或物体变换时。
Automatic 模式是默认设置,它根据屏幕空间导数自动计算适当的 mip 级别。这种模式在大多数情况下提供最佳的质量和性能平衡,因为它确保了纹理细节与屏幕像素密度匹配。自动 LOD 计算依赖于 ddx 和 ddy 指令,这些指令在片元着色器中可用,但在顶点着色器中不可用。
Lod Level 模式允许手动指定固定的 mip 级别。这种模式适用于需要精确控制纹理细节的情况,如特效着色器或特定风格化渲染。当使用固定 LOD 时,纹理采样不会随距离变化,这可能导致远处物体过度模糊或近处物体锯齿。
Lod Bias 模式在自动计算的 mip 级别上应用一个偏置值。正偏置会使纹理更模糊,负偏置会使纹理更锐利,但可能引入闪烁或噪点。这一模式适用于微调纹理外观,或在不同硬件上平衡性能和质量。
Derivatives 模式使用显式导数计算 mip 级别,适用于特殊情况,如自定义 UV 映射或非标准着色器流程。这种模式提供了最大的灵活性,但需要更深入的理解才能正确使用。
Quality
Quality 设置控制采样时的过滤质量,影响纹理的视觉平滑度和性能。
Low 质量使用双线性过滤,计算开销较小但可能在高对比度边缘产生明显的块状效应。这种设置适用于移动平台或性能敏感的场景,其中渲染速度优先于视觉保真度。
High 质量使用各向异性过滤,更好地保持倾斜视角下的纹理细节。这种设置会产生更高质量的图像,特别是对于远离摄像机的表面,但会增加内存带宽和计算需求。高性能硬件通常能够处理高质量设置而不会显著影响帧率。
Automatic Streaming
Automatic Streaming 开关控制虚拟纹理系统的流送行为。
Enabled 状态允许 Unity 自动管理纹理流送,根据摄像机位置和视角动态加载和卸载纹理块。这是推荐设置,因为它提供了最佳的可用性和性能平衡,无需手动干预。
Disabled 状态关闭自动流送,需要手动管理纹理加载。这种高级模式适用于特殊用例,如自定义流送逻辑或特定的内存管理需求,但对大多数用户不推荐,因为它增加了复杂性且容易出错。
Enable Global Mip Bias
Enable Global Mip Bias 开关控制是否应用 Unity 引擎的全局 mip 偏置。
当启用时,Unity 可以在运行时自动调整 mip 级别,以配合动态分辨率缩放或其他后处理效果。这种偏置改善了细节重建和 temporal anti-aliasing 的效果,但可能轻微改变纹理外观。
禁用此选项会确保 mip 级别完全由 Lod Mode 设置控制,提供更可预测的采样行为,但可能牺牲一些图像质量优化。
Layer Type
Layer Type 设置允许为虚拟纹理的每个层指定数据类型,这影响了采样结果的解释和处理方式。
Default 类型适用于标准颜色数据,如漫反射贴图、粗糙度贴图或金属度贴图。采样结果直接作为颜色或标量值使用,无需特殊转换。
Normal 类型指定该层包含法线贴图数据。当设置为 Normal 时,采样器会执行适当的解码和转换,将存储在纹理中的切线空间法线转换为可用的向量数据。对于法线贴图层,确保原始纹理数据正确编码至关重要------通常是使用两种常见的编码方式:DX 风格(绿色通道不变)或 OpenGL 风格(红色通道不变)。
生成的代码示例
Sample Virtual Texture 节点在编译时会生成相应的 HLSL 代码,理解这些代码有助于深入掌握节点的功能和在需要时进行自定义修改。
函数结构分析
生成的代码核心是一个名为 SampleVirtualTexture 的函数,它封装了虚拟纹理采样的完整流程:
text
HLSL
float4 SampleVirtualTexture(float2 uv, VTPropertyWithTextureType vtProperty, out float4 Layer0)
{
// 初始化虚拟纹理参数结构
VtInputParameters vtParams;
vtParams.uv = uv;
vtParams.lodOrOffset = 0.0f;
vtParams.dx = 0.0f;
vtParams.dy = 0.0f;
vtParams.addressMode = VtAddressMode_Wrap;
vtParams.filterMode = VtFilter_Anisotropic;
vtParams.levelMode = VtLevel_Automatic;
vtParams.uvMode = VtUvSpace_Regular;
vtParams.sampleQuality = VtSampleQuality_High;
// 光线追踪特殊处理
#if defined(SHADER_STAGE_RAY_TRACING)
if (vtParams.levelMode == VtLevel_Automatic || vtParams.levelMode == VtLevel_Bias)
{
vtParams.levelMode = VtLevel_Lod;
vtParams.lodOrOffset = 0.0f;
}
#endif
// 准备虚拟纹理采样
StackInfo info = PrepareVT(vtProperty.vtProperty, vtParams);
// 采样特定层
Layer0 = SampleVTLayerWithTextureType(vtProperty, vtParams, info, 0);
// 返回解析输出
return GetResolveOutput(info);
}
参数详解
VtInputParameters 结构包含了控制采样行为的所有参数:
- uv:输入的纹理坐标,通常来自顶点着色器插值或计算所得
- lodOrOffset:LOD 级别或偏置值,具体含义取决于 levelMode 设置
- dx 和 dy:屏幕空间导数,用于自动 LOD 计算
- addressMode:寻址模式,控制 UV 坐标超出[0,1]范围时的行为
- filterMode:过滤模式,决定纹理放大缩小时的插值方法
- levelMode:LOD 计算模式,对应 Graph Inspector 中的 Lod Mode 设置
- uvMode:UV 空间模式,通常为常规 UV 空间
- sampleQuality:采样质量,对应 Quality 设置
特殊情形处理
代码中的条件编译部分处理了光线追踪等特殊情形:
text
HLSL
#if defined(SHADER_STAGE_RAY_TRACING)
if (vtParams.levelMode == VtLevel_Automatic || vtParams.levelMode == VtLevel_Bias)
{
vtParams.levelMode = VtLevel_Lod;
vtParams.lodOrOffset = 0.0f;
}
#endif
在光线追踪着色器中,自动 LOD 和 LOD 偏置模式被强制转换为固定 LOD 模式,因为光线追踪环境下无法计算屏幕空间导数。这一转换确保了代码的兼容性和稳定性。
采样流程
函数的执行流程遵循标准的虚拟纹理采样步骤:
- 参数初始化:设置所有必要的采样参数
- 系统准备:调用 PrepareVT 函数初始化虚拟纹理系统
- 层采样:对指定层进行实际采样操作
- 结果返回:通过输出参数和返回值提供采样结果
理解这一流程有助于调试虚拟纹理相关问题和优化着色器性能。
实际应用示例
基础虚拟纹理采样
最简单的 Sample Virtual Texture 用法是采样单层虚拟纹理作为漫反射颜色:
- 在 Shader Graph 中创建 Virtual Texture 属性
- 添加 Sample Virtual Texture 节点,将 VT 端口连接到 Virtual Texture 属性
- 将 UV 端口连接到适当的 UV 坐标(如 UV 节点)
- 将 Out 端口连接到主着色器的 Base Color 输入
这种设置适用于替换传统的 2D 纹理采样,同时获得虚拟纹理的流送优势。
多层 PBR 材质设置
对于完整的 PBR 材质,可以使用四层虚拟纹理:
- 第 1 层(Out):基础颜色,连接到 Base Color
- 第 2 层(Out2):法线贴图,设置为 Normal 类型,连接到 Normal 输入
- 第 3 层(Out3):金属度和粗糙度,通常红色通道为金属度,绿色通道为粗糙度
- 第 4 层(Out4):环境光遮蔽,连接到 Occlusion 输入
这种配置用一个虚拟纹理资产替代了多个独立纹理,简化了材质管理并提高了内存效率。
高级混合技术
Sample Virtual Texture 节点可以与其他节点结合,实现复杂的材质效果:
- 使用 Height 输出与 Parallax Occlusion Mapping 节点结合,实现视差效果
- 将多个虚拟纹理采样与 Blend 节点结合,实现材质混合
- 使用自定义 UV 变换与 Triplanar 节点结合,实现无接缝的三平面映射
这些高级技术扩展了虚拟纹理的应用范围,使其能够适应各种复杂的渲染需求。
故障排除与最佳实践
常见问题
虚拟纹理采样中可能遇到的常见问题包括:
- 纹理不显示或显示为粉色:检查 Virtual Texture 属性是否正确设置和连接
- 性能下降:确保虚拟纹理缓存大小适当,减少不必要的采样
- 纹理闪烁或 popping:调整流送设置,增加缓存尺寸或调整 mip 偏置
- 法线看起来不正确:确认法线层的 Layer Type 设置为 Normal,并检查原始纹理的编码格式
优化建议
为了获得最佳性能和视觉效果:
- 根据目标平台平衡虚拟纹理的分辨率和层数
- 使用适当的 mip 偏置避免过采样或欠采样
- 在移动平台上考虑使用较低质量的过滤设置
- 定期分析虚拟纹理流送统计信息,优化纹理设置
兼容性考虑
Sample Virtual Texture 节点在不同平台和渲染管线中的行为可能有所差异:
- 在 Built-in Render Pipeline 中需要额外的设置步骤
- 移动平台可能对虚拟纹理的支持有限,需测试目标设备
- 当虚拟纹理禁用时,确保备用纹理具有适当的分辨率和格式
【Unity Shader Graph 使用与特效实现】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)