cesium 实现地图环境功能 - 雨,雪,雾特效

  • 需求背景
  • 解决效果
  • Code
    • index.vue
    • fogEffect.ts
    • rain.glsl
    • snow.glsl
    • fog.glsl

需求背景

需要实现天气模拟,日照模拟功能,提高三维实景效果

解决效果

Code

在这里插入图片描述
注意:我以下glsl文件时基于 webgl1.0,即cesium,创建球的时候,要指定 webgl 为 1.0 版本

index.vue

<- /**
* @author: liuk
* @date: 2024-07-15
* @describe: 地图环境
*/ -->
<template><div class="map_scene-wrap"><div class="head_title_arrow">工具</div><div class="second-level-heading"><span>天气模拟</span></div><div class="map_scene-content"><div @click="weatherClick(0)" :class="{ select: weatherItemSelectIndex === 0 }">晴天</div><div @click="weatherClick(1)" :class="{ select: weatherItemSelectIndex === 1 }">下雨</div><div @click="weatherClick(2)" :class="{ select: weatherItemSelectIndex === 2 }">下雪</div><div @click="weatherClick(3)" :class="{ select: weatherItemSelectIndex === 3 }">大雾</div></div><div class="second-level-heading"><span>日照模拟</span></div><div class="ymfxClass"><div class="nowDate">{{ moment(new Date()).format('YYYY-MM-DD') }}</div><el-slider :marks="{0: '0点',24: '24点'}" v-model="hour" :min="0" :max="24" @input="shadowSliderChange"></el-slider></div></div>
</template><script lang="ts" setup>
import moment from "moment";
import {onMounted, reactive, toRefs} from "vue";
import {usemapStore} from "@/store/modules/cesiumMap";
import FogEffect from "./fogEffect.ts"
import rainGlsl from "./rain.glsl"
import snowGlsl from "./snow.glsl"let lastStage, fogEffectconst mapStore = usemapStore()
const model = reactive({weatherItemSelectIndex: -1,hour: 12,
})
const {weatherItemSelectIndex, hour} = toRefs(model)onMounted(() => {fogEffect = new FogEffect({show: false,viewer,maxHeight: 40000, //大于此高度后不显示fogByDistance: new Cesium.Cartesian4(100, 0.0, 9000, 0.9),color: Cesium.Color.WHITE,});fogEffect.show = false
})const weatherClick = (index) => {model.weatherItemSelectIndex = model.weatherItemSelectIndex === index ? -1 : indexremoveStage()switch (model.weatherItemSelectIndex) {case 0:model.hour = 12shadowSliderChange(12)break;case 1:showRain();break;case 2:showSnow();break;case 3:showfogEffect();break;}
}
// 地图逻辑
const viewer = mapStore.getCesiumViewer();
const showSnow = () => {lastStage = viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader: snowGlsl}));
}
const showRain = () => {lastStage = viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader: rainGlsl}));
}
const showfogEffect = () => {fogEffect.show = true;
}
const shadowSliderChange = (val) => {viewer.scene.globe.enableLighting = true// JulianDate 与北京时间 相差8小时const time = new Date(new Date().setHours(Number(val)) - 8 * 60 * 60 * 1e3);time.setHours(val);console.log(new Date(time).toLocaleString())viewer.clock.currentTime = Cesium.JulianDate.fromIso8601(time.toISOString())// iso8601String
}
const removeStage = () => {viewer.scene.postProcessStages.remove(lastStage);fogEffect.show = false;
}
</script><style lang="scss" scoped>
.map_scene-wrap {align-items: flex-start;position: absolute;top: 70px;right: 65px;width: 300px;background: rgba(0, 0, 0, 0.6);border-radius: 4px;backdrop-filter: blur(2px);padding: 20px;.second-level-heading {margin-left: 10px;margin-top: 20px;font-size: 14px;color: #fff;position: relative;line-height: 1;padding-left: 10px;&::before {position: absolute;display: block;content: '';width: 3px;height: 70%;background-color: rgba(46, 165, 255, 1);left: 0;top: 50%;transform: translateY(-50%);}i {font-size: 16px;color: rgba(255, 255, 255, 0.8);cursor: pointer;&:hover {color: rgba(255, 255, 255, 1);}}}.map_scene-content {display: flex;flex-wrap: wrap;font-family: PingFang SC Regular;padding-top: 10px;& > div {padding: 4px 10px;margin-right: 10px;cursor: pointer;color: #fff;font-size: 13px;background: rgba(46, 165, 255, 0.3);border: 1px solid #2ea5ff;&:not(:first-child) {margin-left: 8px;}}.select {background: #2ea5ff;border: 1px solid #2ea5ff;}}.ymfxClass {margin-left: 20px;.nowDate {text-align: right;font-size: 12px;font-family: SourceHanSansCN-Regular, SourceHanSansCN;font-weight: 400;color: #2ea5ff;}::v-deep .el-slider {.el-slider__button {width: 13px;height: 13px;position: relative;top: -1px;}.el-slider__runway {height: 4px;background: rgb(255, 255, 255, 0.3);.el-slider__bar {height: 100%;color: rgba(46, 165, 255, 1);}.el-slider__marks-text {font-size: 12px;font-weight: 400;color: #2ea5ff;}}.el-slider__stop {display: none;height: 4px;background: rgb(255, 255, 255, 0.3);}}}
}
</style>

fogEffect.ts

/*** @author: liuk* @date: 2024-07-14* @describe:场景雾效果* @by:根据深度图的深度值,对片元进行不同程度的模糊*/import * as Cesium from "cesium";
import FogFS from "./fog.glsl";export default class FogEffect {//========== 构造方法 ==========constructor(options) {this.viewer = options.viewer;this.fogByDistance = Cesium.defaultValue(options.fogByDistance,new Cesium.Cartesian4(10, 0.0, 1000, 0.9)); //雾强度this.color = Cesium.defaultValue(options.color, Cesium.Color.WHITE); //雾颜色this._show = Cesium.defaultValue(options.show, true);this._maxHeight = Cesium.defaultValue(options.maxHeight, 9000);this.init();}//========== 对外属性 ==========//是否开启效果get show() {return this._show;}set show(val) {this._show = Boolean(val);this.FogStage.enabled = this._show;}//========== 方法 ==========init() {var that = this;this.FogStage = new Cesium.PostProcessStage({fragmentShader: FogFS,uniforms: {fogByDistance: function () {return that.fogByDistance;},fogColor: function () {return that.color;}},enabled: this._show});this.viewer.scene.postProcessStages.add(this.FogStage);//加控制,只在相机高度低于一定高度时才开启本效果this.viewer.scene.camera.changed.addEventListener(this.camera_changedHandler, this);}camera_changedHandler(event) {if (this.viewer.camera.positionCartographic.height < this._maxHeight) {this.FogStage.enabled = this._show;} else {this.FogStage.enabled = false;}}//销毁destroy() {this.viewer.scene.camera.changed.removeEventListener(this.camera_changedHandler, this);this.viewer.scene.postProcessStages.remove(this.FogStage);//删除所有绑定的数据for (let i in this) {delete this[i];}}
}

rain.glsl

uniform sampler2D colorTexture;//输入的场景渲染照片
varying vec2 v_textureCoordinates;float hash(float x){return fract(sin(x*133.3)*13.13);
}void main(void){float time = czm_frameNumber / 240.0;vec2 resolution = czm_viewport.zw;vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);vec3 c=vec3(.6,.7,.8);float a=-.4;float si=sin(a),co=cos(a);uv*=mat2(co,-si,si,co);uv*=length(uv+vec2(0,4.9))*.3+1.;float v=1.-sin(hash(floor(uv.x*100.))*2.);float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;c*=v*b; //屏幕上雨的颜色gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5); //将雨和三维场景融合
}

snow.glsl

uniform sampler2D colorTexture; //输入的场景渲染照片
varying vec2 v_textureCoordinates;float snow(vec2 uv,float scale){float time = czm_frameNumber / 60.0;float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);k=smoothstep(0.,k,sin(f.x+f.y)*0.01);return k*w;
}void main(void){vec2 resolution = czm_viewport.zw;vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);vec3 finalColor=vec3(0);float c = 0.0;c+=snow(uv,10.);c+=snow(uv,8.);c+=snow(uv,6.);c+=snow(uv,5.);finalColor=(vec3(c)); //屏幕上雪的颜色gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5);  //将雪和三维场景融合}

fog.glsl

float getDistance(sampler2D depthTexture, vec2 texCoords)
{float depth = czm_unpackDepth(texture2D(depthTexture, texCoords));if (depth == 0.0) {return czm_infinity;}vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth);return -eyeCoordinate.z / eyeCoordinate.w;
}
float interpolateByDistance(vec4 nearFarScalar, float distance)
{float startDistance = nearFarScalar.x;float startValue = nearFarScalar.y;float endDistance = nearFarScalar.z;float endValue = nearFarScalar.w;float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);return mix(startValue, endValue, t);
}
vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor)
{return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a);
}
uniform sampler2D colorTexture;
uniform sampler2D depthTexture;
uniform vec4 fogByDistance;
uniform vec4 fogColor;
varying vec2 v_textureCoordinates;
void main(void)
{float distance = getDistance(depthTexture, v_textureCoordinates);vec4 sceneColor = texture2D(colorTexture, v_textureCoordinates);float blendAmount = interpolateByDistance(fogByDistance, distance);vec4 finalFogColor = vec4(fogColor.rgb, fogColor.a * blendAmount);gl_FragColor = alphaBlend(finalFogColor, sceneColor);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3245862.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

逆向案例二十二——请求头参数加密,某省公共资源交易电子公共服务平台

网址&#xff1a;交易列表 - 福建省公共资源交易电子公共服务平台 想要抓取数据&#xff0c;进行抓包分析&#xff0c;找到数据包&#xff0c;发现请求头有加密参数Portal-Sign&#xff0c;返回的数据内容也进行了加密。 直接搜索加密参数&#xff0c;找到加密位置&#xff0c…

Julia 初学者指南(二) | 数据类型与函数基础

唠唠闲话 Julia 是一种高性能的动态编程语言&#xff0c;特别适用于数值分析和计算科学领域。它拥有一个强大的类型系统和灵活的多重分派机制&#xff0c;这使得代码易于编写同时还能保持接近 C 语言的运行速度。此外&#xff0c;Julia 也能无缝调用 C 和 Fortran 库&#xff0…

Linux网络编程-socket套接字使用详解

1.概念 在Linux中&#xff0c;套接字&#xff08;socket&#xff09;是一种通信机制&#xff0c;用于实现不同进程之间或同一主机上的不同线程之间的数据交换。它是网络编程的基础&#xff0c;允许应用程序通过网络进行通信&#xff0c;也可以在同一台机器上的不同进程间进行通…

【STM32】MPU内存保护单元

注&#xff1a;仅在F7和M7系列上使用介绍 功能&#xff1a; 设置不同存储区域的存储器访问权限&#xff08;管理员、用户&#xff09; 设置存储器&#xff08;内存和外设&#xff09;属性&#xff08;可缓冲、可缓存、可共享&#xff09; 优点&#xff1a;提高嵌入式系统的健壮…

如何将电子书发送到kindle

修改guide Amazon之kindle 修改邮箱 参考&#xff1a; blog 多种方式&#xff1a;如何将电子书发送到kindle

《知识点扫盲 · 学会 WebSocket》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

笔记 5 :linux 0.11 注释,函数 copy_mem() , copy_process () , 中断函数 int 80H 的代码框架

&#xff08;38&#xff09;接着介绍一个创建进程时的重要的函数 copy_mem&#xff08;&#xff09; 函数&#xff1a; &#xff08;39&#xff09; 分析另一个关于 fork&#xff08;&#xff09; 的重要的函数 copy_process&#xff08;&#xff09;&#xff0c;与李忠老师的操…

大模型的“幻觉”克星!被低估的RAG技术

1 RAG与大模型、Prompt、微调的关系 本文主要带大家深入学习一下最近AI领域的重要技术RAG&#xff0c;本文致力于用大白话给大家说明白RAG&#xff0c;但是还是需要一些大模型和微调有关的领域名词有一些基本的了解&#xff0c;大家选择性阅读哦!在进行正文学习之前我们先用一…

【内网穿透】打洞笔记

文章目录 前言原理阐述公网sshfrp转发服务 实现前提第一步&#xff1a;第二步第三步第四步 补充第五步&#xff08;希望隧道一直开着&#xff09;sftp传数据&#xff08;嫌云服务器上的网太慢&#xff09; 前言 租了一个云服务器&#xff0c;想用vscode的ssh远程连接&#xff…

数据库中的复合查询

一、基本查询回顾 1、查询工资高于500或岗位为manager的员工&#xff0c;并且名字首字母是J 2、按部门编号升序&#xff0c;工资降序排序 3、用年薪降序排序 4、显示工资最高的员工名字和岗位&#xff08;使用了子查询&#xff09; 5、查询工资高于平均工资的员工 6、按部门查…

kubernetes集群部署elasticsearch集群,包含无认证和有认证模式

1、背景&#xff1a; 因公司业务需要&#xff0c;需要在测试、生产kubernetes集群中部署elasticsearch集群&#xff0c;因不同环境要求&#xff0c;需要部署不同模式的elasticsearch集群&#xff0c; 1、测试环境因安全性要求不高&#xff0c;是部署一套默认配置&#xff1b; 2…

orcad导出pdf 缺少title block

在OrCAD中导出PDF时没有Title Block 最后确认问题在这里&#xff1a; 要勾选上Title Block Visible下面的print

《昇思25天学习打卡营第19天|Diffusion扩散模型》

什么是Diffusion Model&#xff1f; 什么是Diffusion Model? 如果将Diffusion与其他生成模型&#xff08;如Normalizing Flows、GAN或VAE&#xff09;进行比较&#xff0c;它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从…

46 mysql 客户端拿不到具体的错误信息

前言 这是最近碰到的一个问题 同样的一个 环境的问题, 在正常的 mysql 环境会返回 具体的错误信息, 然后 在我的另外一个环境里面 只能返回一些 unknown error 之类的 十分抽象的环境 然后 我们这里 来看一下 具体的情况 我们这里从 错误的环境 往前推导 来查看 并解决这个…

常见的计算机语言有哪些?

计算机语言用于编写软件和应用程序&#xff0c;各种语言有不同的用途和特点。目前常见的的编程语言有&#xff1a; 1、Java&#xff1b;2、Python&#xff1b;3、JavaScript&#xff1b;4、C&#xff1b;5、C#&#xff1b;6、Swift&#xff1b;7、Go&#xff1b;8、Ruby&#…

Chromium CI/CD 之Jenkins实用指南2024-系统基本配置(二)

1. 引言 在现代软件开发和持续集成/持续部署&#xff08;CI/CD&#xff09;过程中&#xff0c;Jenkins已经成为一款不可或缺的工具。作为一个开源的自动化服务器&#xff0c;Jenkins能够帮助开发团队自动化各种任务&#xff0c;包括构建、测试和部署应用程序。特别是当与Ubunt…

高职综合布线实训室

一、高职综合布线实训室建设背景 随着《国民经济和社会发展第十四个五年规划和2035年远景目标纲要》的深入实施&#xff0c;数字化转型已成为国家发展的核心战略之一&#xff0c;计算机网络技术作为数字化建设的基石&#xff0c;其重要性日益凸显。然而&#xff0c;面对数字时代…

数据可视化在智慧医疗中的重要应用

在现代智慧医疗的推动下&#xff0c;数据可视化技术正日益成为医疗领域的重要工具。通过将复杂的医疗数据转换为直观的图表和图形&#xff0c;数据可视化不仅提升了医疗服务的效率&#xff0c;还极大地改善了患者的就医体验。 在智慧医疗中&#xff0c;数据可视化首先在电子病历…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 7月17日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年7月17日 星期三 农历六月十二 1、 三部门&#xff1a;紧急调拨1万件救灾物资支持河南、山东两省做好受灾群众基本生活保障工作。 2、 多部门联合公布无人驾驶试点名单&#xff1a;北京、上海等20个城市&#xff08;联合体…

Cesium能做啥,加载哪些数据源,开源免费用商用吗?这里告诉你。

很多小伙伴对Cesium是什么&#xff0c;一知半解&#xff0c;本文是基础知识的扫盲&#xff0c;为大家分享cesium是什么、能做什么、默认数据是什么&#xff0c;为什么首先要进行数据加载&#xff0c;要加载哪些数据&#xff0c;希望通过这些带你入个门&#xff0c;欢迎点赞评论…