TravelingHouston

RPT · 任务报告 · DIGITAL WONDERS 出品

Traveling Houston 诞生记。

一份从月球开始的休斯顿 3D 城市指南。这是它的任务报告:创意从何而来,坠落和城市如何做成,实时数据与声音,十四个游戏,底层的工程,以及一次冷眼评审之后改了什么。

  • 138个地点,逐一核实
  • 14份 Top 10 指南
  • 77场活动
  • 130个站点按地图重建
  • 84,090栋建筑来自 OpenStreetMap
  • 155首原创歌曲
  • 14个游戏,技术绝不重复
  • 1个 WebGL 画布

§ 011969年7月20日 · 102:45:58 GET

一个词, 开启了一切。

鹰号在静海着陆时,巴兹·奥尔德林报出“Contact light”(接触灯亮),机组随即执行关机程序。接着,尼尔·阿姆斯特朗发出了全世界都在等待的那条消息,而它的第一个词是一座城市的名字:“休斯顿,这里是静海基地。鹰已着陆。”

所以,这份指南就从那句话开始的地方开始:在登月舱的舱内,离家238,900英里。你向下滚动,便一路坠落回家:穿过黑暗,进入墨西哥湾上空的黎明,再落进一座用开放地图数据搭建的休斯顿。从那一刻起,镜头再也不停止飞行。每份指南都是一份飞行计划,每个地点都是镜头真正飞抵的航点,就在它自己的经纬度上,每一次翻页都是一次横跨城市的飞行。

在写下第一行引擎代码之前,计划书就点明了这个网站必须证明的两件事:它是网上最有用的休斯顿指南;而且,别人都做不出来。下面的一切,都是为了其中之一。

§ 02降落 · 238,900英里到0英尺

从月球 坠落。

开场的“降落”从鹰号的舱内开始,舱室依据 Grumman《LM News Reference》中的尺寸为本站打造:两扇向下倾斜、望向月面平原的三角窗,仪表板和断路器,显示 P68 程序和着陆点坐标的 DSKY,以及停在102:45:58的任务计时器,正是那句呼叫的时刻。镜头从指令长一侧的窗户飞出,绕着平原上的登月舱盘旋。

舱外的下降级是 NASA 自己的公有领域阿波罗登月舱模型,来自 NASA 3D Resources,精简到62,000个三角形、789 KB,并在这里重新处理了表面:用 3D Voronoi 凹凸做出皱褶的琥珀色和黑色 Kapton 箔,阳极氧化铝,阳光下月面的反光,一圈地球反照光勾出的轮廓。装着舱室的上升级被重建成一块块拼接的面板,起飞时它把下降级留在月球上,正如当年。

地球是 NASA 的影像:白天一侧用 Blue Marble Next Generation,灯光用 Black Marble,再加上 NASA 的云层,桌面端宽4,096像素,手机上2,048像素。逼近得州时,一块取自全分辨率 Blue Marble 的2,048 × 1,536影像,每像素500米,在墨西哥湾上空渐渐融入。太阳在它该在的位置:休斯顿正值黎明,西海岸仍在黑暗中。影像在主线程之外解码,每帧只上传一张纹理,所以坠落从不会因此卡顿。

到了再入界面,400,000英尺,无线电像当年对乘组那样中断,空气燃起光芒;低于100英里后,仪表改用英尺读数。再往下,地面是一张照片:USDA 国家农业影像计划(National Agriculture Imagery Program)的航空影像,在120公里范围内拼接、调色并融入 Blue Marble,中间30公里用的是更清晰的测绘影像。海岸线依据该地区的地图数据描出,并以距离场保存,所以在任何高度都保持平滑;云层和云影会一直保留,直到你降到15,000英尺以下。

登月舱舱内:倾斜的窗户外是灰色的月面,仪表板上排列着圆形仪表,还有一个绿色的任务计时器。
图 2.1 鹰号的舱室,为本站打造。“降落”就从这里的第一帧开始。
登月舱立在月球上:灰色面板拼成的上升级,下面是包裹着皱褶金色箔片的下降级,长长的影子投在平原上。
图 2.2 NASA 的登月舱,重新处理了表面:Kapton 箔、铝材、一圈地球反照光。
黑色太空中的地球,美洲位于白天一侧,云带横陈,晨昏线穿过墨西哥湾。
图 2.3 回家路上的 NASA Blue Marble 和 Black Marble:晨昏线上的黎明,正落在休斯顿上空。
早晨从高空望去的 Galveston Bay,远处的休斯顿地区像一幅由田野、城镇和河湾拼成的照片。
图 2.4 飞越 Galveston Bay 进场:城市下方是 USDA 航空影像。页面上这一段在日出前飞过;这里展示的是早晨。

§ 03世界 · 29.7604° N 95.3698° W

一座城市, 用它自己的地图搭建。

这里的休斯顿就是 OpenStreetMap:75,839个建筑轮廓,遍布 Downtown、Midtown 和 Museum District、Medical Center、Montrose、Uptown、EaDo 和各体育场、Space Center、San Jacinto 以及 Kemah。地图上记录了高度的建筑,按记录的高度抬升(有1,842栋有记录,高楼都在其中);没有记录的,按建筑类型给出高度。高速公路上跑着22,000盏车灯,一个方向白、另一个方向红(手机上7,000盏),河湾、Ship Channel 和 Galveston Bay 也来自同一份数据。

每栋建筑都按轮廓和高度分类(住宅、棚屋、商业楼),再用一套六色调的休斯顿调色板上色:屋顶更深,带屋顶设备,高于12米的建筑都有窗格,幕墙玻璃有蓝灰、古铜、绿色和银色。到了夜里,窗户会亮起来。地标是依据公开尺寸搭建的模型:San Jacinto Monument、展厅里的土星五号、背在747上的航天飞机、Astrodome,还有开着顶棚、带着小火车的 Daikin Park。

然后是站点。除了 Space Center、Daikin Park 和 Bellaire Boulevard 上那五个各有专属模型的地点,指南里的每个地点都会在镜头飞来时,用 OpenStreetMap 重建自己所在的街区:130套场景,8,251栋建筑,立在真实的轮廓上,盖着真实的屋顶。立面按用途和材质生成,朝向地址所在街道的那面墙上有橱窗玻璃和一扇门,招牌上是这个地点的真名,邻居的招牌上是地图记录的它们的名字;街道画着标线,停车场画着车位、停着车,门外还有这类地方该有的东西:烤炉和野餐桌、串灯、露台。有十二个地点配了专门定制的物件。

Bellaire Boulevard 有一条专属的街道,从 Kirkwood 到 Gessner:双向车道和种着橡树的中央隔离带,拖着光轨的车流,每栋商业建筑都是一排亮灯的临街商铺,招牌按地图上的租户名写就,十二座购物中心的立柱招牌,信号灯杆上的路牌在 Beltway 以西是英文和越南文,以东是英文和中文,Hong Kong City Mall 的牌坊和灯笼,Vietnam War Memorial 和 Teo Chew Temple。

正午的 Downtown Houston 哑光黏土模型:高楼是浅色方块,投下硬朗的阴影,低矮的建筑一直铺到地平线。
图 3.1 黏土模式下的城市(任意页面加上 ?view=clay):套上外观之前的地图数据。
同一视角下黄金时刻的 Downtown Houston:高楼被照成琥珀色,下方是街道和高速公路,角落里是 Daikin Park,远处是绿色的土地。
图 3.2 同一个镜头,完成版:调色板、玻璃、窗户和航拍地面,黄金时刻。
The Breakfast Klub 在自己的街区重建:一栋矮楼,招牌带上写着店名,门前露台撑着遮阳伞,前景是画着车位线的停车场和街道。
图 3.3 一套站点场景:The Breakfast Klub 在自己的街区,有招牌、露台和停车场。
黄昏时沿 Bellaire Boulevard 望去:两侧车道上红白光轨,两边是亮灯的商业街区和立柱招牌,太阳低悬在右侧。
图 3.4 黄昏的 Bellaire Boulevard,从 Corporate Drive 向西望去。

§ 04遥测 · 实时

休斯顿, 此时此刻。

页眉里的时钟是一个开关。打开它,指南精心设定的时刻就让位给真实的时刻:太阳位于此刻休斯顿上空它真正所在的位置,用 NOAA 的太阳位置公式在设备上算出;天气取自 National Weather Service 在 Bush Intercontinental 最近一次的观测,每十分钟发一个小请求。阴天时光线变灰、阴影变淡,起雾时视野收拢,下雨时雨丝划过镜头。

城市上空的飞机是真的。距 Downtown 60海里以内的每一架(进出 IAH 和 Hobby 的航班、Medical Center 上空的直升机、40,000英尺高空飞过的航班)都按照 adsb.lol 志愿者接收站收到的广播位置、高度和航迹飞行,每十秒更新一次,其间用航位推算补足,所以新的定位会平滑过渡,而不是跳一下。主机上一个小小的代理,不管有多少人在看,都只每十秒请求一次,把返回数据裁剪到渲染器要画的内容,并剔除参与 FAA 隐私计划的飞机。关于访客的任何信息都不会被发送出去。

Astros 的赛程每晚从 MLB 的 Stats API 获取。两个 Daikin Park 站点都会显示下一场主场比赛,只有第二次查询确认后才会称之为揭幕日;主场获胜后的第二天早上,球场上空的烟花会多放一轮,橙、蓝、白三色。

静态网站会冻结在构建的那一天,所以这个网站每天都重新构建:在休斯顿时间黎明前重新导出并发布;活动信息屏和首页的“接下来六场”会在浏览器里重新核对日期,构建之后已经结束的活动会自动让位。网站上没有任何日期是手写的。

Downtown Houston 笼罩在灰色的阴天下,雨丝斜划过画面,高楼在雾气中变得朦胧。
图 4.1 实时天空的雨,为这张图强制开启。在网站上,只有机场报告下雨时才会下。
夜里从本垒上方望向 Daikin Park:开着的顶棚下,球场亮着绿色的灯光,金色烟花在体育场上空绽放。
图 4.2 Daikin Park 站点上空的烟花,主场获胜后多放一轮。

§ 05音频 · 9个电台加档案馆

一台收音机, 跟着地图调频。

Digital Wonders 为本站写了155首原创歌曲,用 Suno 和 Mureka 制作,分布在9个电台:honky-tonk 和 western swing,Tejano cumbia 和 conjunto,Frenchtown 的 zydeco,Third Ward 的福音和布鲁斯,慢放切碎的 H-Town 说唱,越南城市流行,Afrobeats 和 bhangra,墨西哥湾沿岸的游艇摇滚,Montrose 的爵士和迪斯科。歌词写的都是指南里的真实地点,大多数地点都有一首自己的歌,镜头抵达时响起。另有一个频道播放7张1916年至1924年的公有领域唱片。

调频盘跟着镜头走。某个站点的标记亮起时,收音机会转到这个站点所属的电台;有自己歌曲的站点,会从第一段副歌切入。每首歌都是电台剪辑版,从第一句歌词之前一点开始,到最后一句之后一点结束,按对齐歌词中的时间点剪切,母带处理到−16 LUFS。每份指南都有自己的歌单,同一份歌单里没有一首歌会放两遍。

音乐之下,是阿波罗的真实声音:6段来自 Wikimedia Commons 的 NASA 录音,夹在 quindar 提示音之间(“鹰已着陆”、第一步、返航途中的阿波罗8号);还有一层在 Web Audio 中实时合成的环境声,跟随镜头的时刻和速度变化:轨道上的无线电嘶嘶声,只有你真的在移动时才有的风声,白天的车流和鸟鸣,黄昏的蝉,夜里的蟋蟀。声音会等你第一次点击才响起。输错网址,就会落到漂流中的阿波罗13号,循环播放真实的“休斯顿,我们出了个问题”,总共只有45 kB。

404页面:标题“休斯顿,我们有麻烦了”,下方是对接着登月舱的阿波罗13号指令舱模型,漂浮在太空中,身后是小小的地球,再往下是飞行通话记录。
图 5.1 404页面:漂流中的阿波罗13号,通话记录与 Flight Journal 所载一致。

§ 06互动玩法 · 每份指南一个

十四个游戏, 技术绝不重复。

每份指南都有同样诚实的骨架:在真实地图上飞抵的十个地点;外加一个只存在于那个页面的玩法。没有两个共用同一种技术,读指南不需要玩任何一个,而且每一个都能用键盘玩。在指南页面上,大多数是满版场景,边缘消融在城市之中,而不是装在盒子里摆在城市上面。

十四个互动玩法,每份指南一个,每个一种技术。
编号指南互动玩法技术
TTD玩什么让鹰号着陆月球重力对抗可调推力的下降发动机,六十秒燃料,登月舱的影子就是高度计
EAT餐厅护照从 Natural Earth 采样的点阵地球仪,从每种菜系的故乡划出大圆弧线,旋转带惯性
BBQ烧烤烟熏炉偏置式烟熏炉的钢材在着色器里逐渐做旧,指针反应滞后,超过275 °F烟就变白
TMX塔可与Tex-MexLoteríaHTML 和 CSS 3D,不是 WebGL:真实、可聚焦的卡牌,用浏览器自带语音念牌的西班牙语报牌人
SWT甜品冰淇淋叠叠乐一个叠放模型:每一次偏移都会加大倾斜,冰淇淋塔在弹簧上摇晃,直到倒下
BRN咖啡与早午餐拉花在半浮点渲染目标上运行的 GPU 稳定流体求解器:平流、涡度、二十次 Jacobi 迭代
BAR酒吧最后一轮从指针速度读取摇晃,钢制摇酒壶随降温结霜,酒吧的名字亮在霓虹灯里
MSC现场音乐与夜生活Chopped & Screwed一段离线渲染一次的节拍,按唱盘的真实转速播放;拖动它,把它拖慢到70%
FAM亲子家庭发射台在一座玩具地图般的休斯顿上空画出弹道弧线,地图取自这个世界自己的城市栅格
MUS博物馆博物馆区滚动驱动,走过十座展馆,每座取自其博物馆的建筑,不复制任何一幅画作
OUT公园与户外划过河湾真实的 Buffalo Bayou 中心线,黄昏的一艘皮划艇,一群用粒子模拟的犬吻蝠
SPT体育击球!击球练习速度下的时机游戏;打出深远球,火车就会驶过 Crawford Boxes
TRP一日游公路地图在真实地图的高速公路上求最短路径,车后拖着 GPS 轨迹,还有 Bolivar 渡轮
NBH街区环线滚动驱动的拉远镜头,依次穿过 I-610、Beltway 8 和 Grand Parkway,用的是城市自己的高速公路几何

自由飞行和404页面也算:一架无人机飞越整座城市,建筑是实体的(由屋顶栅格化出的高度网格),还有漂流中的阿波罗13号。

“烟熏炉”:夜里的一台偏置式烟熏炉,火箱发着红光,白烟从烟囱升起,温度表的指针远远越过了目标区间。
图 6.1 “烟熏炉”烧得太旺:超过275 °F,烟就变得又浓又白。
“Chopped & Screwed”:胡桃木底座上的一台唱机,唱片贴着紫色标签,有唱臂和推子,旁边显示转速和音高读数,并列出十家现场音乐场馆。
图 6.2 Chopped & Screwed:拖动唱片让它变慢,就像 DJ Screw 当年在南区做的那样。

任何视角都能变成纪念品。“明信片”按钮会把 3D 视图渲染成1,800 × 1,200,做成一张经典的“寄自某地”大字明信片:地名用粗大的字母写出,字里填满它自己的天际线,一行遥测口吻的说明文字,再加一个印着休斯顿日期和时间的邮戳。

§ 07系统 · 一个上下文

一个画布, 装下一切。

整个网站只有一个 WebGL 上下文。城市是背景视图;每个游戏都是绑定在页面某个矩形区域上的一个视图,用裁剪测试(scissor)画进同一个画布,所以纹理可以共享,也永远不会触及任何浏览器的上下文数量上限。满版的玩法都做了羽化:每帧把世界复制一次,再盖回它们的边缘上。

着色器在绘制任何新内容之前,就在主线程之外并行编译:你还在太空时编译城市,每套站点场景和每块瓦片在流式载入时编译。自适应分辨率读取两秒窗口的中位数,降到下限时,先牺牲阴影贴图的尺寸,再放弃泛光。three.js、GSAP 和 Lenis 从不进入首次加载;在它们到来之前,每个页面都已经是完整的 HTML。

最诡异的 bug,是 Downtown 一家酒吧 La Carafe 上方一个忽闪忽闪的黑块。罪魁祸首是一个不是数字的像素:在多重采样下,站点建筑的着色器把数值外推到了三角形边缘之外,泛光处理又把那一个 NaN 扩散成了一整块。现在,泛光之下插值的每个值都声明为 centroid,还有一个扫描器在全部130个站点逐一读取泛光的输入,查找任何不是有限数的值。

每个页面在没有 3D 层时都是完整的,3D 层只是装饰:画布对辅助技术隐藏,所有信息都是真实文本。开启减少动态效果后,镜头直接切换,不再飞行。axe-core 在桌面和手机尺寸下审查的页面上报告零违规;由于 axe 看不透 3D 场景,对比度直接在字形上逐帧测量,背景是移动中的城市。在320像素宽的手机上,没有任何内容被裁切或缩放。

整个网站是一个静态导出,放在普通的共享主机上:.htaccess 文件提供简洁的 URL,空中交通代理就是一个 PHP 文件,推送到 main 后大约一分钟上线,每次部署前都要跑一百多个单元测试(内容完整性、地图投影、“降落”的时钟、每个镜头、每个标题都能放进最小的手机)。

一张明信片,写着 Greetings from The Menil Collection,名称用粗大的字母写出,字里填满黄昏时 Montrose 的航拍景色,米色边框,休斯顿邮戳,以及带坐标的说明文字。
图 7.1 一张来自 Menil Collection 的明信片,就是按钮生成的样子。

§ 08评审 · 第二轮

冷眼评审, 然后重建。

网站上线后,我们自己做了一次冷眼评审,按设计评委的方式打分:设计、可用性、创意和内容。创意和内容最站得住。评审给出了二十项排好优先级的修改,以及一份必须保留的清单:舱内的开场、字体、太空中的地球、地点页面、Lotería、404页面。

它毫不客气地点出了最弱的画面,被重做的正是这些。进场原本落在一块平坦的橄榄色平面上,海岸线呈锯齿台阶状;现在它是第2节里的那张航拍照片,海岸线由距离场平滑,云层会在你下降时散开。登月舱原本是一摞盒子,燃料箱是一个金色的蛋;现在它是 NASA 自己的模型,重新处理了表面。城市原本是同一个米色盒子重复到底;现在它有了分类、配色、玻璃和灯光。

而且页面太长了。首页在桌面上从58屏缩到48屏(手机上从69屏缩到54屏),每份指南都短了约四分之一,站点导轨变成了跳转工具,J 和 K 键分别前往下一站和上一站,开场下方还安静地放着一个“跳过,直达休斯顿”。同一轮修改,也给每类页面配了专属的道具:活动页的实时翻牌信息屏,你的计划的登机牌,简报页的仪表铭牌,制作说明页的片尾字幕。

§ 09 · 制作名单

Digital Wonders 出品

得州休斯顿

创意、调研、设计、工程、声音和音乐:Digital Wonders。地图数据 © OpenStreetMap 贡献者(ODbL);影像来自 NASA 和 USDA;天气来自 NOAA 和 National Weather Service;飞机数据来自 adsb.lol(ODbL);阿波罗录音来自 NASA。所有来源和许可都列在制作说明中。

你有一个地方、一件产品或一个故事,值得拥有一个属于自己的世界吗?这正是我们做的事。

在 digitalwonders.tech 启动项目或者重新开始飞行