购买课程
诗贯山河在做什么:从一帧画面拆到一整条产线

诗贯山河在做什么:从一帧画面拆到一整条产线

免费试读 · 约 22 分钟阅读

我们要做的不是「能跑的 Demo」,而是一条能稳定产出短视频素材的内容产线。

这一节我们不急着打开代码。先做一件更重要的事:拿诗贯山河的一帧画面,把它拆成工程结构。很多视觉项目之所以后期失控,是因为开发者一开始按「画面元素」拆:山是一块,水是一块,诗词是一块,按钮是一块。这样拆很直观,但不适合维护。

真正适合工程的拆法,是按「生产关系」拆:哪些东西是离线生产出来的,哪些东西是运行时加载的,哪些东西每帧都在更新,哪些东西只是最终交付时才需要。这个视角一换,你会发现诗贯山河不是一个页面,而是一条从地图资产到短视频画面的流水线。

先看用户看到的一帧

用户看到的画面大概是这样的:一个固定 4:5 竖屏画幅,中央是一张带起伏的中国古风地形,河流有轻微水色,某些点位附近会出现雨雪烟气,点击诗词点位后镜头飞过去,诗文卡片淡入,背景可能配合鸟鸣、风声或水声。

如果你是第一次做,可能会直接问:这个山怎么画?这个粒子怎么做?这个卡片怎么写 CSS?这些问题都对,但顺序不对。我们应该先问:这些画面元素分别由什么数据驱动?它们的生命周期是什么?它们要不要跨区域复用?

第一条线:地图不是背景图

最容易低估的是地图。很多人会把地图当成一张大背景图,觉得只要找一张好看的水墨中国地图铺上去就行。但诗贯山河里的地图至少包含四类信息:视觉底图、高程数据、水体遮罩、坐标 bounds。它们看起来像一张图,工程上却是四种不同职责。

  • 视觉底图负责第一眼的风格,比如纸感、墨色、地貌明暗。
  • 高程数据负责山体起伏,后面会进入 shader 影响顶点或法线。
  • 水体遮罩负责告诉材质哪里是河流、湖泊、海岸线。
  • bounds 负责把真实坐标映射到 Three.js 平面,不记录它就无法稳定放点。

所以地图不是一张图片,而是一个资产包。你后面要新增四川、陕西、洛阳,真正复用的不是图片,而是这套资产包规范。

第二条线:诗词不是文案

诗词也不能只当展示文案。它在系统里至少承担四个角色:卡片内容、地图点位、镜头目标、氛围触发器。比如同一首诗可以决定卡片里显示什么,也可以决定相机飞向哪里,还可以决定这一段镜头要不要叠加细雨或风声。

这就是为什么诗词数据必须结构化。title、author、dynasty、body 只是最表层;location、region、tags、effectCue、audioCue 才决定它能不能进入产线。如果只把诗写成一段字符串,后面所有交互都会变成硬编码。

第三条线:特效不是越多越好

雨、雪、风、沙、烟、瀑布听起来是六种效果,但底层都要解决同一批问题:在哪里出现、出现多大范围、强度多少、持续多久、是否跟随镜头、是否参与性能预算。你不能为每种效果单独发明一套参数,否则调试会非常痛苦。

更好的抽象是局部 Volume。Volume 是一个影响区域,它不关心自己最后表现成雨还是雪,只描述位置、半径、高度、强度、时间和随机种子。具体效果再消费这套配置。这样做的好处是:数据层可以统一管理特效点位,渲染层可以统一调度生命周期。

第四条线:镜头不是动画装饰

点击点位后镜头飞过去,看起来只是一个动画,但它其实是叙事结构。镜头从全局地图出发,飞向某个地点,最后停在一个适合阅读诗词卡片的构图上。这个过程里,相机位置、观察点、FOV、速度曲线、卡片入场、音频 cue 都要配合。

如果你只是 tween camera.position,会得到一个机械移动的镜头;如果你把相机看成一个状态机,区分 idle、flying、focused、returning,就能在不同阶段安排不同的 UI、特效和声音。这就是从动画思维到导演思维的差别。

第五条线:交付约束要提前进入设计

诗贯山河不是只在浏览器里给人随便点点,它还要服务短视频素材生产。所以 4:5 画幅不是最后导出时再裁一下,而是一开始就影响构图:地形主体放哪里,诗词卡片放哪里,点位密度多少,镜头结束时哪里留白,按钮和调试面板发布时如何隐藏。

很多项目做完才发现录屏不好看,就是因为交付约束来得太晚。工程上应该反过来:先确定最终画幅、目标平台、性能底线,再倒推场景、卡片、镜头和特效。

把这五条线串成产线

  1. 离线阶段:用 QGIS / GDAL 生成地图资产包,整理诗词与古地名数据。
  2. 加载阶段:前端按区域加载纹理、遮罩、高程、音频和结构化 JSON。
  3. 渲染阶段:Three.js 根据资产和数据创建地形、水体、点位、局部特效。
  4. 交互阶段:用户点击点位,镜头状态机、诗词卡片、音频和特效联动。
  5. 交付阶段:按 4:5 画幅录屏或上线访问,统计数据用于判断后续迭代。

为什么这套拆法很重要

因为它直接决定了后续扩展成本。如果地图资产包规范是稳定的,新增区域就是重复生产资产;如果诗词数据结构是稳定的,新增内容就是填表;如果 Volume 抽象是稳定的,新增天气只是多一种 renderer;如果镜头状态机是稳定的,新增交互就不会破坏已有节奏。

反过来,如果这些边界没立住,项目会变成一堆互相知道对方细节的代码:诗词数据里写材质参数,镜头动画里写 DOM 选择器,shader 里假设某张贴图尺寸,部署脚本里手动列文件名。它也许能上线,但每次迭代都像拆炸弹。

工程四象限

  • 场景层:负责 Three.js scene、camera、renderer、后期处理和主循环。
  • 资产层:负责地图贴图、GLB、音频、遮罩、高程等文件的命名、加载和缓存。
  • 数据层:负责诗词、古地名、区域、特效点位、镜头目标等结构化内容。
  • 运营层:负责竖屏画幅、统计埋点、发布脚本、OSS 上传和线上稳定性。

这门课的完整知识地图

下面这张图是课程结构。你可以把它当成一张工程地图:第一章建立全景,第二章解决地图资产,第三章解决内容数据,第四章解决局部特效,后面再进入镜头、音频、发布和运营。

读完这一节你应该能判断什么

  • 一个视觉项目什么时候只是 Demo,什么时候已经需要资产管线。
  • 哪些信息应该离线生产,哪些信息应该运行时计算。
  • 为什么点位、镜头、特效都应该由数据驱动。
  • 为什么画幅、录屏、部署这些交付问题要提前进入架构。
这节是整个课程的总索引。后面每一章都在展开这里的一条线:地图资产、内容数据、实时渲染、交互叙事、发布交付。