07 / 12 · Connect a learned model连接训练模型
Load a real model without guessing its meaning明确数据含义,再加载真实模型
Decode a specific model contract, upload persistent records, and render the pretrained fixture.解码具体模型约定,上传常驻记录,渲染预训练数据。
PLY tells you how fields are stored. It does not tell you whether “scale” means a physical length or its logarithm, or whether “color” means RGB or SH coefficients. A loader that guesses may produce a plausible but wrong picture.PLY 告诉你字段怎么存,却不自动告诉你 scale 是真实长度还是长度的对数,也不告诉你 color 是 RGB 还是 SH 系数。靠猜的加载器可能生成看似合理却错误的图像。
1. Write the contract before the decoder1. 先写约定,再写解码器
This fixture is STG-Lite: 32 little-endian float32 fields per record, 128 bytes. It stores position, temporal center/log-scale, unused normal slots, nine motion coefficients, three direct RGB features, opacity logit, three log-scales, quaternion wxyz and quaternion velocity. The field order is strict. This is not a universal 4DGS layout.本数据是 STG-Lite:每条记录 32 个小端 float32 字段,共 128 字节,包含位置、时间中心与时间对数尺度、未使用法线槽、九个运动系数、三个直接 RGB 特征、不透明度 logit、三个对数尺度、wxyz 四元数及其速度。字段顺序严格固定,这不是通用 4DGS 布局。
In this model the f_dc fields hold direct RGB features used by the lightweight renderer. Do not apply the static 3DGS SH-DC conversion just because the property names look familiar. The SH laboratory teaches a different appearance model; it does not add missing SH coefficients to this file.此模型的 f_dc 字段保存轻量渲染器使用的直接 RGB 特征。不要只因名字熟悉,就套用静态 3DGS 的 SH-DC 转换。SH 实验讲的是另一种外观模型,不会给这个文件补出不存在的 SH 系数。
2. Decode, validate, then activate2. 解码、验证,再激活
The strict parser checks header types/order, count limits, payload size, finite values and activation overflow. Only then upload the record array. Runtime scales use exp(log_scale); opacity uses sigmoid(logit). Passing log-scale directly into a covariance would square the wrong number.严格解析器会检查头部类型与顺序、数量上限、payload 大小、有限数值以及激活溢出,然后才上传记录数组。运行时尺度使用 exp(log_scale),不透明度使用 sigmoid(logit)。若直接把 log-scale 塞进协方差,就会对错误的量平方。
3. Keep the source on the GPU3. 让原始记录常驻 GPU
StgPass::new uploads the source payload once. Each frame, prepare evaluates centers and opacity on the CPU, culls and sorts them, then uploads the ordered u32 indices. The shader uses each source index to read the original record and evaluates time-dependent geometry again. CPU and GPU evaluation must stay consistent or sorting will describe a different scene.StgPass::new 只上传一次原始 payload。每帧 prepare 在 CPU 上求中心与透明度、剔除并排序,然后上传排序后的 u32 索引。Shader 用源索引读取原始记录,再计算随时间变化的几何。CPU 与 GPU 求值必须一致,否则排序对应的是另一个场景。
At 108,317 records, source storage is 13,864,576 bytes, about 13.22 MiB. One full u32 index order is 433,268 bytes, about 0.41 MiB. Compressed download size is a separate number; neither value measures the complete process or GPU memory footprint.108,317 条记录的源数据占 13,864,576 字节,约 13.22 MiB;一份完整 u32 索引序列占 433,268 字节,约 0.41 MiB。压缩下载大小又是另一个数字,这两个数都不代表进程或 GPU 的总内存占用。
4. Compare under a known camera4. 在已知相机下对比
Stage 7 gives an orbitable overview. Use the main viewer’s calibrated reference comparison when judging agreement with the research image. A different pose, field of view, crop or timestamp can dominate apparent error. The included asset is an official pretrained research fixture, not evidence that this project trained that scene.阶段 7 提供可绕转的全景观察。判断与研究图像是否一致时,应使用主 viewer 的标定相机参考对比。姿态、视野、裁剪或时间不同,都可能主导视觉误差。附带的是官方预训练研究数据,不代表本项目训练了该场景。
The demo is for non-commercial research/evaluation; check the upstream model and dataset terms before reusing assets. A model loader should carry provenance and representation metadata alongside the byte layout.此演示用于非商业研究与评估,复用资产前应查看上游模型和数据集条款。加载器除字节布局外,还应保存来源与表示方法元数据。
RUN → OBSERVE运行 → 观察
Make this step concrete把这一步运行起来
The Sear steak research scene, rendered by the existing StgPass inside the new shared host. Model download requires an explicit button online.在新共享宿主内,由已有 StgPass 渲染 Sear steak 研究场景;在线版点击按钮后才下载模型。
Open GPU milestone 7 →打开 GPU 里程碑 7 →cargo run --locked --example workshop -- 7
# Online: choose stage 7, then Load research model.
cargo run --locked --example native_smokeCommands use the reference repository. Rust/WGSL changes need a native rebuild or npm run build:wasm, followed by a browser reload.命令以参考仓库为基础。修改 Rust/WGSL 后需重新编译桌面程序,或运行 npm run build:wasm 后刷新浏览器。
IDEA → IMPLEMENTATION想法 → 实现
Follow the running code沿着真实代码看
Excerpts are extracted from the repository at site build time. Expand only the part you are studying; full files include context and line numbers.片段在网站构建时直接从仓库提取。只展开正在研究的部分,完整文件包含上下文与行号。
src/workshop.rs · L254–306
Stage 7 delegates to the real pass without changing the host.阶段 7 转交真实 pass,宿主无需改变。
pub fn prepare(
&mut self,
queue: &wgpu::Queue,
frame: Frame,
size: [u32; 2],
) -> Result<u32, String> {
frame.validate()?;
if size.contains(&0) {
return Err("Cannot prepare a zero-sized target".into());
}
let (view, projection) = camera(frame, size[0], size[1]);
self.stage = frame.stage;
if frame.stage == 7 {
let pass = self.real.as_mut().ok_or("Load the STG-Lite model first")?;
self.count = pass
.prepare(
queue,
frame.time,
view.to_cols_array_2d(),
projection.to_cols_array_2d(),
size,
)?
.visible_count as u32;
} else {
let data = instances(frame, view);
self.count = data.len() as u32;
queue.write_buffer(&self.instances, 0, bytemuck::cast_slice(&data));
queue.write_buffer(
&self.uniforms,
0,
bytemuck::bytes_of(&Uniforms {
view_projection: (projection * view).to_cols_array_2d(),
viewport_stage: [size[0] as f32, size[1] as f32, frame.stage as f32, 0.0],
}),
);
}
Ok(if frame.stage == 0 { 0 } else { self.count })
}
pub fn draw(&self, pass: &mut wgpu::RenderPass<'_>) {
if self.stage == 0 {
return;
}
if self.stage == 7 {
if let Some(real) = &self.real {
real.draw(pass);
}
return;
}
pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &self.bindings, &[]);
pass.draw(0..if self.stage == 1 { 3 } else { 6 }, 0..self.count);
}Open full source with line numbers ↗打开带行号的完整源码 ↗Real-model render pass ↗真实模型渲染 pass ↗ · Real-model shader ↗真实模型 shader ↗
Predict it, change it, explain it先预测,再修改,再解释
Why would a generic XYZRGB PLY loader be insufficient even if it can read every byte in this file?即使普通 XYZRGB PLY 加载器能读完所有字节,为什么仍然不够?
Check your reasoning核对推理
It would miss activation, time, shape, quaternion order and the renderer’s appearance convention. Storage decoding and representation decoding are separate responsibilities.它会遗漏激活、时间、形状、四元数顺序与外观约定。解码存储格式和解码表示含义,是两项不同职责。