通过传图片,实现一个可以设置重复次数和持续时间的流动线条。是在常见的流动线条效果上面更改了一些代码。找了很多,但都是单一的流动效果,不能设置重复次数,于是就自己重新改动了一点。
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也是一样的设置,对于垂直墙动画,也是一样的,只不过方向不同而已。
环绕墙在原先基础上显示两个环绕效果:
?代码如下:
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的材质感兴趣,希望对你有帮助。
|