1.下雪粒子效果启动后,新增在模型上添加积雪效果;
This commit is contained in:
parent
7a861756c6
commit
eef0209e58
|
@ -31,6 +31,8 @@ export const useWeatherParticle = (viewer) => {
|
|||
weather = new SnowEffect(_viewer, {
|
||||
snowSize: 0.02, // ❄️大小,最好小于0.02
|
||||
snowSpeed: 60.0, // 速度
|
||||
isCover: true, // 是否显示积雪覆盖效果
|
||||
coverage: 0.3, // 积雪覆盖(混色)占比
|
||||
});
|
||||
weather.show(true);
|
||||
};
|
||||
|
|
|
@ -13,6 +13,9 @@ class SnowEffect {
|
|||
options = options || {};
|
||||
this.snowSize = Cesium.defaultValue(options.snowSize, 0.02); // ❄️大小,最好小于0.02
|
||||
this.snowSpeed = Cesium.defaultValue(options.snowSpeed, 60.0); // 速度
|
||||
// 积雪效果
|
||||
this.isCover = Cesium.defaultValue(options.isCover, false); // 是否显示积雪覆盖效果
|
||||
this.coverage = Cesium.defaultValue(options.coverage, 0.3); // 积雪覆盖(混色)占比
|
||||
this.viewer = viewer;
|
||||
this.init();
|
||||
}
|
||||
|
@ -31,6 +34,27 @@ class SnowEffect {
|
|||
},
|
||||
});
|
||||
this.viewer.scene.postProcessStages.add(this.snowStage);
|
||||
if(this.isCover) {
|
||||
const coverShader = new Cesium.CustomShader({
|
||||
uniforms: {
|
||||
u_lightColor: {
|
||||
type: Cesium.UniformType.VEC3,
|
||||
value: new Cesium.Cartesian3(1, 1, 1),
|
||||
},
|
||||
u_snowAlpha: {
|
||||
type: Cesium.UniformType.FLOAT,
|
||||
value: this.coverage,
|
||||
},
|
||||
},
|
||||
fragmentShaderText: this.cover()
|
||||
})
|
||||
for (let index = 0; index < this.viewer.scene.primitives.length; index++) {
|
||||
const primitive = this.viewer.scene.primitives.get(index);
|
||||
if(primitive instanceof Cesium.Cesium3DTileset) {
|
||||
primitive.customShader = coverShader;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
@ -43,6 +67,19 @@ class SnowEffect {
|
|||
}
|
||||
delete this.snowSize;
|
||||
delete this.snowSpeed;
|
||||
|
||||
// 销毁积雪效果
|
||||
if(this.isCover === undefined) return;
|
||||
if(this.isCover) {
|
||||
for (let index = 0; index < this.viewer.scene.primitives.length; index++) {
|
||||
const primitive = this.viewer.scene.primitives.get(index);
|
||||
if(primitive instanceof Cesium.Cesium3DTileset) {
|
||||
primitive.customShader = undefined;
|
||||
}
|
||||
}
|
||||
delete this.isCover;
|
||||
delete this.coverStage;
|
||||
}
|
||||
}
|
||||
show(visible) {
|
||||
this.snowStage.enabled = visible;
|
||||
|
@ -82,5 +119,71 @@ class SnowEffect {
|
|||
}\n\
|
||||
";
|
||||
}
|
||||
|
||||
cover() {
|
||||
return `
|
||||
#define MAX_RADIUS 2
|
||||
// Set to 1 to hash twice. Slower, but less patterns.
|
||||
#define DOUBLE_HASH 0
|
||||
// Hash functions shamefully stolen from:
|
||||
// https://www.shadertoy.com/view/4djSRW
|
||||
#define HASHSCALE1 .1031
|
||||
#define HASHSCALE3 vec3(.1031, .1030, .0973)
|
||||
float hash12(vec2 p)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * HASHSCALE1);
|
||||
p3 += dot(p3, p3.yzx + 19.19);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
vec2 hash22(vec2 p)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * HASHSCALE3);
|
||||
p3 += dot(p3, p3.yzx+19.19);
|
||||
return fract((p3.xx+p3.yz)*p3.zy);
|
||||
|
||||
}
|
||||
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
||||
vec3 positionEC = fsInput.attributes.positionEC;
|
||||
vec3 positionMC = fsInput.attributes.positionMC;
|
||||
vec2 uv = fsInput.attributes.texCoord_0 * 500.;
|
||||
vec3 pos_dx = dFdx(positionEC);
|
||||
vec3 pos_dy = dFdy(positionEC);
|
||||
vec3 normalEC = normalize(cross(pos_dx, pos_dy));
|
||||
vec4 positionWC = normalize(czm_inverseView * vec4(positionEC,1.0));
|
||||
vec3 normalWC = normalize(czm_inverseViewRotation * normalEC);
|
||||
float time = czm_frameNumber / 60.0;
|
||||
vec2 p0 = floor(uv);
|
||||
vec2 circles = vec2(0.);
|
||||
for (int j = -MAX_RADIUS; j <= MAX_RADIUS; ++j)
|
||||
{
|
||||
for (int i = -MAX_RADIUS; i <= MAX_RADIUS; ++i)
|
||||
{
|
||||
vec2 pi = p0 + vec2(i, j);
|
||||
#if DOUBLE_HASH
|
||||
vec2 hsh = hash22(pi);
|
||||
#else
|
||||
vec2 hsh = pi;
|
||||
#endif
|
||||
vec2 p = pi + hash22(hsh);
|
||||
|
||||
float t = fract(0.3*time + hash12(hsh));
|
||||
vec2 v = p - uv;
|
||||
float d = length(v) - (float(MAX_RADIUS) + 1.)*t;
|
||||
|
||||
float h = 1e-3;
|
||||
float d1 = d - h;
|
||||
float d2 = d + h;
|
||||
float p1 = sin(31.*d1) * smoothstep(-0.6, -0.3, d1) * smoothstep(0., -0.3, d1);
|
||||
float p2 = sin(31.*d2) * smoothstep(-0.6, -0.3, d2) * smoothstep(0., -0.3, d2);
|
||||
circles += 0.5 * normalize(v) * ((p2 - p1) / (2. * h) * (1. - t) * (1. - t));
|
||||
}
|
||||
}
|
||||
circles /= float((MAX_RADIUS*2+1)*(MAX_RADIUS*2+1));
|
||||
vec3 n = vec3(circles, sqrt(1. - dot(circles, circles)));
|
||||
material.diffuse = mix(material.diffuse, vec3(1.0) , u_snowAlpha * smoothstep(0., .5, dot(positionWC.xyz, normalWC)));
|
||||
material.diffuse *= min(max(0.0, dot(normalEC, czm_sunDirectionEC) * 1.0) + u_lightColor, 1.0);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
export default SnowEffect;
|
|
@ -25,6 +25,10 @@ const options = ref({
|
|||
},
|
||||
ditu: 'tianditu', // 底图选择
|
||||
isTerrainProvider: true, // 启用地形
|
||||
modelList: [
|
||||
'/model/hu_ma_shan/tileset.json',
|
||||
'/model/yi_liu/tileset.json'
|
||||
], // 测试模型列表
|
||||
})
|
||||
const showProperty = ref(false); // 控制属性面板的显示与隐藏
|
||||
const propertyData = ref([])
|
||||
|
|
Loading…
Reference in New Issue