maptalks 开发GIS地图(30)maptalks.three.23- custom-electricShield

1. 电子罩栏,这个效果很不错了。可是用在什么地方比较合适呢?

2. 定义扩展对象类

 1 class ElectricShield extends maptalks.BaseObject {
 2             constructor(coordinate, options, material, layer) {
 3                 options = maptalks.Util.extend({}, OPTIONS, options, { layer, coordinate });
 4                 super();
 5                 //Initialize internal configuration
 6                 // https://github.com/maptalks/maptalks.three/blob/1e45f5238f500225ada1deb09b8bab18c1b52cf2/src/BaseObject.js#L135
 7                 this._initOptions(options);
 8                 const { altitude, radius } = options;
 9                 //generate geometry
10                 const r = layer.distanceToVector3(radius, radius).x;
11                 const geometry = new THREE.SphereBufferGeometry(r, 50, 50, 0, Math.PI * 2);
12 
13                 //Initialize internal object3d
14                 // https://github.com/maptalks/maptalks.three/blob/1e45f5238f500225ada1deb09b8bab18c1b52cf2/src/BaseObject.js#L140
15                 // this._createMesh(geometry, material);
16                 this._createGroup();
17                 const mesh = new THREE.Mesh(geometry, material);
18                 this.getObject3d().add(mesh);
19                 //set object3d position
20                 const z = layer.distanceToVector3(altitude, altitude).x;
21                 const position = layer.coordinateToVector3(coordinate, z);
22                 this.getObject3d().position.copy(position);
23                 this.getObject3d().rotation.x = Math.PI / 2;
24             }
25 
26             _animation() {
27                 const ball = this.getObject3d().children[0];
28                 const speed = this.getOptions().speed;
29                 ball.material.uniforms.time.value += speed;
30             }
31         }

3. 电子罩栏的材质,其中使用了 ShaderMaterial

  1 function getMaterial() {
  2             var ElectricShield = {
  3                 uniforms: {
  4                 time: {
  5                     type: "f",
  6                     value: 0
  7                 },
  8                 color: {
  9                     type: "c",
 10                     value: new THREE.Color("#9999FF")
 11                 },
 12                 opacity: {
 13                     type: "f",
 14                     value: 1
 15                 }
 16                 },
 17                 vertexShaderSource: "
  precision lowp float;
  precision lowp int;
  "
 18                 .concat(
 19                     THREE.ShaderChunk.fog_pars_vertex,
 20                     "
  varying vec2 vUv;
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    "
 21                 )
 22                 .concat(THREE.ShaderChunk.fog_vertex, "
  }
"),
 23                 fragmentShaderSource: `
 24                 #if __VERSION__ == 100
 25                  #extension GL_OES_standard_derivatives : enable
 26                 #endif
 27                 uniform vec3 color;
 28                 uniform float opacity;
 29                 uniform float time;
 30                 varying vec2 vUv;
 31                 #define pi 3.1415926535
 32                 #define PI2RAD 0.01745329252
 33                 #define TWO_PI (2. * PI)
 34                 float rands(float p){
 35                     return fract(sin(p) * 10000.0);
 36                 }
 37                 float noise(vec2 p){
 38                     float t = time / 20000.0;
 39                     if(t > 1.0) t -= floor(t);
 40                     return rands(p.x * 14. + p.y * sin(t) * 0.5);
 41                 }
 42                 vec2 sw(vec2 p){
 43                     return vec2(floor(p.x), floor(p.y));
 44                 }
 45                 vec2 se(vec2 p){
 46                     return vec2(ceil(p.x), floor(p.y));
 47                 }
 48                 vec2 nw(vec2 p){
 49                     return vec2(floor(p.x), ceil(p.y));
 50                 }
 51                 vec2 ne(vec2 p){
 52                     return vec2(ceil(p.x), ceil(p.y));
 53                 }
 54                 float smoothNoise(vec2 p){
 55                     vec2 inter = smoothstep(0.0, 1.0, fract(p));
 56                     float s = mix(noise(sw(p)), noise(se(p)), inter.x);
 57                     float n = mix(noise(nw(p)), noise(ne(p)), inter.x);
 58                     return mix(s, n, inter.y);
 59                 }
 60                 float fbm(vec2 p){
 61                     float z = 2.0;
 62                     float rz = 0.0;
 63                     vec2 bp = p;
 64                     for(float i = 1.0; i < 6.0; i++){
 65                     rz += abs((smoothNoise(p) - 0.5)* 2.0) / z;
 66                     z *= 2.0;
 67                     p *= 2.0;
 68                     }
 69                     return rz;
 70                 }
 71                 void main() {
 72                     vec2 uv = vUv;
 73                     vec2 uv2 = vUv;
 74                     if (uv.y < 0.5) {
 75                     discard;
 76                     }
 77                     uv *= 4.;
 78                     float rz = fbm(uv);
 79                     uv /= exp(mod(time * 2.0, pi));
 80                     rz *= pow(15., 0.9);
 81                     gl_FragColor = mix(vec4(color, opacity) / rz, vec4(color, 0.1), 0.2);
 82                     if (uv2.x < 0.05) {
 83                     gl_FragColor = mix(vec4(color, 0.1), gl_FragColor, uv2.x / 0.05);
 84                     }
 85                     if (uv2.x > 0.95){
 86                     gl_FragColor = mix(gl_FragColor, vec4(color, 0.1), (uv2.x - 0.95) / 0.05);
 87                     }
 88                 }`
 89             };
 90             let material = new THREE.ShaderMaterial({
 91                 uniforms: ElectricShield.uniforms,
 92                 defaultAttributeValues: {},
 93                 vertexShader: ElectricShield.vertexShaderSource,
 94                 fragmentShader: ElectricShield.fragmentShaderSource,
 95                 blending: THREE.AdditiveBlending,
 96                 depthWrite: !1,
 97                 depthTest: !0,
 98                 side: THREE.DoubleSide,
 99                 transparent: !0
100             });
101             return material;
102         }

4. 添加电子罩栏

1         var ballElectric, material;
2         function addElectricShield() {
3             material = getMaterial();
4             ballElectric = new ElectricShield(map.getCenter(), { radius: 500 }, material, threeLayer)
5             threeLayer.addMesh(ballElectric);
6             initGui();
7             animation();
8         }

5. 页面显示

6. 源码地址

https://github.com/WhatGIS/maptalkMap/tree/main/threelayer/demo

原文地址:https://www.cnblogs.com/googlegis/p/14735545.html