当前位置: 首页 > news >正文

2025cesium进阶教程|Cesium 天气特效实现:从 ShaderToy 移植下雪效果的完整方案

本篇我们介绍如何将 ShaderToy 中的下雪效果成功移植到 Cesium 中,实现场景下雪的视觉效果。这种移植方式可以扩展到其他 ShaderToy 效果,只需根据具体效果调整变量替换和颜色混合的方式即可。

视频教程点击这里查看

一、什么是 Shader

Shader(着色器)是运行在 GPU 上的小程序,用于控制图形渲染过程中的各种视觉效果。它通过编写特定的代码(通常是 GLSL 语言),来定义顶点如何变换、像素(片元)如何着色等,从而实现从简单的颜色填充到复杂的光影、纹理、动画等多种视觉表现。在 3D 渲染中,着色器是实现丰富视觉效果的核心工具。

二、Cesium 中的 CustomShader

在 Cesium 这个三维地理信息可视化引擎中,CustomShader 是一个功能强大的接口,其核心作用是允许开发者自定义图形渲染过程中的 GLSL 着色逻辑。借助它,开发者能够对 3D Tiles、模型(Model)或 Primitive 等对象实现更为灵活、复杂的视觉效果,比如让模型发光、呈现流动感、闪烁、根据高度变色、随时间变化、依据法线方向渐变等。

基本原理

Cesium 中的每个 3D 模型或 Tileset 在渲染时,都会使用一个默认的渲染着色器(Shader Program)。而 CustomShader 的作用,就是在保留 Cesium 默认渲染功能的前提下,允许开发者往这个默认的着色器程序中注入自定义的 GLSL 代码,以此来干预渲染过程。

主要影响的渲染阶段

CustomShader 主要能对渲染管线中的两个关键阶段产生影响:

  1. Vertex Shader(顶点着色器)阶段:该阶段主要负责对模型的顶点进行处理,比如顶点的位置变换、计算顶点的颜色等。
  2. Fragment Shader(片元着色器)阶段:此阶段则是对像素(片元)进行着色处理,决定每个像素最终显示的颜色,像纹理采样、光照计算等都在此阶段完成。
两个阶段可获取的重要数据

在顶点着色器和片元着色器阶段,能够获取到模型的多种重要数据,具体如下表所示:

模型中的对应属性着色器中的变量类型是否在顶点着色器中可用是否在片元着色器中可用描述
POSITIONpositionMCvec3模型坐标系中的位置
POSITIONpositionWCvec3世界坐标系中的位置(WGS84 ECEF (x, y, z)),低精度
POSITIONpositionECvec3眼睛坐标系中的位置
NORMALnormalMCvec3模型坐标系中的单位法向量,仅在顶点着色器中可用
NORMALnormalECvec3眼睛坐标系中的单位法向量,仅在片元着色器中可用
TANGENTtangentMCvec3模型坐标系中的单位切向量,始终为 vec3。对于提供 w 分量的模型,在计算副切向量后会移除 w 分量
TANGENTtangentECvec3眼睛坐标系中的单位切向量,始终为 vec3。对于提供 w 分量的模型,在计算副切向量后会移除 w 分量
NORMAL & TANGENTbitangentMCvec3模型坐标系中的单位副切向量,仅在法向量和切向量都可用时才存在
NORMAL & TANGENTbitangentECvec3眼睛坐标系中的单位副切向量,仅在法向量和切向量都可用时才存在
TEXCOORD_NtexCoord_Nvec2第 N 组纹理坐标
COLOR_Ncolor_Nvec4第 N 组顶点颜色,始终为 vec4;如果模型未指定 alpha 值,则默认 alpha 值为 1
JOINTS_Njoints_Nivec4第 N 组关节索引
WEIGHTS_Nweights_Nvec4第 N 组权重值

三、在 Cesium 后处理中使用 ShaderToy 的代码

ShaderToy 是一个在线的 GLSL 着色器创作和分享平台,上面有许多优秀的着色器效果。我们可以将这些效果移植到 Cesium 中,以丰富 Cesium 场景的视觉表现。下面以一个下雪效果的 ShaderToy 代码(https://www.shadertoy.com/view/ldsGDn)为例,说明如何进行移植。

移植的关键步骤

  1. 入口函数的调整:ShaderToy 中使用mainImage(out vec4 fragColor, in vec2 fragCoord)作为入口函数,而在 Cesium 的后处理着色器中,使用void main(void)作为入口函数,最终通过gl_FragColor输出颜色。

  2. 内置变量的替换

    • ShaderToy 中的iResolution.xy(屏幕分辨率)对应 Cesium 中的czm_viewport.zw
    • ShaderToy 中的fragCoord.xy(像素坐标)对应 Cesium 中的gl_FragCoord.xy
    • ShaderToy 中的iTime(时间)在 Cesium 中可以用czm_frameNumber / 60.0来模拟(假设帧率为 60fps)。
    • ShaderToy 中的iMouse(鼠标交互)在 Cesium 中通常没有直接对应的变量,可根据需要去掉或改为常量。
  3. 最终颜色混合:在 Cesium 中,后处理效果需要与场景原有的颜色进行混合,因此需要读取场景的颜色纹理colorTexture,然后将自定义效果的颜色与场景颜色进行混合。

具体的移植代码

const snowShader = /*glsl*/ `
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
#define LIGHT_SNOW
#ifdef LIGHT_SNOW#define LAYERS 50#define DEPTH .5#define WIDTH .3#define SPEED .6
#else // BLIZZARD#define LAYERS 200#define DEPTH .1#define WIDTH .8#define SPEED 1.5
#endif
void main(void)
{const mat3 p = mat3(13.323122,23.5112,21.71123,21.1212,28.7312,11.9312,21.8112,14.7212,61.3934);vec2 resolution = czm_viewport.zw;vec2 fragCoord = gl_FragCoord.xy;// ShaderToy 的 iTime -> 用 frameNumber 模拟时间float iTime = float(czm_frameNumber) / 60.0;// ShaderToy 的 uv 计算vec2 uv = vec2(1.0, resolution.y / resolution.x) * fragCoord / resolution;vec3 acc = vec3(0.0);float dof = 5.0 * sin(iTime * 0.1);for (int i = 0; i < LAYERS; i++) {float fi = float(i);vec2 q = uv * (1.0 + fi * DEPTH);q += vec2(q.y * (WIDTH * mod(fi * 7.238917, 1.0) - WIDTH * 0.5),SPEED * iTime / (1.0 + fi * DEPTH * 0.03));vec3 n = vec3(floor(q), 31.189 + fi);vec3 m = floor(n) * 0.00001 + fract(n);vec3 mp = (31415.9 + m) / fract(p * m);vec3 r = fract(mp);vec2 s = abs(mod(q, 1.0) - 0.5 + 0.9 * r.xy - 0.45);s += 0.01 * abs(2.0 * fract(10.0 * q.yx) - 1.0);float d = 0.6 * max(s.x - s.y, s.x + s.y) + max(s.x, s.y) - 0.01;float edge = 0.005 + 0.05 * min(0.5 * abs(fi - 5.0 - dof), 1.0);acc += vec3(smoothstep(edge, -edge, d) * (r.x / (1.0 + 0.02 * fi * DEPTH)));}vec4 img = texture2D(colorTexture, v_textureCoordinates);gl_FragColor = img + vec4(acc, 1.0);
}
`;
const snowPost = new Cesium.PostProcessStage({name: "snow",fragmentShader: snowShader,
});
viewer.scene.postProcessStages.add(snowPost);

http://www.dtcms.com/a/609377.html

相关文章:

  • 数据库 - SQL
  • 单页网站seo怎么做秦皇岛高端网站设计
  • 做网商必备网站手机百度关键词优化
  • python实现电脑手势识别截图
  • openEuler 全场景操作系统下 cpolar 内网穿透的价值深挖与协同优化
  • 为什么选择威洛博直线模组——从 3C、新能源、半导体到医疗的大致解析
  • 利用ArcPy批量检查管线隐患点与周边设施距离的实现方案
  • 【ZeroRange WebRTC】Amazon Kinesis Video Streams WebRTC SDK 音视频传输技术分析
  • 政务机关数字化办公核心系统
  • 盐城做网站企业新增网站推广教程
  • 衡东建设局网站公司内部交流 网站模板
  • 自己做网站要买什么在网站制作前需要有哪些前期策划工作
  • RAG系统学习之——RAG技术详解与实战指南
  • ASC学习笔记0014:手动添加一个新的属性集
  • 通过手机远程操控电脑,一步步学习便捷方法
  • 【AI学习-comfyUI学习-Segment Anything分割+实时图像裁剪-各个部分学习-第九节2】
  • [Linux]学习笔记系列 -- [kernel[params
  • AI 多模态全栈应用项目描述
  • SpringMVC(2)学习
  • 面向智能教育的生成式AI个性化学习内容生成研究
  • C语言编程代码编译 | 学习如何高效编译和调试C语言程序
  • 多模态学习与多模态模型
  • 网站建设费的税率网页设计制作用什么软件
  • Flutter Material 3设计语言详解
  • 天猫魔盒M19_晶晨S912H当贝桌面线刷机包_adb开启
  • 长沙seo优化排名东营优化网站
  • Python 编程实战 · 实用工具与库 — Flask 基础入门
  • supOS工厂操作系统 | 像“拼乐高”一样做数据分析
  • 青岛营销型网站推广wordpress doc导入
  • upload-labs(1-13)(配合源码分析)