emissive 提到 0.8 仍然发黑:它乘的是本来就很暗的反照率,0.8 × 深绿约等于 sRGB [0.22, 0.31, 0.11],还是暗的。要提的是反照率本身。 Cesium 截图定位:草亮黄绿、建筑近白、路面浅灰,只有树暗。这棵树图集的叶片 本来就是深绿(绿色系像素均值 sRGB [0.249, 0.35, 0.12]),按真实反照率渲染 是对的,但场景里其他材质都被手工提亮过——EXPORT_TINTS 草 0.72、带肋墙面 0.86,EXPORT_EMISSION_OVERRIDES 建筑 0.18,全是针对 Cesium 偏白的默认光照 调出来的。新资产没调过,是唯一如实渲染的东西,放旁边就显得发黑。 - FOLIAGE_ALBEDO_GAIN = 2.1,在抠图植被 dilate 那一遍顺带乘上。用增益而非 tint:其他材质是单一表面,而这是同时装着叶片/树皮/果实的图集,往绿色混会 把树干染绿。缩放保留色相关系,只把整体抬到和邻居一样的曝光。 - FOLIAGE_SATURATION = 1.75,绕各像素自身 Rec.709 亮度做饱和度拉伸。图集本 来就偏灰(平均饱和度 0.22),远看时 mip 把叶片、树皮、缝隙混在一起会更往 中性靠。绕亮度拉伸把叶片推绿而基本不动本来中性的部分,也没有绿色 tint 强 加给树干的色相偏移。叶片 sRGB → [0.262, 0.529, 0.021],饱和度 0.22 → 0.34, 过曝到纯白的像素占 0.3%。 - FOLIAGE_EMISSION 回调 0.25,它只负责给背光面兜底。 - 新增 triangulate_mesh():export_tangents 打开后刷了 55 行「切向空间只能只算 三角/四边形」,MeshBatch 建的 OSM 轮廓都是 n-gon。glTF 只有三角形,导出时 无论如何都会三角化,提前做不改变任何输出三角形(三角数 51719 前后一致), 切线 49/102 → 102/102,警告归零。 被数据排除的假设:贴图颜色全链路逐位一致;模拟 mip 链可见像素亮度 0.127→0.124;法线贴图抠图区是干净平面法线;GLB 重新导入 Blender 渲染正常。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Blender 3D 场景生成
该生成器将 OSM 建筑、水体、植被标签,以及可选的 osm2streets GeoJSON 道路图层,组合为 Blender 3D 场景。
项目主入口是根目录的区域管线:
npm run build:area -- --config config/areas/nantaizi-lake-innovation-valley.json --stages blender,cesium
下面的命令适合单独调试 Blender 脚本。
生成场景
/Applications/Blender.app/Contents/MacOS/Blender \
--background --factory-startup \
--python blender/generate_scene.py -- \
--osm "/path/to/input.osm" \
--geojson "/path/to/osm2streets_web_out" \
--output "/path/to/output.blend" \
--render "/path/to/preview.png" \
--tree-style natural
--geojson 为可选参数。不提供时,道路使用简单的 OSM highway 折线,而非详细 osm2streets 几何。实际资产生成建议先跑 intermediates 阶段,为 Blender 提供 osm2streets 道路面、标线、斑马线和箭头。
--tree-style 可选 apple、fattree、natural、procedural。
apple(拟真)——SpeedTree Red Delicious,4.5k tris,叶片是 alpha 抠图卡片,带法线贴图。fattree(卡通)——低面数卡通树,2.2k tris,纯实体几何,无抠图。natural——低面数树干 + 多层不规则树冠,不依赖外部模型。procedural——最轻,球形树冠。
apple 和 fattree 依赖 assets/models/ 下的第三方模型(已 gitignore)。模型缺失时自动回落到 natural,干净 checkout 仍可构建;实际使用的样式记录在场景的 tree_style_used 属性里。
使用 --office-overrides 指定一组 OSM way ID(逗号分隔),这些建筑将渲染为办公楼风格,即使其 OSM 标签为 building=industrial:
--office-overrides "117753521,117753535"
说明
- OSM
bounds元素定义场景范围(排除远处的地铁等关系成员) natural=tree节点 → 独立树木(默认低面数自然树冠)natural=tree_row路径 → 沿路径均匀分布的树木landuse=grass→ 绿色地面natural=scrub→ 低矮灌木丛amenity=fountain→ 低多边形喷泉- 建筑:
building=industrial→ 厂房风格;其他 → 办公楼风格(带窗带) - 植被和建筑高度从 OSM
height标签读取 - 程序化细节(窗带、屋顶设备、树冠)不改变 OSM 体量
- 纹理使用 Poly Haven 的 1K CC0 纹理,打包在
.blend内
导出为 Cesium GLB
/Applications/Blender.app/Contents/MacOS/Blender \
--background \
--python blender/export_cesium.py -- \
--blend "/path/to/output.blend" \
--glb "/path/to/output_cesium.glb" \
--metadata "/path/to/output_cesium.json"
GLB 使用以 OSM bounds 中心为原点的局部 ENU 坐标系(X 东,Y 北,Z 上)。
使用配套的 JSON 元数据文件将模型放置到 Cesium 中。
区域管线的 cesium 阶段还会在输出目录生成 <area-id>-cesium-preview.html。
导出脚本会:
- 应用网格修改器并创建 UV
- 将 Blender 特有材质转换为 glTF 兼容 PBR 材质
- 烘焙色调覆盖基础色以实现干净的 Web 渲染
- 将所有纹理图片嵌入 GLB
- 写入包含 WGS84 锚点和 Cesium JS 辅助代码的 JSON 元数据
预览
在输出目录上启动 HTTP 服务后打开预览页:
cd /path/to/output
python3 -m http.server 8765