这两种方法是地形纹理混合系统中的不同技术方案,用于在地形上混合多种纹理。让我详细介绍它们的区别:

1 Splat Map(分离贴图)方法

工作原理: Splat Map 使用多张灰度贴图(通常是 RGBA 通道),每个通道代表一种纹理的权重/强度。

技术实现

  • 每个像素的 RGBA 四个通道分别存储 4 种不同纹理的混合权重
  • 权重值范围 0-1,表示该位置某种纹理的可见程度
  • 最终颜色 = 纹理 1 × R 权重 + 纹理 2 × G 权重 + 纹理 3 × B 权重 + 纹理 4 × A 权重 + …

优点

  • 平滑混合:多种纹理可以在同一像素上平滑过渡
  • 自然效果:能创造出非常自然的地形纹理混合
  • 广泛支持:大多数地形系统都支持这种方法

缺点

  • 纹理数量限制:单张贴图只能混合 4 种纹理(RGBA 限制)
  • 内存消耗大:需要多张高分辨率的权重贴图
  • 性能开销:着色器中需要采样多张纹理并进行混合计算

2 Index Map(索引贴图)方法

工作原理: Index Map 使用单一贴图存储纹理索引,每个像素值直接指向要使用的纹理编号。

技术实现

  • 每个像素存储一个整数值,代表纹理数组中的索引
  • 例如:像素值 0 = 草地纹理,1 = 石头纹理,2 = 沙土纹理
  • 着色器根据索引值直接从纹理数组中选择对应纹理

优点

  • 支持更多纹理:理论上可以支持 256 种不同纹理(8 位索引)
  • 内存效率高:只需要一张索引贴图,占用内存少
  • 性能优秀:着色器只需要单次纹理查找,无混合计算
  • 精确控制:每个区域使用固定的纹理,边界清晰

缺点

  • 硬边界:纹理之间无法平滑过渡,边界较为生硬
  • 视觉效果限制:难以创造自然的混合效果
  • 工具复杂性:需要特殊的地形编辑工具

3 实际应用场景

Splat Map 适合

  • 需要自然地形混合效果的项目
  • 写实风格的开放世界游戏
  • 地形纹理种类相对较少(每组 4 种以内)

Index Map 适合

  • 需要大量不同纹理类型的项目
  • 性能要求较高的项目
  • 风格化或像素艺术风格的游戏
  • 需要精确控制纹理分布的场景

4 混合方案

现代地形系统有时会结合两种方法:

  • 使用 Index Map 确定主要纹理
  • 在纹理边界处使用额外的混合信息实现平滑过渡
  • 或者使用多层 Index Map 实现更复杂的混合效果

Note

Godot Terrain3D 里实际采用的应该是 Index Map+ 混合的方案,里面存了两个纹理索引,一个是 base 纹理索引,一个是 overlay 纹理索引,以及 blend 权重。

5 FAQ

如果要支持 32 种纹理,splat 方法是否得用 8 张 RGBA 贴图,是否需要占用大量显存?

是的,你的分析是正确的。如果使用 Splat Map 方法支持 32 种纹理,确实会面临严重的显存问题。

Splat Map 的显存计算

纹理数量需求

  • 32 种纹理 ÷ 4(RGBA 通道)= 8 张 splat map

显存占用示例(以 2048x2048 分辨率为例):

  • 单张 RGBA32 贴图:2048 × 2048 × 4 字节 = 16.77 MB
  • 8 张 splat map:16.77 MB × 8 = 134.2 MB
  • 32 张实际纹理贴图:假设每张 1024×1024 RGBA,约 4MB × 32 = 128 MB
  • 总计约 262 MB 仅用于地形纹理系统

如果地形分辨率更高(如 4096×4096),splat map 部分就会占用 537 MB

具体问题

显存压力

  • 移动设备显存通常只有 2-4GB,262MB 占用过大
  • PC 显卡虽然显存更多,但仍然是巨大的浪费

带宽消耗

  • 着色器需要采样 8 张 splat map + 32 张纹理
  • GPU 带宽消耗巨大,影响渲染性能

缓存效率

  • 大量纹理采样会导致 GPU 缓存未命中
  • 进一步降低性能

Index Map 的优势对比

显存占用

  • 单张 R8 索引贴图(2048×2048):2048 × 2048 × 1 = 4 MB
  • 32 张纹理贴图:128 MB
  • 总计约 132 MB(节省约 50% 显存)

性能优势

  • 着色器只需采样 1 张索引贴图 + 1 次纹理数组查找
  • GPU 带宽消耗极低
  • 缓存友好

实际解决方案

方案 1:混合方法

// 使用索引贴图确定主纹理,局部使用权重混合
int main_texture_index = int(texture(index_map, uv).r * 255.0);
vec4 base_color = texture(texture_array, vec3(uv, main_texture_index));
 
// 可选:在特定区域使用少量 splat 混合
vec4 blend_weights = texture(local_splat_map, uv);
// 仅在需要平滑过渡的区域进行混合

方案 2:分层索引

  • 使用多个索引层,每层处理不同细节级别
  • 远距离使用低细节索引,近距离使用高细节索引

方案 3:压缩技术

  • 使用压缩纹理格式(如 BC1, BC3)
  • 动态加载,只保留当前可见区域的纹理

结论

对于 32 种纹理的需求,Index Map 方法明显更优:

  • 显存节省:约 50% 的显存占用
  • 性能提升:显著减少 GPU 带宽消耗
  • 扩展性:轻松支持更多纹理类型
  • 工具简化:编辑和管理更加简单

这就是为什么 Terrain3D 选择 Index Map 方法的主要原因——在支持大量纹理的同时,保持良好的性能和合理的资源占用。