Cesium之流动线纹理实现的两种方式


直接上代码吧

方法一:采用自定义shader 的实现,利用cesium内置的glsl变量是纹理随着时间按照指定方向进行流动。效果图中科技感的数字流动是呈现沿着线往上流动,这种效果很适合在智慧城市数字孪生的场景中结合其他的三维地物作为装饰。我们可以看到wall的方向跟线的方向流动的方向是不一样的,wall 的流动方向是横着流动,这是着色器中的纹理方向的设置相关,我这里没有把wall的代码放出来。不过,如何更改流动方向,我相信聪明的你应该清楚如何更改了。赶紧去试一试吧。这种方式用的是addPrimiFlowline 方法

let source1 =  "czm_material czm_getMaterial(czm_materialInput materialInput)\n\`        `{\n\`            `czm_material material = czm_getDefaultMaterial(materialInput);\n\`            `vec2 st = fract (repeat *materialInput.st);\n\`            `float time = czm_frameNumber * animationSpeed;\n\`            `vec4 colorImage = texture2D(image, vec2(st.t,fract((st.s - time)) ));\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\`            `material.emission = fragColor.rgb;\n\`            `return material;\n\`        `}";``function addPrimitiveFlowAppear(pos){`      `var primitive = new Cesium.Primitive({`          `geometryInstances : new Cesium.GeometryInstance({`            `geometry : new Cesium.PolylineGeometry({`              `positions : pos,`              `width : 5,`              `vertexFormat : Cesium.PolylineMaterialAppearance.VERTEX_FORMAT//可以不设置,一般会根据 appearance的类型自动默认对应的类型`            `}),`            `attributes : {`              `//color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 1.0))`            `}`          `}),`          `appearance : new Cesium.PolylineMaterialAppearance({`            `material :``            Cesium.Material.fromType(Cesium.Material.FadeType, {`              `repeat: true,`              `fadeInColor: Cesium.Color.BLUE.withAlpha(0),`              `fadeOutColor: Cesium.Color.WHITE,`              `time: new Cesium.Cartesian2(0.0, 0.0),`              `fadeDirection: {`                `x: true,`                `y: false,`              `}`            `})`          `})`          `      });`      `return primitive`    `}`  `function addPrimiFlowline(pos,fs){`      `var primitive = new Cesium.Primitive({`          `geometryInstances : new Cesium.GeometryInstance({`            `geometry : new Cesium.PolylineGeometry({`              `positions : pos,`              `width : 10`            `}),`            `attributes : {`              `//color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 1.0))`            `}`          `}),`          `appearance : new Cesium.PolylineMaterialAppearance({`            `translucent : true`          `})`          `      });`      `primitive.appearance.material=new Cesium.Material({`        `fabric: {`            `uniforms://uniforms,`            `{`                `image:wallMater,`                `animationSpeed:0,`                `color:Cesium.Color.GREEN.withAlpha(0.5),`                `repeat:new Cesium.Cartesian2(1.0,1.0)`            `},`            `source:fs`        `},`      `});`      `return primitive`    `}`

`// 通过设置fadetype 实现流动的线`    `let primi = this.addPrimitiveFlowAppear(positions)`    `viewer.scene.primitives.add(primi);``// 添加数字流动线`
    `let linePos = Cesium.Cartesian3.fromDegreesArrayHeights([120.21725, 23.63556, 0,120.21725, 23.63556, 15000.0])`    `let linePos1 = Cesium.Cartesian3.fromDegreesArrayHeights([120.32044, 23.63392, 0, 120.32044, 23.63392, 15000.0])`    `let lineUniforms = {image:wallMater, animationSpeed:10,color:Cesium.Color.BLUE.withAlpha(0.6), repeat:new Cesium.Cartesian2(2.0,1.0)}`    `let num_line = this.addPrimiFlowline(linePos,source1)`    `num_line.appearance.material.uniforms=lineUniforms`    `let num_line1 = this.addPrimiFlowline(linePos1,source1)`    `num_line1.appearance.material.uniforms.color=Cesium.Color.BLACK``    num_line1.appearance.material.uniforms.repeat=new Cesium.Cartesian2(2.0,1.0)`    `viewer.scene.primitives.add(num_line);`    `viewer.scene.primitives.add(num_line1);`
    `var timex = 0;`    `function render() {`      `timex += 0.01;`      `if (timex >= 1.0) {`        `timex = 0; // 控制在0.0到1.0之间`      `}`          `      primi.appearance.material.uniforms.time.x = timex;`      `requestAnimationFrame(render);`    `}`    `requestAnimationFrame(render);

方法二:根据cesium 内置的材质类型实现。具体介绍各位可以去API文档查看,有哪些uniforms和各个属性代表的意思也写的很清楚。示例代码看addPrimitiveFlowAppear方法。

要注意:

1、cesium绘制地物有两种方式,一种是通过entity的方式。entity是cesium封装的一种高级接口,很适合上手入门。entity添加的地物可以使用如以下已经封装好的materialProperty 来组合各种材质效果,enetity详细内容参考官方文档,具体使用例子可以参考前面文章cesium property实现飞行实时姿态仿真中飞行尾部轨迹的实现

 另一种是primitive的方式,本文中这两个都是通过primitive来绘制几何体。他们的材质跟前面讲的property是不一样的机制,cesium通过primitive提高了渲染的自由度,让精通GLSL编程的开发者有更大的发挥舞台。在接口使用上的区别是:1、primitive通过appearance来给material赋值。2、上面列举的materialproperty是不可以在这里使用的,但是内置的几种类型材质可以使用,第二种实现方式实现就是利用内置的类型。

2、第二种实现方式中,通过内置材质类型的uniforms中的time必须是变化才能使其材质产生流动效果,因此为了让其变换,我们将其放到requstAnimation中,进行修改。有没有更好的实现方式呢,我们下期进行探讨。

本文转自 https://blog.csdn.net/qq_26991807/article/details/123429407,如有侵权,请联系删除。