learning_cesium/天气场景.html

486 lines
22 KiB
HTML
Raw Permalink Normal View History

2024-03-19 18:06:25 +08:00
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8">
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Learning Cesium!</title>
<script src="./Build/Cesium/Cesium.js"></script>
<style>
@import url(./Build/Cesium/Widgets/widgets.css);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
#app{
position: absolute;
top: 20px;
left: 150px;
}
fieldset{
color:aliceblue
}
</style>
<!-- 添加Element UI -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="cesiumContainer"></div>
<div id="app">
<fieldset>
<legend>场景模拟</legend>
<el-button type="primary" @click="switchWeather('snow')">下雪</el-button>
<el-button type="primary" @click="switchWeather('rain')">下雨</el-button>
<el-button type="primary" @click="switchWeather('cloudy')">阴天</el-button>
<el-button type="primary" @click="switchWeather('daytime')">白天</el-button>
<el-button type="primary" @click="switchWeather('fog')">雾天</el-button>
<el-button type="primary" @click="no">清除</el-button>
</fieldset>
</div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8';
//========================================================================================
//添加OSM的建筑
// const tileset = viewer.scene.primitives.add(
// new Cesium.Cesium3DTileset({
// url: Cesium.IonResource.fromAssetId(96188),
// })
// );
// Add OSM Building tileset
// let osmBuildingsTileset = Cesium.createOsmBuildings();
// viewer.scene.primitives.add(osmBuildingsTileset);
// //设置条件渲染
// osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
// defines: {
// mh: "${feature['cesium#estimatedHeight']}",
// },
// "color": {
// conditions: [
// ["${mh} >= 300", "rgba(45, 0, 75, 0.5)"],
// ["${mh} >= 200", "rgb(102, 71, 151)"],
// ["${mh} >= 100", "rgb(170, 162, 204)"],
// ["${mh} >= 50", "rgb(224, 226, 238)"],
// ["${mh} >= 25", "rgb(252, 230, 200)"],
// ["${mh} >= 10", "rgb(248, 176, 87)"],
// ["${mh} >= 5", "rgb(198, 106, 11)"],
// ["true", "rgb(127, 59, 8)"]
// ],
// },
// // "show" : "${Height} > 50.0"
// })
// 粒子系统
// 下雪
function snowScene(){
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
float snow(vec2 uv,float scale)
{
float time = czm_frameNumber / 160.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,30.)*.0;
c+=snow(uv,20.)*.0;
c+=snow(uv,15.)*.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.3);
}
`;
let postProcessStage = new Cesium.PostProcessStage({fragmentShader});
// viewer.scene.skyAtmosphere.hueShift = -0.8; //色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
// viewer.scene.skyAtmosphere.saturationShift = -0.7; //饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
viewer.scene.skyAtmosphere.brightnessShift = -0.33; //亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
viewer.scene.fog.enabled = true; //如果启用雾,则为 true ,否则为 false 。
// viewer.scene.fog.density = 0.001; //确定雾的密度的标量
viewer.scene.fog.minimumBrightness = 0.8; //照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
viewer.scene.postProcessStages.add(postProcessStage);
}
// 下雨
function rain() {
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
float hash(float x){
return fract(sin(x*23.3)*13.13);
}
void main(void){
float time = czm_frameNumber / 60.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.)*5.;
c*=v*b;
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5);
}
`;
let postProcessStage = new Cesium.PostProcessStage({fragmentShader});
viewer.scene.skyAtmosphere.hueShift = -0.8;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
viewer.scene.skyAtmosphere.saturationShift = -0.7;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
viewer.scene.skyAtmosphere.brightnessShift = -0.33;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
viewer.scene.fog.density = 0.001;//确定雾的密度的标量
viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
viewer.scene.postProcessStages.add(postProcessStage);
}
//阴天
function cloudy(){
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
void main(void){
vec4 c=vec4(.01,.01,.01,0.1);
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), c, 0.5);
}
`;
let postProcessStage = new Cesium.PostProcessStage({fragmentShader});
viewer.scene.skyAtmosphere.hueShift = -0.8;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
viewer.scene.skyAtmosphere.saturationShift = -0.7;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
viewer.scene.skyAtmosphere.brightnessShift = -0.9;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
// viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
// viewer.scene.fog.density = 0.01;//确定雾的密度的标量
// viewer.scene.fog.minimumBrightness = 0.5;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
viewer.scene.postProcessStages.add(postProcessStage);
}
// 白天
function daytime (){
var fragmentShader =`
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
uniform float scale;
uniform vec3 offset;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
gl_FragColor = vec4(color.rgb * scale + offset, 1.0);
}`;
let postProcessStage = new Cesium.PostProcessStage({
fragmentShader : fragmentShader,
uniforms : {
scale : 1.1,
offset : function() {
return new Cesium.Cartesian3(0.1, 0.1, 0.1);
}
}
});
viewer.scene.skyAtmosphere.hueShift = 0.0;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
viewer.scene.skyAtmosphere.saturationShift = 0.0;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
viewer.scene.skyAtmosphere.brightnessShift =0.0;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
viewer.scene.fog.enabled = false;//如果启用雾,则为 true ,否则为 false 。
// viewer.scene.fog.density = 0.001;//确定雾的密度的标量
// viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
viewer.scene.postProcessStages.add(postProcessStage);
}
//雾
function fog(){
const fragmentShader = `uniform sampler2D colorTexture;
uniform sampler2D depthTexture;
varying vec2 v_textureCoordinates;
void main(void)
{
vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);
vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);//雾的颜色
float depth = czm_readDepth(depthTexture, v_textureCoordinates);
vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);
float f=(depthcolor.r-0.22)/0.99;//雾的溶度
if(f<0.0) f=0.0;
else if(f>1.0) f=1.0;
gl_FragColor = mix(origcolor,fogcolor,f);
}`
let postProcessStage = new Cesium.PostProcessStage({fragmentShader});
viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
// viewer.scene.fog.density = 0.001;//确定雾的密度的标量
// viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
viewer.scene.postProcessStages.add(postProcessStage);
}
new Vue({
el: '#app',
data: function() {
return {
visible: false ,
viewer: null,
mapboxAccess: "pk.eyJ1IjoicWl1c2hpamllIiwiYSI6ImNsMDNvdDRybDEyc2YzZG9kbWZoY2FuOW0ifQ.4FH-BUupi46Z0zQ-CEm_Ig",
postProcessStage: null
}
},
methods:{
initCesium(){
this.viewer = new Cesium.Viewer('cesiumContainer',{
geocoder:false,//位置查找
homeButton:false,//视图返回初始位置
sceneModePicker:false,//视角选择器
baseLayerPicker:false,//底图选择器
navigationHelpButton:false,//导航帮助按钮
animation:false,//动画控制器
// creditContainer:"credit",//版权显示
timeline:false,//时间线
fullscreenButton:false,//全屏控件
vrButton:false
});
this.viewer.camera.flyTo({
destination: new Cesium.Cartesian3(-2325771.0288233184,5392181.511762224,2484480.395134067),
orientation: {
heading: 6.0399326,
pitch: -0.30503,
roll: 6.2825747,
},
});
},
addMapboxLayer(){
this.viewer.imageryLayers.removeAll();
// 样式id查看https://docs.mapbox.com/api/maps/styles/
// URL格式的 mapbox://styles/:owner/:style 其中 :owner 是您的 Mapbox 账户名 :style 是样式 ID 。
// 可选值streets-v10、outdoors-v10 、light-v9、dark-v9、satellite-v9、satellite-streets-v10
const mapboxStyleImagery = new Cesium.MapboxStyleImageryProvider({
styleId: "dark-v9",
accessToken: this.mapboxAccess,
// proxy: new Cesium.DefaultProxy("http://127.0.0.1:8080/proxy/"),
});
this.viewer.imageryLayers.addImageryProvider(mapboxStyleImagery);
},
addOSMBuilding(){
let osmBuildingsTileset = Cesium.createOsmBuildings();
this.viewer.scene.primitives.add(osmBuildingsTileset);
//设置条件渲染
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
defines: {
mh: "${feature['cesium#estimatedHeight']}",
},
"color": {
conditions: [
["${mh} >= 300", "rgba(45, 0, 75, 0.5)"],
["${mh} >= 200", "rgb(102, 71, 151)"],
["${mh} >= 100", "rgb(170, 162, 204)"],
["${mh} >= 50", "rgb(224, 226, 238)"],
["${mh} >= 25", "rgb(252, 230, 200)"],
["${mh} >= 10", "rgb(248, 176, 87)"],
["${mh} >= 5", "rgb(198, 106, 11)"],
["true", "rgb(127, 59, 8)"]
],
},
// "show" : "${Height} > 50.0"
})
},
snow(){
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
float snow(vec2 uv,float scale)
{
float time = czm_frameNumber / 160.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,30.)*.0;
c+=snow(uv,20.)*.0;
c+=snow(uv,15.)*.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.3);
}
`;
this.postProcessStage = new Cesium.PostProcessStage({fragmentShader});
// this.viewer.scene.skyAtmosphere.hueShift = -0.8; //色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
// this.viewer.scene.skyAtmosphere.saturationShift = -0.7; //饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
this.viewer.scene.skyAtmosphere.brightnessShift = -0.33; //亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
this.viewer.scene.fog.enabled = true; //如果启用雾,则为 true ,否则为 false 。
// this.viewer.scene.fog.density = 0.001; //确定雾的密度的标量
this.viewer.scene.fog.minimumBrightness = 0.8; //照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
},
rain() {
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
float hash(float x){
return fract(sin(x*23.3)*13.13);
}
void main(void){
float time = czm_frameNumber / 60.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.)*5.;
c*=v*b;
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5);
}
`;
this.postProcessStage = new Cesium.PostProcessStage({fragmentShader});
this.viewer.scene.skyAtmosphere.hueShift = -0.8;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
this.viewer.scene.skyAtmosphere.saturationShift = -0.7;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
this.viewer.scene.skyAtmosphere.brightnessShift = -0.33;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
this.viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
this.viewer.scene.fog.density = 0.001;//确定雾的密度的标量
this.viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
},
cloudy(){
const fragmentShader = `uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
void main(void){
vec4 c=vec4(.01,.01,.01,0.1);
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), c, 0.5);
}
`;
this.postProcessStage = new Cesium.PostProcessStage({fragmentShader});
this.viewer.scene.skyAtmosphere.hueShift = -0.8;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
this.viewer.scene.skyAtmosphere.saturationShift = -0.7;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
this.viewer.scene.skyAtmosphere.brightnessShift = -0.9;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
// this.viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
// this.viewer.scene.fog.density = 0.01;//确定雾的密度的标量
// this.viewer.scene.fog.minimumBrightness = 0.5;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
},
daytime (){
var fragmentShader =`
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
uniform float scale;
uniform vec3 offset;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
gl_FragColor = vec4(color.rgb * scale + offset, 1.0);
}`;
this.postProcessStage = new Cesium.PostProcessStage({
fragmentShader : fragmentShader,
uniforms : {
scale : 1.1,
offset : function() {
return new Cesium.Cartesian3(0.1, 0.1, 0.1);
}
}
});
this.viewer.scene.skyAtmosphere.hueShift = 0.0;//色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
this.viewer.scene.skyAtmosphere.saturationShift = 0.0;//饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
this.viewer.scene.skyAtmosphere.brightnessShift =0.0;//亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
this.viewer.scene.fog.enabled = false;//如果启用雾,则为 true ,否则为 false 。
// this.viewer.scene.fog.density = 0.001;//确定雾的密度的标量
// this.viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
},
fog(){
const fragmentShader = `uniform sampler2D colorTexture;
uniform sampler2D depthTexture;
varying vec2 v_textureCoordinates;
void main(void)
{
vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);
vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);//雾的颜色
float depth = czm_readDepth(depthTexture, v_textureCoordinates);
vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);
float f=(depthcolor.r-0.22)/0.99;//雾的溶度
if(f<0.0) f=0.0;
else if(f>1.0) f=1.0;
gl_FragColor = mix(origcolor,fogcolor,f);
}`
this.postProcessStage = new Cesium.PostProcessStage({fragmentShader});
this.viewer.scene.fog.enabled = true;//如果启用雾,则为 true ,否则为 false 。
// this.viewer.scene.fog.density = 0.001;//确定雾的密度的标量
// this.viewer.scene.fog.minimumBrightness = 0.8;//照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
},
//切换场景
switchWeather(type){
if(this.postProcessStage){
// this.viewer.scene.postProcessStages.remove(this.postProcessStage);
this.no();
this.postProcessStage = null;
}
if(!type){
return ;
}
//切换场景
if(type === 'snow'){
this.snow();
}else if(type === 'rain'){
this.rain();
}else if(type === "cloudy"){
this.cloudy();
}else if(type === "fog"){
this.fog();
}else if(type === "daytime"){
this.daytime();
}
if(this.postProcessStage){
this.viewer.scene.postProcessStages.add(this.postProcessStage);
}
},
// 清空,不加天气
no(){
this.viewer.scene.postProcessStages.remove(this.postProcessStage);
this.viewer.scene.skyAtmosphere.hueShift = 0.0; //色调变化适用于大气。默认为0.0无移位。色相偏移1.0表示可用色相完全旋转。
this.viewer.scene.skyAtmosphere.saturationShift = 0.0; //饱和度偏移将应用于大气。默认为0.0(无移位)。-1.0的饱和度偏移是单色的。
this.viewer.scene.skyAtmosphere.brightnessShift = 0.0; //亮度变化适用于大气。默认为0.0(无移位)。-1.0的亮度偏移是完全黑暗,这将使空间显示出来。
this.viewer.scene.fog.enabled = false; //如果启用雾,则为 true ,否则为 false 。
this.viewer.scene.fog.density = 0.001; //确定雾的密度的标量
this.viewer.scene.fog.minimumBrightness = 0.8; //照明产生的雾色的最小亮度。值为0.0可能会使雾完全变成黑色。值1.0不会影响完全没有亮度。
}
},
created(){
this.initCesium()
this.addMapboxLayer()
this.addOSMBuilding()
}
})
</script>
</body>
</html>