znlgis 博客

GIS开发与技术分享 — GDAL · GeoServer · PostGIS · QGIS · OpenLayers · Cesium · FreeCAD · NPOI

第06章:颜色调整、球谐与外观优化

清理与规范化之后,往往还需要对模型整体外观做润色——提亮、增加对比、校正色温、调整透明度等。SuperSplat 的颜色调整面板正是为此而生,对应源码 src/color-grade.tssrc/ui/color-panel.ts。本章也会借此深入理解球谐颜色在编辑中的特殊性。

1. 为什么调色要分 DC 与 SH

回顾第 02 章:高斯的颜色由球谐系数编码,分为 DC 分量(0 阶,方向无关的基础色)高阶 SH 分量(方向相关)。调色时必须分别处理两者,否则视角相关的高光会失真。

SuperSplat 在 color-grade.ts 中明确区分:

applyDC(c: RGB) {   // 对基础色:带亮度/黑点偏移
    this.apply(c, this.offset);
}
applySH(c: RGB) {   // 对高阶项:不加偏移,仅缩放/饱和
    this.apply(c, 0);
}

也就是说:亮度、黑点等“偏移类”调整只作用于 DC 基础色,而缩放、饱和度等“比例类”调整同时作用于 DC 与高阶 SH,从而在改变整体观感的同时保持光照的方向性合理。

DC 与可视颜色之间的换算同样基于 0 阶球谐常数 SH_C0

const SH_C0 = 0.28209479177387814;
const dcDecode = (v: number) => v * SH_C0 + 0.5;   // 系数 -> 颜色
const dcEncode = (v: number) => (v - 0.5) / SH_C0; // 颜色 -> 系数

2. 颜色调整面板的参数

颜色面板(ColorPanel)暴露一组调色参数,对应 GradeParams

参数 含义 作用
Tint(色调) 一个 RGB 颜色 对整体进行染色/白平衡偏移
Temperature(色温) 暖↔冷 增大偏暖(增强 R、减弱 B),减小偏冷
Saturation(饱和度) 灰度↔鲜艳 1 为原始,0 变灰度,>1 更鲜艳
Brightness(亮度) 提亮/压暗 给 DC 颜色加偏移
Black Point(黑点) 暗部下限 抬高/压低暗部,影响对比
White Point(白点) 亮部上限 配合黑点决定动态范围(对比度)
Transparency(透明度) 整体不透明度缩放 作用于每个高斯的 opacity

黑点与白点共同决定一个线性映射的缩放系数:scale = 1 / (whitePoint - blackPoint),加上亮度偏移 offset = -blackPoint + brightness。这本质上是一次“色阶(Levels)”调整——和 Photoshop 的黑/白场滑块类似。

饱和度采用标准的亮度加权灰度公式(Rec.601):

const grey = c.r * 0.299 + c.g * 0.587 + c.b * 0.114;
c.r = grey + (c.r - grey) * saturation; // 其余通道同理

3. 透明度与不透明度的处理

不透明度在 3DGS 中以经过 sigmoid 激活前的原始值存储。调整透明度时需要先 sigmoid 还原到 [0,1]、乘以系数、再 invSigmoid 编码回去:

const sigmoid = (v) => 1 / (1 + Math.exp(-v));
const invSigmoid = (v) => (v <= 0 ? -400 : (v >= 1 ? 400 : -Math.log(1 / v - 1)));

applyOpacity(o) {
    return invSigmoid(sigmoid(o) * this.transparency);
}

这保证了透明度缩放在“感知线性”的空间里进行,不会因为直接乘原始 logit 值而产生异常。

4. 调色工作流

  1. 打开颜色调整面板(在视图/菜单中找到 Colors 面板);
  2. 先用 Black Point / White Point 拉开对比,让暗部更沉、亮部更亮;
  3. Brightness 微调整体明暗;
  4. Temperature 校正白平衡(扫描常偏暖或偏冷);
  5. Saturation 调整色彩浓度,避免过饱和;
  6. 如需统一色调,使用 Tint 染色;
  7. Transparency 微调整体通透感(一般保持 1,除非需要半透明效果)。

调整是非破坏式预览,可随时复位。这些参数在导出时会“烘焙”进高斯的颜色与不透明度数据(DC 与 SH 分别处理,opacity 通过 sigmoid 流程)。

5. hasTint 优化判定

ColorGrade 构造时会计算 hasTint,判断当前参数是否实际改变了颜色:

this.hasTint = (
    !p.tintClr.equals(Color.WHITE) ||
    p.temperature !== 0 ||
    p.saturation !== 1 ||
    p.brightness !== 0 ||
    p.blackPoint !== 0 ||
    p.whitePoint !== 1
);

当所有参数都是默认值时 hasTint 为 false,导出/渲染可跳过调色计算——这是一个值得借鉴的性能优化点(仅在确有改动时才执行逐点变换)。

6. 与显示设置的区别

注意区分两类“外观”设置:

  • 颜色调整(color-grade):改变的是模型数据本身(导出会带上),属于内容编辑;
  • 视图/显示设置(view-panel、scene-config):如背景色、色调映射(tonemapping)、曝光等,属于当前观察方式,不改变模型数据。

调色前要明确目标:是想永久改变模型颜色(用 color-grade),还是只想换个观察环境(用 view 设置)。

7. 本章小结

本章讲解了 SuperSplat 的外观优化能力:

  • 调色区分 DC(基础色,带偏移)与高阶 SH(仅缩放/饱和),以保持视角相关光照正确;
  • 可调参数包括色调、色温、饱和度、亮度、黑点、白点、透明度,本质是“色阶 + 白平衡 + 饱和度 + 不透明度缩放”;
  • 不透明度调整在 sigmoid 空间进行;
  • hasTint 用于在无改动时跳过计算;
  • 区分“改数据的调色”与“改观察方式的显示设置”。

下一章我们进入相机姿态、时间轴与动画导出。


← 上一章 目录 下一章 →