[{"content":"这个博客的域名 noahland.cn，来自我的 Minecraft 服务器「诺亚大陆」。\n诺亚大陆是什么 「诺亚大陆」是我从 2020 年 7 月开始运营的一个 Minecraft 网易我的世界租赁服务器项目。2023年转到朋友的第三方租赁服务器。我给它建了一个 GitHub 项目库（Noahland-Server），存档、文档、插件、拓展包和配置文件都收在里面，谁想看服务器是怎么搭的，直接翻仓库就行。\n更早的时候，我还整理过 Nukkit 的学习资料——Nukkit 是基岩版的开服软件，虽然诺亚大陆早期也是基岩版，可惜出于拓展性、生态考量。这份教程仓库并未派上用场。后来我也给工匠典藏（Tinkers\u0026rsquo; Construct）模组写过中文拓展，虽然是 mcfunction 级别的小东西，但都是一路折腾过来的脚印。\n为什么用服务器的名字注册域名 我也考虑过richli4307——我的网名,不过服务器开了六年，名字也比我自己任何一个网名都有辨识度。\n所以这次备案个人博客，注册域名的时候几乎没有任何犹豫：noahland.cn，就是它了。诺亚的小站，诺亚大陆的主人在自己的小站里写笔记。\n这个站会写什么 服务器运维只是其中一部分。更多时候这里会记录我折腾各种东西的过程——树莓派、家庭服务器、Rust 小工具。技术笔记为主，偶尔写点生活。\n第一篇文章的评论区还没开，想聊诺亚大陆的话，服务器还在跑，游戏里见。\n湘ICP备2026046179号-1\n","date":"2026-10-13T00:00:00Z","permalink":"/p/story-of-noahland/","title":"「诺亚大陆」与 noahland.cn：这个域名的来历"},{"content":"域名 noahland.cn 备案通过，「诺亚的小站」正式上线了。\n这个站会用来放两类内容：\n技术笔记：服务器、网络、自动化相关的经验教训 生活分享：一些我觉得值得记下的事 本站基于 Hugo + Stack 主题 构建，部署在自己的 VPS 上。更多文章陆续有来。\n湘ICP备2026046179号-1\n","date":"2026-10-13T00:00:00Z","permalink":"/p/hello-noahland/","title":"你好，诺亚的小站"},{"content":" 在线试玩 → www.noahland.cn/rainy-store/ 浏览器直接打开即可（推荐 Chrome/Edge + 独显），鼠标拖动环绕视角。\n雨天的深夜，街角亮着灯的便利店——这是我基于店长测试Agent产生的渲染项目修改而来：把一个 Three.js r184 的卡通风格单文件场景，重构成 PBR 写实管线，同时尝试保持：成品必须仍是单个 HTML 文件，零外部依赖，双击就能开。\n从卡通到写实，差距在哪 店长测试产生的原场景（baseline）是 MeshToonMaterial 四阶卡通渐变 + 描边后处理，可爱：\n项 baseline 目标 材质 MeshToonMaterial + 顶点色 全 PBR（albedo/roughness/normal/ORM） 阴影 完全没有 烘焙阴影贴图 后处理 Outline + Bloom SSAO + SSGI + SSR + SSS + Bloom 纹理 3 张 2048 Canvas 图集 全部程序化生成，禁止手绘位图 改造前的卡通风格 baseline。图集资源全部复用，我仅修改了整条渲染管线。\n几条关键技术决策 吃「静态场景」的红利。 光源位置 100% 静态，全场只有路灯闪烁强度和信号灯颜色两处动态 → 阴影贴图只烘焙一次，renderer.shadowMap.autoUpdate = false，之后每帧零成本。几何也基本静态 → SSGI 走低频更新 + 时域累积 + 重投影，不在每帧全量 raymarch。这两条是在 4060 上跑得动 SSGI 的前提。\n所有画质 Pass 一律半分辨率。 SSAO / SSGI / SSR / SSS 全部 ≤ 0.5× 渲染，配套空间降噪；SSGI 另配时域累积。每帧全场景渲染次数硬约束 ≤ 2 次（GBuffer prepass + 主渲染）。\n纹理零手绘。 没有额外的纯手绘材质贴图，优先级是「复用现有图集 → 公式程序化生成 → 参考公开技术实现」。Roughness/Metal/AO 由公式生成 ORM 图烘焙内联，法线贴图由高度函数 Sobel 求导生成，一切能离线烘焙的全离线。\n自适应降级而不是砍画质。 沿用帧时长统计，超预算时按「关 SSGI 时域累积 → 降 renderScale → 砍雨粒子数」的顺序降；首帧黑屏时逐级降级（关 MSAA → 关 Bloom → 关 SSGI）再展示画面。\n反射的分面处理。 路面和人行道分开各渲一张反射 RT，反射查询点按反射面高度修正，再配逐面几何剔除——根治了抬高面倒影错位和矮墙底面镜面错位这类经典 bug。\n性能红线 项 值 显卡 RTX 4060 Laptop 帧率 30–60 FPS（低于 30 不达标） 主渲染分辨率 renderScale 0.75（可调） 网络请求 0 场景本身不大——13 个 Mesh 承载整条街，Draw Call 个位数——压力全在屏幕空间管线上。真正难的不是把效果做出来，难的是在 30 FPS 的预算里把效果做出来。\n为什么是单文件 这是项目最有性格的约束：禁止 CDN、禁止 fetch、所有纹理运行时 Canvas 生成或构建期内联为 data URI，最终产物 file:// 双击即开。这样就构造出了一个可以随手发给朋友双击打开的雨夜。\n后续 代码整理后若店长同意，我会开源到 GitHub，届时补上链接 待办清单：SSS 改进、雨滴打在玻璃上的折射、低配模式更多档位 如果你打开 demo 觉得卡，?q=low 可以切低配。我自己手机反正是没抗住。\n","date":"2026-10-13T00:00:00Z","image":"/p/rainy-store-render/images/overview.jpg","permalink":"/p/rainy-store-render/","title":"雨夜便利店：一个 Three.js 单文件场景的写实化渲染重构"},{"content":"最近和几个同学做了一个叫「熊导游」（TravelBear）的项目：一台树莓派 4B 上的 AI 景区导览设备。按一下按键，摄像头拍下眼前的展品，定位模块告诉它你在哪，云端大模型生成一段讲解，然后用语音播报出来。\n整个流程听起来简单，真要把每一环都做实，还是踩了不少坑。项目开源在 GitHub，这里记录几个最有意思的技术决策。\n整体架构 设备端五个模块：定位、识图、LLM、TTS、按键状态机。主程序用有限状态机控制状态流转，trigger() 是按键入口，支持打断——讲解员讲到一半再按一下就能换题。\n识图：Qwen-VL-Max，置信度低于 0.05 的画面直接丢弃，不让模型瞎编 LLM：阿里云 qwen-plus，实测 2.4 秒生成 127 字讲解，语速刚好 TTS：小米 MiMo，云端兜底，实测尾音完整 ASR：本来想做语音问答，冻结了——设备定位是「一按一讲」，先把核心体验做扎实 最难的问题：展厅里 GPS 不可信 室外定位用的是 NEO-M8N GPS 模块，本地围栏两档判定（景区级宽松、点位级严格），未命中再走高德在线反解兜底。这套方案在室外工作得很好——实测 9 星、HDOP 2.87，准确命中「上海大学（宝山校区）」。\n但展厅里完全是另一回事：GPS 会漏进弱 fix，漂移几十米，青铜器和陶瓷的讲解能讲串。\n我们的解法是给每个展位布一个 ESP32-C3 的 iBeacon 蓝牙信标，树莓派板载蓝牙扫描 RSSI，中值滤波加阈值过滤后映射到展位。关键是仲裁策略：\nBLE 信标新鲜命中无条件最高优先——信标固定在展位的米级物理证据前，GPS（包括点位级）不插嘴；信标信号消失 10 秒后才落回 GPS。\n这个策略有 9 条行为测试锁死（test_ble_priority.py），消除了展厅内 GPS 漏入导致的讲解串味。\n状态 截至 2026-09-28，硬件全链路已经实测闭环：GNSS 室外定位、BLE 室内定位、识图、LLM、TTS、按键热键、服务锁、打断全部通过真实验收。剩下的是现场工作：信标进馆布点、阈值标定和供电方案。\n从「按一下键」到「听见讲解」，全链路延迟压在可接受范围内——对一个靠电池和 4G 跑的设备来说，每一毫秒的云端往返都是省出来的。\n","date":"2026-10-01T00:00:00Z","permalink":"/p/travelbear-ai-guide/","title":"熊导游：一个按键就能唤起 AI 讲解的景区导览设备"},{"content":"之前给树莓派 4B 买外壳时，顺手给配了一块微雪 3.5 寸 TFT 屏。最初简简单单用 Python 写了个系统仪表盘,显示 CPU、温度、内存、磁盘、IP、Docker 容器和 Tailscale 状态，但监控的数据越来越多，很快摸到性能天花板，最后我不得不用 Rust 重写了整个东西（pi-dashboard，v0.2.2）。\n为什么 Python 不够 起初我只是计划做一个0.5FPS的监控屏幕程序，后面发现监控速度太慢，很多程序都是脉冲式的负载。为了更客观反应小派的实际硬件状态，我打起了rust的主意。\nRust 版做额外做的几件事 脏区刷新。核心思路是每次渲染都先保留上一帧画面，只把画面里变化的矩形区域写入帧缓冲。静止状态下 SPI 写入量远小于全屏，动态画面下的流畅度立刻不一样了。为此自己实现了 RGB565 帧缓冲层和一套几何原语。\n字体渲染。因为要监测的数据很多，但屏幕太小，字体必须和像素足够对齐才能保证清晰度。为此我写了一个字体级 baseline 锚定的文本引擎，现在多行混排稳定得多。\nSPI 超频到 48MHz。微雪屏官方建议频率偏保守，考虑到我的脏区刷新的平均带宽需求并不大，所以树莓派和这块屏的配合在 48MHz 下稳定，主循环跑到 15 FPS。\n裸解析触摸事件。彻底重写触摸协议和校准方式。现在不依赖任何触摸框架，直接读 input_event,在保持轻量的同时保持了可控性。现在支持点击容器列表翻页，但是重启按钮还是有点难按。\n双通道指标采集。考虑不同监控指标的变化速度差异显著，我让CPU 这类变得快的指标走快通道，磁盘、IP 这类变得慢的走慢通道,同时保证帧率与低功耗。\n最有意思的部分：让聊天机器人也能看屏 仪表盘内置了一个 Unix Domain Socket 的 IPC server，配套写了 pi-dashboard-mcp——一个 MCP server，让 AstrBot（我部署的聊天机器人）可以直接查询系统状态、截屏、切换显示模式。\n也就是说，机器人不用问人「服务器现在什么状态」，它自己看一眼屏幕就知道了。\n尾巴 这个仪表盘是树莓派时代的遗物——2026 年 9 月底我把整套服务迁到了一台小新笔记本上，树莓派正式退役。项目代码和这段折腾的记录都留在 GitHub 和本站里，权当纪念。\n树莓派退役之后这块屏我还留着。虽然有些硬件退役了，但它教会我的东西会一直跟着我。\n","date":"2026-09-20T00:00:00Z","permalink":"/p/pi-dashboard-rust/","title":"给树莓派 3.5 寸屏写了个 Rust 系统仪表盘"}]