Cesium从已知的自定义材质扩展其他效果(二)

通过传图片,实现一个可以设置重复次数和持续时间的流动线条。是在常见的流动线条效果上面更改了一些代码。找了很多,但都是单一的流动效果,不能设置重复次数,于是就自己重新改动了一点。

function FlowLineMaterial(opt) {
    this.defaultColor = new Cesium.Color(0, 0, 0, 0);
    opt = opt || {};
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this.color = opt.color || this.defaultColor; //颜色
    this._duration = opt.duration || 1000; //时长
    this.url = opt.url; //材质图片
    this._time = undefined;
}

FlowLineMaterial.prototype.getType = function (time) {
    return "FlowLine";
};

FlowLineMaterial.prototype.getValue = function (time, result) {
    if (!Cesium.defined(result)) {
        result = {};
    }
    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, this.defaultColor, result.color);
    result.image = this.url;
    if (this._time === undefined) {
        this._time = new Date().getTime();
    }
    result.time = (new Date().getTime() - this._time) / this._duration;

    return result;
};

FlowLineMaterial.prototype.equals = function (other) {
    return this === other ||
        other instanceof FlowLineMaterial && Cesium.Property.equals(this._color, other._color);
};

Object.defineProperties(FlowLineMaterial.prototype, {
    isConstant: {
        get: function get() {
            return false;
        }
    },
    definitionChanged: {
        get: function get() {
            return this._definitionChanged;
        }
    },
    color: Cesium.createPropertyDescriptor('color')
});


Cesium.Material._materialCache.addMaterial("FlowLine", {
    fabric: {
        type: "FlowLine",
        uniforms: {
            color: new Cesium.Color(1, 0, 0, 1.0),
            image: '',
            time: 0,
            repeat: new Cesium.Cartesian2(1.0, 1.0)
        },

        source: "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
                    {\n\
                        czm_material material = czm_getDefaultMaterial(materialInput);\n\
                        vec2 st = repeat * materialInput.st;\n\
                        vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
                        if(color.a == 0.0)\n\
                        {\n\
                            material.alpha = colorImage.a;\n\
                            material.diffuse = colorImage.rgb; \n\
                        }\n\
                        else\n\
                        {\n\
                            material.alpha = colorImage.a * color.a;\n\
                            material.diffuse = max(color.rgb * material.alpha * 3.0, color.rgb); \n\
                        }\n\
                        return material;\n\
                    }"
    },
    translucent: function translucent() {
        return true;
    }
});

使用起来的话也很简单,只不过要注意repeat的值,并不是普通的数字,而是Cartesian2类型的值。

用法如下;重复两次

viewer.entities.add({
  name: 'PolylineTrail',
  polyline: {
    positions: Cesium.Cartesian3.fromDegreesArrayHeights([
      110,30, 100000,
      114, 30, 100000,
      114, 50, 1000000]),
    width: 5,
    material: new FlowLineMaterial({
      color: Cesium.Color.fromCssColorString('#00ff00'),
      duration: 5000,
      repeat: new Cesium.Cartesian2(2.0,1.0),
      url: 'img/lineArrow2.png'
    })
  }
});


viewer.zoomTo(viewer.entities);

效果图:

 如果完善一下的话,就可以只传数字,从而实现在x方向或者y方向上的重复。

主要原理是fabric的source里面。

materialInput.st 是一个vec2类型的值,repeat最后也会变成vec2类型的值。两个相乘,应该就是向量的乘法。

materialInput.st的第一个值可以看成是沿线的方向,第二个值是线的垂直方向。沿线的方向重复了两次。

对于流动墙体,则有两种情况。一种是环形围绕墙的动画,一种是在垂直方向上的动画。

如果将这种思路应用到环绕墙效果上,那么repeat也是一样的设置,对于垂直墙动画,也是一样的,只不过方向不同而已。

扫描二维码关注公众号,回复: 15218955 查看本文章

环绕墙在原先基础上显示两个环绕效果:

 代码如下:

function PolylineTrailLinkMaterialProperty(color, duration, repeat) {
  this._definitionChanged = new Cesium.Event();
  this._color = undefined;
  this._repeat = undefined;
  this._colorSubscription = undefined;
  this.color = color;
  this.repeat = repeat;
  this.duration = duration;
  this._time = (new Date()).getTime();
}
Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
  isConstant: {
      get: function () {
          return false;
      }
  },
  definitionChanged: {
      get: function () {
          return this._definitionChanged;
      }
  },
  color: Cesium.createPropertyDescriptor('color'),
  repeat: Cesium.createPropertyDescriptor('repeat')
});
PolylineTrailLinkMaterialProperty.prototype.getType = function (time) {
  return 'PolylineTrailLink';
}
PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) {
  if (!Cesium.defined(result)) {
      result = {};
  }
  result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
  result.repeat = Cesium.Property.getValueOrClonedDefault(this._repeat, time,new Cesium.Cartesian2(1.0,1.0), result.repeat);
  result.image = Cesium.Material.PolylineTrailLinkImage;
  result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
  return result;
}
PolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
  return this === other ||
      (other instanceof PolylineTrailLinkMaterialProperty &&
          Property.equals(this._color, other._color))
}
Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;
Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';
Cesium.Material.PolylineTrailLinkImage = "./img/colors.png";
Cesium.Material.PolylineTrailLinkSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
                                            {\n\
                                                 czm_material material = czm_getDefaultMaterial(materialInput);\n\
                                                 vec2 st = repeat * materialInput.st;\n\
                                                 vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
                                                 material.alpha = colorImage.a * color.a;\n\
                                                 material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
                                                 return material;\n\
                                             }";
Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, {
  fabric: {
      type: Cesium.Material.PolylineTrailLinkType,
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 1),
        image: Cesium.Material.PolylineTrailLinkImage,
        time: 0,
        repeat: new Cesium.Cartesian2(1.0,1.0)
      },
      source: Cesium.Material.PolylineTrailLinkSource
  },
  translucent: function (material) {
      return true;
  }
});

var redWall = viewer.entities.add({
  name: "Red wall from surface with outline",
  wall: {
    positions: Cesium.Cartesian3.fromDegreesArray([
      -107.0,
      43.0,
      -97.0,
      43.0,
      -97.0,
      40.0,
      -107.0,
      40.0,
      -107.0,
      43.0,
    ]),
    maximumHeights: [10000, 10000, 10000, 10000, 10000],
    minimumHeights: [43.9, 49.4, 38.7, 40, 54],
    material: new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.RED, 3000, new Cesium.Cartesian2(2.0,1.0))
  },
});

viewer.zoomTo(viewer.entities)

只是和上面流动线略有不同的设置方式。

垂直流动墙效果:

上面是在垂直方向重复两次的,下面是不重复的效果

 

材质代码如下,和环绕墙材质很多代码一样,唯一不同的就是glsl语言略有不同,重复的方向从s的水平方向变成了t的垂直方向。


function PolylineTrailLinkMaterialProperty(color, duration, repeat) {
  this._definitionChanged = new Cesium.Event();
  this._color = undefined;
  this._colorSubscription = undefined;
  this.color = color;
  this._repeat = undefined;
  this.repeat = repeat;
  this.duration = duration;
  this._time = (new Date()).getTime();
}
Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
  isConstant: {
      get: function () {
          return false;
      }
  },
  definitionChanged: {
      get: function () {
          return this._definitionChanged;
      }
  },
  color: Cesium.createPropertyDescriptor('color'),
  repeat: Cesium.createPropertyDescriptor('repeat')
});
PolylineTrailLinkMaterialProperty.prototype.getType = function (time) {
  return 'PolylineTrailLink';
}
PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) {
  if (!Cesium.defined(result)) {
      result = {};
  }
  result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
  result.repeat = Cesium.Property.getValueOrClonedDefault(this._repeat, time, new Cesium.Cartesian2(1.0,1.0), result.repeat);
  result.image = Cesium.Material.PolylineTrailLinkImage;
  result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
  return result;
}
PolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
  return this === other ||
      (other instanceof PolylineTrailLinkMaterialProperty &&
          Property.equals(this._color, other._color))
}
Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;
Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';
// Cesium.Material.PolylineTrailLinkImage = "./img/colors.png";
Cesium.Material.PolylineTrailLinkImage = "./img/fence.png";
// Cesium.Material.PolylineTrailLinkSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
//                                             {\n\
//                                                  czm_material material = czm_getDefaultMaterial(materialInput);\n\
//                                                  vec2 st = materialInput.st;\n\
//                                                  vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
//                                                  material.alpha = colorImage.a * color.a;\n\
//                                                  material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
//                                                  return material;\n\
//                                              }";
Cesium.Material.PolylineTrailLinkSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
  czm_material material = czm_getDefaultMaterial(materialInput);\n\
  vec2 st = repeat * materialInput.st;\n\
  vec4 colorImage = texture2D(image, vec2(fract((st.t - time)), st.t));\n\
  vec4 fragColor;\n\
  fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
  fragColor = czm_gammaCorrect(fragColor);\n\
  material.alpha = colorImage.a * color.a;\n\
  material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
  return material;\n\
}";
    // vec4 fragColor;\n\
    // fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
    // fragColor = czm_gammaCorrect(fragColor);\n\
Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, {
  fabric: {
      type: Cesium.Material.PolylineTrailLinkType,
      uniforms: {
          color: new Cesium.Color(0.0, 0.0, 0.0, 1),
          image: Cesium.Material.PolylineTrailLinkImage,
          repeat: new Cesium.Cartesian2(1.0,1.0),
          time: 0
      },
      source: Cesium.Material.PolylineTrailLinkSource
  },
  translucent: function (material) {
      return true;
  }
});

var redWall = viewer.entities.add({
  name: "Green wall from surface with outline",
  wall: {
    positions: Cesium.Cartesian3.fromDegreesArray([
      -107.0,
      43.0,
      -97.0,
      43.0,
      -97.0,
      40.0,
      -107.0,
      40.0,
      -107.0,
      43.0,
    ]),
    maximumHeights: [1000000, 1000000, 1000000, 1000000, 1000000],
    material: new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.GREEN, 3000, new Cesium.Cartesian2(1.0,2.0))
  },
});

viewer.zoomTo(viewer.entities)

 传入new Cesium.Cartesian2(1.0,2.0)就是重复两次的效果了。

如果对于glsl有了解,下面这个文档就很有帮助。它解释了cesium在渲染过程中使用到的glsl语言,以及哪些参数也传入了通道中。

czm_material - Cesium Documentation

如果对webgl渲染了解,并且对cesium的材质感兴趣,希望对你有帮助。

猜你喜欢

转载自blog.csdn.net/GhostPaints/article/details/126058256