小明是个乐高迷,但他的搭法和别人不一样。别的小朋友一块一块地找零件、对照图纸,他却熬夜写了一本《乐高城市拼搭说明书》:里面规定了路要修多宽、街区分多大、高楼往哪儿扎堆、公园要留几块。第二天,他把说明书交给一群会读图的乐高小机器人,自己出门买早餐——等回来时,玄关地板上已经长出了一整座城市。更神奇的是,他改了一个数字再跑一遍,城市还是那座城市,但街道走向、楼群高低全都变了样。这就是“程序化建筑与城市生成”的魔力:程序员不亲手搭建每一栋楼、每一条街,而是设计一套“让内容自己长出来”的规则,再用代码把规则跑成一座完整、统一、可复现的虚拟城市。

岗位关联

掌握程序化建筑与城市生成,等于把“一个场景要磨三周”的工作流,变成“一个按钮生成一百座城”的自动化流水线。这是游戏、仿真与数字孪生领域内容生产的核心技能。

目录
  1. 可视化演示
  2. 基础概念:先写规则,再当建筑工人
  3. 核心算法:四本风格各异的拼搭说明书
  4. 城市布局:先画马路,再切地皮,最后盖楼
  5. 生成管线:一条从地皮到细节的流水线
  6. 性能优化:让城市跑得动,而不是卡成 PPT
  7. 实战应用:AI 建筑师登场,城市自己进化
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示程序化内容生成(PCG)三大核心:建筑生成(形状文法3规则R1 base/R2 floor/R3 roof+参数化PRM控制W/H/D生成5层楼房)、城市布局(7条道路网络3水平4垂直划分6个功能区块RES住宅/COM商业/IND工业每区块自动生成建筑)、PCG管线(4阶段NSE噪声→RUL文法规则→PRM参数控制→OUT网格输出+AI驱动增强自然度),三模式切换理解PCG。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+C1+'

基础概念:先写规则,再当建筑工人

小明发现,那本说明书威力再大,也离不开三样东西:一个起始数字、一套拼搭规则、一个最终成品。起始数字决定“第一块积木放在哪”,拼搭规则决定“下一块积木跟在哪”,最终成品就是整座城市。这三样东西,恰好就是程序化生成的骨架。

在计算机里,这三样东西分别叫“种子(Seed)”、“生成规则(Rule)”和“生成内容(Content)”。程序化内容生成(Procedural Content Generation, 简称 PCG)并不是“随机乱画”,而是“由规则驱动的自动化创作”。游戏里那些看似漫无边际的开放世界,背后往往只是一小段规则代码加上一个种子数字。种子一换,世界就换了副面孔;种子不变,世界可以在任何机器上原样复现。

建筑生成与城市生成,是 PCG 的两个层次。前者解决“一栋楼怎么长”,后者解决“一座城怎么排”。建筑生成关注墙、窗、屋顶的组合方式;城市生成关注路网、街区、地块的布局关系。两者的共同点,都是把“人的设计经验”翻译成“机器可执行的规则”。应用价值也很直接:人力只能手搓几十栋楼,规则驱动却能一口气生成几万栋,还能保证风格统一、永不重复。

有了这三样,小明再也不需要一砖一瓦地手搭。他只需要问自己一个问题:我想让这座城市长成什么样?然后把答案写成规则。这就好比给城市装上了一颗会思考的“性格种子”。

C=G(s, R)\displaystyle C = G(s,\, R)
内容 C 等于生成器 G 把种子 s 和规则集 R 加工后产出的成品。想换一座城?改种子;想换一种风格?改规则。
  1. 生成内容 C最终产出的城市、建筑或地形,是等式左边的“成品”。
    CC
  2. 生成器 G一个可执行的函数或程序,负责把“原料”加工成“成品”。
    G(⋅)G(\cdot)
  3. 种子 s一个起始数字,相当于说明书上的“起始积木位置”,决定了所有后续选择。
    ss
  4. 规则集 R一组创作规则,如“路宽 10 米”“楼高 3 到 30 层”,约束生成风格。
    RR

核心算法:四本风格各异的拼搭说明书

同样的零件箱,不同的说明书,能拼出完全不同的东西。程序化生成也有四本经典“说明书”,分别擅长不同的活:形状文法负责“细胞分裂”,L 系统负责“树枝生长”,Perlin 噪声负责“大理石纹理”,波形函数坍缩负责“数独填格”。

形状文法(Shape Grammar)把一栋建筑看成一棵“分形树”:一个起点形状,按规则不断替换成更小的子形状。比如规则“楼体 → 楼体 + 一层楼层”,程序就会像细胞分裂一样,一层层把楼“长”高。这也是 Esri CityEngine 等专业工具的核心建模语言。L 系统(L-system)原是植物学家用来模拟植物生长的形式语言,如今被用来生成树冠、枝干,甚至教堂的飞扶壁。它的精髓是“递归替换”:一根枝上长两根小枝,小枝上再长两根小小枝,越分越细。

Perlin 噪声(Perlin Noise)负责“自然感”。纯随机数像撕碎的纸屑,杂乱无章;Perlin 噪声像大理石纹路,连续平滑、有高有低。它是地形高度、云朵密度、建筑高度起伏的通用“画笔”。波形函数坍缩(Wave Function Collapse, WFC)的思路来自量子力学:每个格子一开始处于“什么都有可能”的叠加态,随着相邻约束不断“坍缩”成确定形态——每块“瓦片”的四个边都必须和邻居严丝合缝,就像数独里每行每列不能重复。

如果把 L 系统比作“会不断分叉生长的树枝”,那么形状文法就是“按图纸细胞分裂的高楼”,Perlin 噪声是“自然起伏的地皮”,WFC 是“处处讲规矩的数独城市”。四本说明书一组合,城市就有了骨架、表情和秩序。

μn+1=P(μn)\displaystyle \mu_{n+1} = P\big(\mu_n\big)
这是 L 系统的迭代公式:用规则集 P 替换当前状态 μₙ 中的所有符号,得到下一代状态 μₙ₊₁。例如规则 A→AB、B→A,从 A 出发会得到 A→AB→ABA→ABAAB,像树枝一样越生越繁。
  1. 当前状态 μₙ第 n 代的结构字符串,比如一棵只有主干的小树。
    μn\mu_n
  2. 规则集 P一组替换规则,如“主干 → 主干 + 左侧枝 + 右侧枝”。
    PP
  3. 应用替换把当前状态中所有可替换的符号,按规则各替换一次。
    P(μn)P(\mu_n)
  4. 下一代状态 μₙ₊₁替换完全部符号后得到的新一代结构,可继续迭代。
    μn+1\mu_{n+1}

城市布局:先画马路,再切地皮,最后盖楼

小明盖城的第一步永远是画马路,因为路是城市的骨架——路往哪儿伸,街区就往哪儿长。第二步是切地皮:被路围出来的一块块区域,就是未来的街区。第三步才是决定哪块地皮盖高楼、哪块留公园。

在城市布局里,“路网规划”是第一优先级。常见路网有三种形态:棋盘网格(曼哈顿式)、放射环线(巴黎式)、有机蔓延(欧洲老城式)。网格路网生成简单、寻路友好;放射路网突出市中心;有机路网依赖噪声与地形,更接近真实老街。路网画完,“地块划分”随之而来:把路围成的多边形切成可建造的单元,常用算法包括规则网格切分与 Voronoi 剖分。

地块有了,密度怎么定?城市不是均匀的立方体森林。现实规律是:越靠近市中心,地价越贵,楼盖得越高、越密;越往外,建筑越矮、越稀疏。这种“市中心高、郊区低”的分布,可以用指数衰减函数来刻画。此外,“功能区分布”——商业中心、住宅区、工业区、绿地——也会显著影响布局,程序可以按功能给不同区域配置不同的高度与风格参数。地标建筑则作为密度曲线上的“异常高值”被单独强调,成为城市的天际线焦点。

有了这张“密度地图”,小明的城市不再是呆板的方格阵——市中心高楼林立,越往外越像温柔的郊区。一座城市的气质,从确定密度函数那一刻起就已经注定了。

ρ(r)=ρ0 e−r/λ\displaystyle \rho(r) = \rho_0 \, e^{-r/\lambda}
离市中心距离为 r 的地方,建筑密度 ρ(r) 从市中心最大值 ρ₀ 开始指数衰减。λ 决定城市“摊多大饼”。
  1. 中心密度 ρ₀市中心(r=0)处的建筑密度,是所有密度的最大值。
    ρ0\rho_0
  2. 距离 r地块到市中心的直线距离,越远密度越低。
    rr
  3. 衰减尺度 λ控制密度下降快慢的“软尺”,λ 越大,城市蔓延得越远。
    λ\lambda
  4. 指数衰减密度随距离指数下降,模拟“地价从中心向外跳水”的规律。
    e−r/λe^{-r/\lambda}

生成管线:一条从地皮到细节的流水线

搭一座城市不能“先盖 100 楼的第 50 层”。小明总结出一条流水线:先铺地基,再修路,再切地皮、盖楼,最后挂窗帘——每一步都站在上一步的肩膀上。

这条流水线在工程上叫“生成管线(Generation Pipeline)”。典型顺序是:地形生成 → 道路生成 → 地块划分 → 建筑生成 → 细节装饰。地形生成用 Perlin 噪声(还记得那块“大理石”吗?)叠出起伏的山丘与盆地,坡度太陡的地方没法修路;道路生成顺着低洼平缓处延伸,围出街块;地块划分把街块切成单元;建筑生成按密度与功能在单元上“长楼”;最后用窗户、路灯、植被等细节让城市活起来。

地形生成是这条管线“地基中的地基”,而它最常用的数学工具正是多层噪声叠加——把不同频率、不同振幅的噪声叠在一起:低频大振幅负责“大起大落”的山脉,高频小振幅负责“坑坑洼洼”的碎石。这样生成的地形既有大尺度轮廓,又有小尺度细节。关键还在于,每层噪声都由同一个种子驱动,所以只要拿住种子,整条管线就能在任何机器上复现同一座城。

流水线就像小明的“盖城总装车间”:地形是地基,道路是骨架,建筑是血肉,细节是妆容。而种子就是贯穿车间的主传送带——只要调整它,整条流水线就会为小明换出一座全新的城。

H(x, y)=∑i=1kAi⋅N(fi x, fi y)\displaystyle H(x,\,y) = \sum_{i=1}^{k} A_i \cdot N\big(f_i\,x,\,f_i\,y\big)
最终高度 H(x,y) 等于 k 层 Perlin 噪声按振幅 Aᵢ 加权求和的结果:低频出轮廓,高频添细节。
  1. 高度值 H(x,y)坐标 (x,y) 处最终的地形高度。
    H(x,y)H(x,y)
  2. 第 i 层噪声N 是基础 Perlin 噪声,输入坐标会被频率 fᵢ 缩放。
    N(fi x, fi y)N(f_i\,x,\,f_i\,y)
  3. 振幅 Aᵢ第 i 层噪声的权重,控制它对最终高度的贡献大小。
    AiA_i
  4. 叠加求和把 k 层噪声按权重相加,层数越多,地形越有细节。
    ∑i=1kAi⋅(⋯ )\sum_{i=1}^{k} A_i \cdot (\cdots)

性能优化:让城市跑得动,而不是卡成 PPT

城市是长出来了,可小明的乐高小机器人一进市中心就卡成 PPT。他这才发现:生成一座城是一回事,让它“跑得动”是另一回事。

程序化生成的城市动辄几十万栋建筑,如果每栋都按最高精度渲染,任何显卡都会当场崩溃。第一个优化手段是 LOD(多细节层次):离得远的楼用几十个面的“粗积木”,离得近的用几千个面的“精密积木”。第二个是 GPU 实例化(Instancing):同款楼有 100 栋,没必要让 CPU 提交 100 次绘制命令——把 100 栋合成一次“批量倒模”,一次提交全部画完。

第三个是流式加载(Streaming):城市太大,没必要一口气全加载进内存,玩家走到哪就生成并加载哪一块,离开就卸载。第四个是空间哈希(Spatial Hashing):当程序需要查询“这栋楼旁边有什么”时,与其遍历全城,不如按网格把建筑分桶存放,直接查桶号。这四个手段组合起来,几十万栋楼也能在普通显卡上流畅运行。它们的核心收益可以用一个简单的公式理解:把渲染总耗时拆成不同精细度建筑的耗时之和,LOD 通过减少高精度建筑数量来压减总耗时。

小明的城市终于不再卡壳了——远处是憨憨的粗积木剪影,近处是精致的门窗细节,路过哪块就现场拼哪块。优化不是偷懒,而是把宝贵的算力花在玩家真正看得见的地方。

T≈NH tH+NM tM+NL tL\displaystyle T \approx N_H\, t_H + N_M\, t_M + N_L\, t_L
渲染一帧的总时间 T,约等于高、中、低三档精度建筑的数量分别乘以各自单栋耗时之和。优化就是压低那头最重的“大象”。
  1. 总耗时 T渲染一帧画面的总 GPU/CPU 时间,越小越流畅。
    TT
  2. 高精度部分近距离高模建筑数量 N_H 乘以每栋耗时 t_H,是开销大头。
    NH tHN_H\, t_H
  3. 中低精度部分中距与远距建筑分别对应 N_M、t_M 和 N_L、t_L,单体成本低。
    NM tM+NL tLN_M\, t_M + N_L\, t_L
  4. 近似求和总耗时约等于三档耗时之和,控制大头(高模数量)是关键。
    T≈(⋯ )T \approx (\cdots)

实战应用:AI 建筑师登场,城市自己进化

到这一步,小明已经是个熟练的“规则设计师”。但他很快遇到新问题:他想做一座“有 1930 年代上海风情”的城,却说不清风情到底由哪些规则组成。这时候,AI 建筑师登场了。

AI 驱动的做法是:给算法大量真实城市照片或街区地图,让它自己学习“上海风格”背后的几何规律,再把这些规律变成生成参数或约束条件。现代工具已经开始用深度生成模型(如扩散模型、GAN)直接产出街景贴图或建筑体块,再用传统 PCG 规则去约束结构与布局。传统方法负责“讲规矩”,AI 负责“提供灵感”,两者正在融合。

在工程实践中,衡量 WFC 这类约束求解器状态有个常用指标——熵。熵越高,说明格子处于“什么都有可能”的不确定状态越多,冲突风险越大;求解器每一步都优先坍缩熵最低的格子,就像数独高手先填“可能性最少”的那一格。这套价值观在实战里同样重要:先做路网主干,再填街区;先锚定地标,再铺普通楼。

小明的“AI 建筑师”看完十万张老照片后,交出的生成参数让整座城瞬间有了旧时光的味道。传统规则负责说“不许这样”,AI 负责说“试试那样”。程序化城市,正在从“写死规则”走向“学会风格”。

S=−∑ipi log⁡2pi\displaystyle S = - \sum_{i} p_i \, \log_2 p_i
熵 S 衡量一个格子有多“不确定”:可能的选择越多、概率越平均,熵越高;WFC 总是先处理熵最低的格子。
  1. 概率 pᵢ某一格子选择第 i 种瓦片或建筑类型的概率。
    pip_i
  2. 信息量−log₂ pᵢ 表示“这个选择带来多少信息量”,概率越小信息越大。
    −log⁡2pi-\log_2 p_i
  3. 期望求和对所有可能类型求和,得到该格子的平均不确定度。
    ∑ipi (−log⁡2pi)\sum_i p_i\, (-\log_2 p_i)
  4. 取负号保证熵为非负值,熵越高越不确定,越低越接近确定答案。
    S=−∑ipilog⁡2piS = - \sum_i p_i \log_2 p_i

AI 应用场景

场景一:开放世界游戏的城市自动生成

阶段:内容生成 / 关卡搭建

解决的问题:手搓一座 5 公里见方的现代都市,传统美术团队要数月;PCG 用路网、密度函数和 Shape Grammar 在几小时内生成,再叠加 AI 后处理去重、补细节。

具体案例:某开放世界项目先用 Perlin 噪声生成地形,再用网格路网切街区,最后用 Shape Grammar 批量长出写字楼与住宅。QA 只需检查路网是否连通、建筑是否穿模,而不是一栋栋地审。

场景二:智慧城市数字孪生

阶段:仿真数据准备

解决的问题:城市交通、排水仿真需要“足够像真的”的街区网络,真实数据又涉及隐私。PCG 可以按真实城市的统计规律生成同等规模的“替身”城市。

具体案例:研究团队以目标城市的路网密度、人口热力分布作为密度函数 ρ(r) 的参数,生成一万个虚拟街区做交通流仿真,评估“地铁改线后早高峰会怎样”。

场景三:影视与动画的背景城市

阶段:美术资产管线

解决的问题:电影需要一座“未来感但又不认识的都市”,纯手搭成本太高,纯随机又不可控。

具体案例:概念团队以手工设计的少量建筑“瓦片”为原料,用 WFC 自动铺满整个远景,再让 AI 生成贴图并做风格迁移,只保留近处几栋手工精修楼。

Python 演示

python76 行
import random  class CityGenerator:    """用种子驱动的程序化城市生成器, 对应文章中的生成管线"""     def __init__(self, seed=42):        self.seed = seed        self.rng = random.Random(seed)        self.size_x = 60        self.size_y = 40        self.grid_map = [[0 for _ in range(self.size_x)] for _ in range(self.size_y)]        self.buildings_list = []     def generate(self):        self._paint_water()        self._lay_roads()        self._sow_parks()        self._rise_buildings()        return self.grid_map     def _paint_water(self):        # 在右下角画一个圆形湖泊, 模拟地形约束        for y in range(self.size_y):            for x in range(self.size_x):                d = ((x - 48) ** 2 + (y - 6) ** 2) ** 0.5                if d < 9:                    self.grid_map[y][x] = -1     def _lay_roads(self):        # 每隔 6 格画一条南北向主干道        for i in range(0, self.size_x, 6):            for y in range(self.size_y):                if self.grid_map[y][i] == 0:                    self.grid_map[y][i] = 1        # 每隔 6 格画一条东西向主干道        for i in range(0, self.size_y, 6):            for x in range(self.size_x):                if self.grid_map[i][x] == 0:                    self.grid_map[i][x] = 1     def _sow_parks(self):        # 剩余空地上以 6% 概率生成公园, 对应功能区分布        for y in range(self.size_y):            for x in range(self.size_x):                if self.grid_map[y][x] == 0 and self.rng.random() < 0.06:                    self.grid_map[y][x] = 2     def _rise_buildings(self):        # 按概率区间生成低层/高层/地标, 对应建筑生成        for y in range(self.size_y):            for x in range(self.size_x):                if self.grid_map[y][x] == 0:                    v = self.rng.random()                    if v < 0.55:                        self.grid_map[y][x] = 3                    elif v < 0.82:                        self.grid_map[y][x] = 4                    else:                        self.grid_map[y][x] = 5                    self.buildings_list.append((x, y))     def render(self):        symbols = {-1: '~~', 0: '..', 1: '==', 2: '##', 3: '[]', 4: 'HH', 5: 'TT'}        lines = []        for row in self.grid_map:            lines.append(''.join(symbols[c] for c in row))        return '\n'.join(lines)  if __name__ == '__main__':    city = CityGenerator(seed=2024)    city.generate()    count = sum(1 for row in city.grid_map for c in row if c >= 3)    print('生成建筑地块数: %d' % count)    print(city.render())
目的:用一个 60×40 的数字网格复现“地形→道路→公园→建筑”的微型生成管线,展示种子如何让一座字符城市稳定复现。
  1. self.rng = random.Random(seed)用固定种子创建可复现的随机源,同一颗种子永远长出同一座城。
  2. self.grid_map = [[0 for _ in range(self.size_x)] for _ in range(self.size_y)]一张二维地图,0 代表未开发空地。
  3. d = ((x - 48) ** 2 + (y - 6) ** 2) ** 0.5计算地块到“湖心”的距离,模拟地形约束。
  4. if d < 9: self.grid_map[y][x] = -1距离小于 9 的格子变成水域,道路会绕开它。
  5. for i in range(0, self.size_x, 6):每隔 6 格画一条南北向主干道。
  6. if self.grid_map[y][i] == 0: self.grid_map[y][i] = 1只在空地上铺路,避免马路穿湖。
  7. if self.grid_map[y][x] == 0 and self.rng.random() < 0.06:空地上以 6% 概率长出公园。
  8. v = self.rng.random()每块空地掷一次骰子,按区间分配建筑类型。
  9. symbols = {-1: '~~', 0: '..', 1: '==', 2: '##', 3: '[]', 4: 'HH', 5: 'TT'}把数字地图翻译成一眼能看懂的字符图例。
  10. if __name__ == '__main__':只有直接运行时才生成并打印,被 import 时不触发。

常见误区

误区程序化生成不就是随机扔骰子吗?反正结果都是碰运气,多跑几次总能跑出一座好城市。

正解程序化生成的核心是“规则 + 种子”:随机只是规则允许范围内的随机,种子保证结果可复现。就像乐高说明书:虽然每步都有几种选择,但选择范围和顺序全是写死的。换种子只是换了“选择答案的起点”,并没有换一本说明书。

为何常见:初学者看到每次结果不同,误以为本质是随机;实际上“可复现的随机”和“听天由命的随机”是两回事。

误区机器能自动生成城市,美术师是不是要失业了?以后只要调调参数就行了吧。

正解PCG 自动化的是“组合与布局”,而建筑贴图、基础模型、风格设定仍然需要美术手工制作——它们就是乐高零件箱里的“积木”。没有好零件,规则再强也只能拼出千篇一律的方块。地标建筑、剧情关键场景也往往要手工精修,PCG 之后再叠加人工打磨。

为何常见:过度神化“全自动”概念,忽略了任何生成系统都建立在资产与规则的质量之上。

误区写好算法点一下按钮,整座城市就该瞬间出现,这才配叫程序化生成。

正解真实工程里城市是“管线”逐步产出的:地形→道路→地块→建筑→细节,每一步都可能失败或需要回炉。复杂场景生成要数秒到数分钟,而且普遍采用流式加载、分块生成,而不是一次性算完。演示视频里的“瞬间长成”其实是快进效果。

为何常见:把精心剪辑的演示视频当成了真实耗时。

误区WFC 要反复试错找冲突,规模一大就卡死,根本没法用于整座城市。

正解WFC 的瓶颈可以通过三类手段控制:优先坍缩低熵格子减少回溯、把瓦片组合预计算成查表、增量式更新只重算受影响区域。配合分块生成,WFC 完全可以用于大规模关卡与城市街区。

为何常见:只盯着朴素实现的最坏情况,没了解约束传播和工程优化手段。

面试题

Q1. 在程序化生成中,种子(seed)最主要的用途是什么?

单选题 · easy

  • A.决定生成的唯一确定性起点← 正确答案
  • B.加快计算机的运算速度
  • C.提高画面的分辨率质量
  • D.替代所有美术资源文件

答案:A。种子是生成流程的“唯一确定性起点”:同一算法加同一种子必然得到同一结果,换种子得到新变体。就像换一块乐高起始积木,并不会让说明书跑得更快或画质更好。B、C、D 分别混淆了性能、画质与资产替代,都不是种子的职责。

Q2. L系统(L-system)最擅长生成下列哪类结构?

单选题 · mid

  • A.递归生长的分支结构← 正确答案
  • B.完全等距的网格道路
  • C.均匀分布的单色纹理
  • D.固定不变的手工模型

答案:A。L 系统通过替换规则递归生成分支结构,天生适合树冠、枝干、藤蔓乃至哥特式飞扶壁。网格道路是布局算法的任务,单色纹理通常用噪声,手工模型则与程序化生成相对。选项 A 正是“枝上生枝”的那本说明书。

Q3. Perlin噪声相比纯随机数的关键优势是什么?

单选题 · mid

  • A.数值连续平滑且自然← 正确答案
  • B.数值完全不可预测
  • C.计算速度一定更快
  • D.不需要任何外部种子

答案:A。Perlin 噪声的核心价值是“连续平滑”:相邻位置的取值变化自然,适合模拟地形起伏。B 描述的是随机数,C 的速度优势并不绝对,D 说反了——噪声同样依赖种子。就像大理石纹理,平滑连续才像自然,纸屑般乱跳只能是噪声。

Q4. 波形函数坍缩(WFC)算法的核心思想更接近什么?

单选题 · hard

  • A.用约束传播解决冲突← 正确答案
  • B.用暴力枚举穷举所有
  • C.用随机数独立决定格
  • D.用固定模板复制粘贴

答案:A。WFC 的精髓是“约束传播加低熵优先”:每个格子先处于多种可能,再按邻居约束逐步坍缩,像数独高手先填可能性最少的格。暴力枚举、独立随机、固定模板都没有利用邻接约束,因此都不是它的核心思想。

Q5. 程序化城市生成管线中,第一步通常是?

单选题 · easy

  • A.生成地形起伏基础← 正确答案
  • B.直接放置高楼大厦
  • C.绘制室内家具装饰
  • D.编写完整的剧情线

答案:A。生成管线的顺序是“地形→道路→地块→建筑→细节”。地形是地基,道路要顺着平缓地形走,建筑要落在地块里。先放高楼、先摆家具、先写剧情都违背了这条依赖链。就像搭乐高城市,先有底板,才有马路和楼房。

Q6. 提升城市场景渲染性能的常用手段包括?

多选题 · mid

  • A.远处建筑使用低模← 正确答案
  • B.相同模型批量绘制← 正确答案
  • C.边游玩边流式加载← 正确答案
  • D.加载全部高清贴图

答案:ABC。LOD(远处低模)、GPU 实例化(同款批量绘制)、流式加载(边走边加载)都是标准优化手段。D 是反面选项:一次性加载全部高清贴图会瞬间耗尽显存,正是优化要避免的做法。

Q7. Shape Grammar中“替换规则”的含义是什么?

单选题 · mid

  • A.用子形状替换父形状← 正确答案
  • B.直接删除所有形状
  • C.随机改变颜色数值
  • D.把二维投影成三维

答案:A。Shape Grammar 通过“用子形状替换父形状”不断细化结构,就像细胞分裂:楼体替换成墙加屋顶,墙再替换成一排砖。删除形状、改颜色、投影变换都与“细化结构”无关。

Q8. 影响城市布局密度分布的因素包括?

多选题 · hard

  • A.到城市中心的距离← 正确答案
  • B.道路网络的连通性← 正确答案
  • C.地形起伏的限制← 正确答案
  • D.渲染引擎的版本号

答案:ABC。中心距离决定密度衰减(ρ(r)公式),道路连通性决定地块的可达性,地形坡度决定哪里能盖房。渲染引擎版本只影响呈现效率,不改变城市布局的几何规律。

Q9. 同样的算法和种子,生成结果通常?

单选题 · easy

  • A.完全一致可复现← 正确答案
  • B.每次都完全不同
  • C.仅颜色发生变化
  • D.结果完全无法预测

答案:A。种子加规则确定后,生成结果是完全确定、可复现的。这正是 PCG 可调试、可验收的基石——如果每次都不同,QA 将无从下手。C 和 D 都否定了确定性,B 则是把“换种子”和“同种子”混为一谈。

Q10. LOD(多细节层次)技术的主要做法是什么?

单选题 · mid

  • A.按距离切换模型精度← 正确答案
  • B.提高贴图的饱和度
  • C.降低游戏的运行帧率
  • D.增加场景的灯光数量

答案:A。LOD 按物体与摄像机的距离切换精度:近处用高模、远处用低模,从而压减公式 T 中最重的 N_H·t_H 项。提高饱和度、降低帧率、增加灯光都与“多细节层次”无关,反而可能拖慢性能。