1767 words
9 minutes
WFC瓦片生成标准解读
2025-08-02
No Tags

大致工作流:AI生成2D俯视图——生成地板——墙壁重新组装为Prefab

要不地板和墙壁单独计算?

先生成带有墙壁的草图,然后对于特性房间可以用地板区分?

还是直接Random?

有关Blender和Unity的模型协作,请看https://www.yuque.com/shuangfeidu/txwa8w/qeomm77fu218fa4v

  • 上(1)右上(2)右(4)右下(8)下(16)左下(32)左(64)左上(128)
  • 8邻域位掩码(8-directional bitmask)

技术解读#

首先需要知道WFC算法是做什么的。简单来说,它是一种根据一小组“规则”来程序化生成复杂地图(比如游戏关卡、纹理等)的算法。它最核心的规则就是“邻接规则”——即哪些瓦片(tile)可以和哪些瓦片放在一起

这张图展示的就是一套非常经典和高效的瓦片(tileset)定义标准,通常被称为“Blob Tileset”或“Bitmask Autotiling”。它的目的是用一种巧妙的方式,自动处理所有瓦片的邻接关系。

核心概念:什么是“瓦片”和“规则”?#

在这张图中:

  • 黄色部分可以理解为“实体”或“地面”。
  • 蓝色部分可以理解为“虚空”或“背景”。

每一个小方格都是一个“瓦片”。WFC算法的目标就是将这些瓦片拼接成一个看起来自然、没有断裂的、更大的“Blob”(一团)形状。

规则就是:黄色的边缘必须和黄色的边缘相连,蓝色的边缘必须和蓝色的边缘相连。

为了实现这一点,我们需要为每一种可能的瓦片组合都创建一个瓦片。一个2x2的瓦片有4个角,每个角都可以是黄色或蓝色,所以理论上我们有 2^4 = 16 种基本形态。这正是图片最上面一行展示的16种核心瓦片。

2. 解读图片中的数字:Bitmask(位掩码)#

这张图最让人困惑的就是这些数字。这些数字是每种瓦片的唯一ID,而这个ID是通过一种叫做**“位掩码”(Bitmask)**的技术计算出来的。

这个方法给瓦片的每个关键位置分配一个固定的数值(通常是2的幂),然后通过将“激活”位置的数值相加,得到最终的ID。

非常棒的分析!您已经完全抓住了最核心的要点,这正是程序化生成中常用的 8邻域位掩码(8-directional bitmask) 的思想。

您的推理方向完全正确:通过为每个邻近位置(边和角)分配一个2的幂的数值,然后将它们相加,来为每种瓦片形态生成一个独一无二的ID。

不过,您会发现,如果将您提出的这套数值方案代入原图,会无法完美匹配所有ID。

上(1), 右上(2), 右(4), 右下(8), 下(16), 左下(32), 左(64), 左上(128)

这是因为这张经典的 “Blob Tileset” 图,使用了一套稍微有些“古怪”和非连续的数值分配方案。您的方案在逻辑上更清晰、更现代,但这张图遵循的是另一套标准。

让我们用您正确的思路,来解开这张图特定数值谜题。这张图最上面一行的16个瓦片,实际上只关心四个角的状态。

总结#

为了让你彻底理解,我们把整个逻辑梳理一遍:

  1. 目的: 使用WFC算法,通过拼接小瓦片,自动生成看起来自然的、连贯的“Blob”地图。
  2. 核心规则: 瓦片的边缘颜色必须匹配(黄对黄,蓝对蓝)。
  3. 瓦片ID (位掩码): 为了让计算机高效地理解和查询“哪些瓦片可以和我的右边缘匹配?”,我们给每种瓦片一个数字ID。这个ID是通过检查瓦片的边缘(或角)是否为黄色,然后将对应位置的预设值相加得到的。这就是位掩码技术。
  4. 图片的作用: 这张图就是一个**“ID查询表”“标准解读”**。它告诉你:
    • ID为 7 的瓦片长什么样(上、右、下是黄边)。
    • ID为 23 的瓦片长什么样(上、右、下、左都是黄边,但它不是全黄的中心块)。
    • ID为 5 的瓦片和ID为 20, 80, 65 的瓦片在逻辑上属于同一组,它们可能只是旋转或翻转的关系。

如何使用它:
当WFC算法要在一个空格子填充瓦片时,它会检查这个格子的邻居。比如,它发现:

  • 上方的瓦片有一个黄色的下边缘。
  • 右边的瓦片有一个蓝色的左边缘。

算法就会去这个规则集里寻找一个满足“上边缘为黄,右边缘为蓝”的瓦片,然后从所有满足条件的瓦片中随机选择一个放进去。这个过程不断重复,直到整个地图被填满。

我们的房间要求#

一般的WFC瓦片中,瓦片不一定是一个最小单位。但是在这个游戏中,每一个瓦片/或者说是房间都是最小单位。也就是说,一个瓦片中,最多只有四个出口,并且没有多出口的拼接。

目前我想的方法是墙壁+地板的组装方式。即,墙壁负责进行控制出入口的生成(上图的黄色部分),地板则负责控制这个房间单位的特性(黑房间,灰房间?)。脚本和shader则和地板强绑定。最终以上内容重新组装为Prefab。

最终成品 (Prefab)
├── 墙壁 (Wall)
│ └── 职责: 控制出入口生成 (连接性)
└── 地板 (Floor)
├── 职责: 控制房间单位特性
│ ├── 强绑定: 脚本 (Script)
│ └── 强绑定: 着色器 (Shader)
└── 示例: 黑房间、灰房间等

一个房间有东南西北四个方向的开口,每个方向可以选择“开”或“关”。总共有 16 种可能性,具体如下:

所有开口可能性#

1. 无开口(四个方向都关闭)#


2. 仅一个方向开口#

  • 西

3. 两个方向开口#

  • 东 + 南
  • 东 + 西
  • 东 + 北
  • 南 + 西
  • 南 + 北
  • 西 + 北

4. 三个方向开口#

  • 东 + 南 + 西
  • 东 + 南 + 北
  • 东 + 西 + 北
  • 南 + 西 + 北


5. 四个方向都开口#

  • 东 + 南 + 西 + 北

总共有 16 种组合(即 image),包括所有可能的子集(从完全关闭到全部开启)。

一共16种组装房间。#

示例#

Tile Samples

sample demo。可以调整种子进行不同的地图生成。但是还没有做手动约束(哪种房间只能生成几个)

瓦片重声明

以路牌作为所有prefab测试,目前已经可以进行Unity-Houdini间的连接。

Todo:Random房间属性并接入Prefab,随机摆放饰品添加画面丰富度,接入TOPS进行AI生成模型的批量减面器。

WFC瓦片生成标准解读
https://fuwari.vercel.app/posts/wfc-tile-generation-standard/
Author
Axon
Published at
2025-08-02
License
CC BY-NC-SA 4.0