之前用cesium+vue搭建了一个简易的案例系统,算是基础功能的堆砌,也不知道有什么实际用处,算是学习的记录,后续会放在github上。
有一个天气效果的展示,雨、雪、雾、云的基础展示,前三者比较常见,网上很多现成的shader,后者官方沙盒中有云的案例,可以自己改改。cesium效果一般,可以尝试去threejs或者ue试试玩。
雨效果:
shader:
//雨
setRainEffect() {
const tiltAngle = .2
const rainSize = 0.3
const rainSpeed = 60
if (viewer) {
let Rain = "uniform sampler2D colorTexture;\n\
varying vec2 v_textureCoordinates;\n\
uniform float tiltAngle;\n\
uniform float rainSize;\n\
uniform float rainSpeed;\n\
float hash(float x) {\n\
return fract(sin(x * 133.3) * 13.13);\n\
}\n\
void main(void) {\n\
float time = czm_frameNumber / rainSpeed;\n\
vec2 resolution = czm_viewport.zw;\n\
vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);\n\
vec3 c = vec3(.6, .7, .8);\n\
float a = tiltAngle;\n\
float si = sin(a), co = cos(a);\n\
uv *= mat2(co, -si, si, co);\n\
uv *= length(uv + vec2(0, 4.9)) * rainSize + 1.;\n\
float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);\n\
float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;\n\
c *= v * b;\n\
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1), .5);\n\
}\n\
"
let rainStage = new Cesium.PostProcessStage({
name: 'yang_rain',
fragmentShader: Rain,
uniforms: {
tiltAngle: () => {
return tiltAngle;
},
rainSize: () => {
return rainSize;
},
rainSpeed: () => {
return rainSpeed;
}
}
});
return window.viewer.scene.postProcessStages.add(
rainStage
);
}
}
雪效果:
shader:
//雪
setSnowEffect() {
if (viewer) {
let fs = "uniform sampler2D colorTexture;\n\
varying vec2 v_textureCoordinates;\n\
\n\
float snow(vec2 uv,float scale){\n\
float time = czm_frameNumber / 60.0;\n\
float w=smoothstep(1.,0.,-uv.y*(scale/10.));\n\
if(w<.1)return 0.;\n\
uv+=time/scale;\n\
uv.y+=time*2./scale;\n\
uv.x+=sin(uv.y+time*.5)/scale;\n\
uv*=scale;\n\
vec2 s=floor(uv),f=fract(uv),p;\n\
float k=3.,d;\n\
p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;\n\
d=length(p);\n\
k=min(d,k);\n\
k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n\
return k*w;\n\
}\n\
\n\
void main(){\n\
vec2 resolution = czm_viewport.zw;\n\
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\
vec3 finalColor=vec3(0);\n\
float c = 0.0;\n\
c+=snow(uv,30.)*.0;\n\
c+=snow(uv,20.)*.0;\n\
c+=snow(uv,15.)*.0;\n\
c+=snow(uv,10.);\n\
c+=snow(uv,8.);\n\
c+=snow(uv,6.);\n\
c+=snow(uv,5.);\n\
finalColor=(vec3(c));\n\
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.3);\n\
\n\
}\n\
";
return window.viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({
name: 'snowEffect',
fragmentShader: fs
}));
}
}
雾效果:
shader:
// 雾天
setFogEffect() {
if (viewer) {
let fragmentShaderSource =
'\n\
uniform sampler2D colorTexture;\n\
uniform sampler2D depthTexture;\n\
varying vec2 v_textureCoordinates;\n\
void main(void)\n\
{\n\
vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);\n\
vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);\n\
float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n\
vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);\n\
float f=(depthcolor.r-0.22)/0.2;\n\
if(f<0.0) f=0.0;\n\
else if(f>1.0) f=0.6;\n\
gl_FragColor = mix(origcolor,fogcolor,f);\n\
}'
return window.viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({
name: 'FogEffect',
fragmentShader: fragmentShaderSource
}));
}
}
云效果:
代码:
//云
setcloudEffect(numClouds, startLong, stopLong, startLat, stopLat, minHeight, maxHeight) {
//加载云特效
Cesium.Math.setRandomNumberSeed(2.5);
const clouds = new Cesium.CloudCollection()
// randomly generate clouds in a certain area
const rangeLong = stopLong - startLong;
const rangeLat = stopLat - startLat;
for (let i = 0; i < numClouds; i++) {
let long = startLong + getRandomNumberInRange(0, rangeLong);
let lat = startLat + getRandomNumberInRange(0, rangeLat);
let height = getRandomNumberInRange(minHeight, maxHeight);
let scaleX = getRandomNumberInRange(150, 350);
let scaleY = scaleX / 2.0 - getRandomNumberInRange(0, scaleX / 4.0);
let slice = getRandomNumberInRange(0.1, 0.7);
let depth = getRandomNumberInRange(5, 20);
let aspectRatio = getRandomNumberInRange(1.5, 2.1);
let cloudHeight = getRandomNumberInRange(5, 20);
clouds.add({
position: Cesium.Cartesian3.fromDegrees(long, lat, height),
scale: new Cesium.Cartesian2(scaleX, scaleY),
maximumSize: new Cesium.Cartesian3(
aspectRatio * cloudHeight,
cloudHeight,
depth
),
slice: slice,
});
}
viewer.scene.primitives.add(clouds);
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(startLong, startLat, 800),//相机位置
orientation: {
heading: -5.3, //方位角
pitch: 0, //倾角
roll: 0 //旋转角
}
});
function getRandomNumberInRange(minValue, maxValue) {
return (
minValue + Cesium.Math.nextRandomNumber() * (maxValue - minValue)
);
}
}