Cesium里的postProcessStages实现暗黑样式的天地图

参考许多可视化大屏,很多的样式都是暗黑的看起来非常有科技感,但大多数都不是天地图底图的,对此,笔者对于实现这个效果进行了研究,总结了下面的两个方法:

方法一:改CSS里的filter滤镜

设置div容器的id或者class,通过css里去改

推荐的属性值:

复制代码
brightness(0.88) contrast(0.95) grayscale(0) hue-rotate(180deg) opacity(1) saturate(2.5) sepia(0.5) invert(1)

效果还可以,地图上的地铁线的颜色也不会影响,但是唯一的缺点就是由于是加在div地图容器上的,地图的弹窗也会变为暗黑的特效,但是优点就是可以兼容所有的GIS前端地图框架,不管是二维的leaflet、openlayers,还是三维的Cesium、ArcGIS api for js。

方法二:对于Cesium,可以使用PostProcessStage

代码如下:

javascript 复制代码
  this.viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({
            name: 'css-like-dark-filter',
            fragmentShader: `
       uniform sampler2D colorTexture;
in vec2 v_textureCoordinates;
out vec4 fragColor;

// 工具函数:RGB -> HSV
vec3 rgb2hsv(vec3 c) {
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
    float d = q.x - min(q.w, q.y);
    float e = 1e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

// 工具函数:HSV -> RGB
vec3 hsv2rgb(vec3 c) {
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
    vec4 texColor = texture(colorTexture, v_textureCoordinates);
    vec3 color = texColor.rgb;

    // 1. invert(1)
    color = 1.0 - color;

    // 2. sepia(0.5)
    vec3 sepia = vec3(
        dot(color, vec3(0.393, 0.769, 0.189)),
        dot(color, vec3(0.349, 0.686, 0.168)),
        dot(color, vec3(0.272, 0.534, 0.131))
    );
    color = mix(color, sepia, 0.5);

    // 3. saturate(2.5)
    float luminance = dot(color, vec3(0.299, 0.587, 0.114));
    vec3 gray = vec3(luminance);
    color = mix(gray, color, 2.5);

    // 4. hue-rotate(180deg) → add 0.5 to hue (since 360° = 1.0 in normalized hue)
    vec3 hsv = rgb2hsv(color);
    hsv.x = fract(hsv.x + 0.5); // 180° rotation
    color = hsv2rgb(hsv);

    // 5. contrast(0.95)
    color = (color - 0.5) * 0.95 + 0.5;

    // 6. brightness(0.88)
    color *= 0.88;

    // Clamp to [0,1] to avoid overflow
    color = clamp(color, 0.0, 1.0);

    fragColor = vec4(color, texColor.a);
}
    `,
            uniforms: {}
        }));
    }

代码里用反引号(`````)包裹的那段内容是 GLSL(OpenGL Shading Language)代码 ,具体来说,是一段 fragment shader(片段着色器)

  • GLSL 是一种用于编写 GPU 着色器程序的 C 风格语言。
  • 它运行在显卡上,用于控制图形渲染管线中的顶点(vertex shader)和像素/片段(fragment shader)处理。
  • 在 CesiumJS 中,PostProcessStage 允许你通过自定义 fragment shader 对整个场景画面进行后处理(post-processing),比如添加滤镜、模糊、夜视效果等。

效果:

不会改css,地图里的弹窗样式也不会改变。

相关推荐
ZC跨境爬虫11 分钟前
跟着 MDN 学CSS day_41:显式轨道、隐式网格与区域命名放置
前端·javascript·css·ui·交互
修己xj1 小时前
告别手动存图!这款叫 Fatkun 的浏览器插件,简直是素材收集神器
前端
袋鼠云数栈2 小时前
从前端到基础设施,ACOS 如何打通企业全链路可观测
运维·前端·人工智能·数据治理·数据智能
AskHarries2 小时前
系统提示词、开发者指令和用户输入的优先级
java·前端·数据库
Moment2 小时前
长上下文会最终杀死 Rag 吗?
前端·javascript·后端
qcx233 小时前
【系统学AI】25 论文导读 ①:两篇改变 AI 的开山之作——Attention Is All You Need & ReAct
前端·人工智能·react.js·transformer
kyriewen3 小时前
大文件上传最全指南:分片、断点续传、秒传,一篇就够了
前端·javascript·面试
郑洁文4 小时前
基于Python的Web命令执行漏洞自动化检测系统
前端·python·网络安全·自动化
新酱爱学习4 小时前
手搓 10 个 Skill 后,我把重复劳动收敛成了一套零依赖 CLI 工具
前端·javascript·人工智能
IT_陈寒5 小时前
Python的线程池居然把我坑在了垃圾回收这块
前端·人工智能·后端