cesium 发光线

news2024/9/30 13:46:09

发光线也是一种比较常见的可视化效果,cesium 内置的材质已经提供了PolylineGlowMaterialProperty类,实现了发光效果。这种材质在线的中间部分始终会有白色线条,如果想实现纯色的发光线,就需要对这种材质进行改造。本篇通过自定义MaterialProperty提供两种发光线材质。

1. 自定义GlowLineMaterialProperty类

1.1. 自定义 GlowLineMaterialProperty 类
/*
 * @Description: 
 * @Author: maizi
 * @Date: 2024-08-16 15:06:46
 * @LastEditTime: 2024-08-27 17:10:15
 * @LastEditors: maizi
 */

function GlowLineMaterialProperty(options) {
  options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);

  this._definitionChanged = new Cesium.Event();
  this._color = undefined;
  this._power = undefined;
 
  this.color = options.color || Cesium.Color.fromBytes(0, 255, 255, 255);
  this.power = options.power || 0.25;
}

Object.defineProperties(GlowLineMaterialProperty.prototype, {
  isConstant: {
    get: function () {
      return (
        Cesium.Property.isConstant(this._color) 
        && Cesium.Property.isConstant(this._power)
      );
    },
  },

  definitionChanged: {
    get: function () {
      return this._definitionChanged;
    },
  },

  color: Cesium.createPropertyDescriptor("color"),
  power: Cesium.createPropertyDescriptor("power")
});


GlowLineMaterialProperty.prototype.getType = function (time) {
  return "GlowLine";
};

GlowLineMaterialProperty.prototype.getValue = function (time, result) {
  if (!Cesium.defined(result)) {
    result = {};
  }

  result.color = Cesium.Property.getValueOrClonedDefault(this._color, time);
  result.power = Cesium.Property.getValueOrClonedDefault(this._power, time);
  return result;
};


GlowLineMaterialProperty.prototype.equals = function (other) {
  const res = this === other || (other instanceof GlowLineMaterialProperty &&
    Cesium.Property.equals(this._color, other._color) &&
    Cesium.Property.equals(this._power, other._power))
  return res;
};
export default GlowLineMaterialProperty;
1.2. 材质shader
uniform vec4 color;
uniform float power;

czm_material czm_getMaterial(czm_materialInput materialInput)
{ 
  czm_material material = czm_getDefaultMaterial(materialInput);
  vec2 st = materialInput.st;
  float glow = power / abs(st.t - 0.5) - (power / 0.5);
  material.alpha = clamp(0.0, 1.0, glow);
  material.diffuse = color.rgb;
  return material;
}
1.3. 添加到缓存
/*
 * @Description: 
 * @Author: maizi
 * @Date: 2024-08-16 16:21:55
 * @LastEditTime: 2024-08-26 18:00:42
 * @LastEditors: maizi
 */
import GlowLinetMaterial from '../shader/GlowLinetMaterial.glsl'

Cesium.Material.GlowLine = 'GlowLine'
Cesium.Material._materialCache.addMaterial(
  Cesium.Material.GlowLine,
  {
    fabric: {
      type: Cesium.Material.GlowLine,
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.7),
        power: 0.25
      },
      source: GlowLinetMaterial,
    },
    translucent: function (material) {
      return true
    },
  }
)

2. 自定义ImageGlowLineMaterialProperty类

2.1. 自定义ImageGlowLineMaterialProperty类
/*
 * @Description: 
 * @Author: maizi
 * @Date: 2024-08-16 15:06:46
 * @LastEditTime: 2024-08-27 17:17:09
 * @LastEditors: maizi
 */

function ImageGlowLineMaterialProperty(options) {
  options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);

  this._definitionChanged = new Cesium.Event();
  this._color = undefined;
  this._image = undefined;
 
  this.color = options.color || Cesium.Color.fromBytes(0, 255, 255, 255);
  this.image = options.image;
}

Object.defineProperties(ImageGlowLineMaterialProperty.prototype, {
  isConstant: {
    get: function () {
      return (
        Cesium.Property.isConstant(this._color) 
        && Cesium.Property.isConstant(this._image)
      );
    },
  },

  definitionChanged: {
    get: function () {
      return this._definitionChanged;
    },
  },

  color: Cesium.createPropertyDescriptor("color"),
  image: Cesium.createPropertyDescriptor("image")
});


ImageGlowLineMaterialProperty.prototype.getType = function (time) {
  return "ImageGlowLine";
};

ImageGlowLineMaterialProperty.prototype.getValue = function (time, result) {
  if (!Cesium.defined(result)) {
    result = {};
  }

  result.color = Cesium.Property.getValueOrClonedDefault(this._color, time);
  result.image = Cesium.Property.getValueOrClonedDefault(this._image, time);
  return result;
};


ImageGlowLineMaterialProperty.prototype.equals = function (other) {
  const res = this === other || (other instanceof ImageGlowLineMaterialProperty &&
    Cesium.Property.equals(this._color, other._color) &&
    Cesium.Property.equals(this._image, other._image))
  return res;
};
export default ImageGlowLineMaterialProperty;
2.2. 材质shader
uniform sampler2D image;
uniform vec4 color;

czm_material czm_getMaterial(czm_materialInput materialInput){
  czm_material material = czm_getDefaultMaterial(materialInput);
  vec2 st = materialInput.st;
  vec4 colorImage = texture(image,st);
  vec3 fragColor = color.rgb;
  material.alpha = colorImage.a * color.a * 3.;
  // 设置中间发光图片的颜色占比
  if(st.t < 0.55 && st.t > 0.45) {
    material.diffuse = colorImage.rgb;
  } else {
    material.diffuse = fragColor.rgb;
  }
  
  return material;
}
2.3. 添加到缓存
/*
 * @Description: 
 * @Author: maizi
 * @Date: 2024-08-16 16:21:55
 * @LastEditTime: 2024-08-26 18:00:42
 * @LastEditors: maizi
 */
import ImageGlowLinetMaterial from '../shader/ImageGlowLinetMaterial.glsl'

Cesium.Material.ImageGlowLine = 'ImageGlowLine'
Cesium.Material._materialCache.addMaterial(
  Cesium.Material.ImageGlowLine,
  {
    fabric: {
      type: Cesium.Material.ImageGlowLine,
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.7),
        image: Cesium.Material.DefaultImageId,
      },
      source: ImageGlowLinetMaterial,
    },
    translucent: function (material) {
      return true
    },
  }
)

3. 完整示例代码

GlowLine.js

/*
 * @Description:
 * @Author: maizi
 * @Date: 2022-05-27 11:36:22
 * @LastEditTime: 2024-08-27 18:27:19
 * @LastEditors: maizi
 */
const merge = require('deepmerge')
import { GlowLineMaterialProperty, ImageGlowLineMaterialProperty } from '../../materialProperty/index.js'
const defaultStyle = {
  power: 0.25,
  color: "#ffff00",
  lineWidth: 8,
  type: 0
}

class GlowLine {
  constructor(viewer, coords, options = {}) {
    this.viewer = viewer
    this.coords = coords;
    this.options = options;
    this.props = this.options.props;
    this.style = merge(defaultStyle, this.options.style || {});
   
    this.entity = null;
    this.material = null
    this.points = []
    this.init();
  }

  init() {
    this.createMaterial();
    this.entity = new Cesium.Entity({
      id: Math.random().toString(36).substring(2),
      type: "glow_line",
      polyline: {
        positions: this.getPositons(),
        width: this.style.lineWidth,
        material: this.material,
        //clampToGround: true
      }
    });
  }

  addPoints() {
    this.coords.forEach((coord) => {
      const point = new Cesium.Entity({
        position: Cesium.Cartesian3.fromDegrees(coord[0],coord[1],coord[2]),
        point: {
          color: Cesium.Color.DARKBLUE.withAlpha(.4),
          pixelSize: 6,
          outlineColor: Cesium.Color.YELLOW.withAlpha(.8),
          outlineWidth: 4
        }     
      }); 
      this.viewer.entities.add(point)
      this.points.push(point)
    })
  }

  removePoints() {
    this.points.forEach((point) => {
      this.viewer.entities.remove(point)
    })
    this.points = []
  }

  getPositons() {
    const positions = []
    this.coords.forEach((coord) => {
      positions.push(Cesium.Cartesian3.fromDegrees(coord[0], coord[1], coord[2]));
    })
    return positions
  }

  createMaterial() {
    switch(this.style.type){
      case 0:
        this.material = new GlowLineMaterialProperty({
          color: new Cesium.Color.fromCssColorString(this.style.color),
          power:this.style.power
        });
        break
      case 1:
        this.material = new ImageGlowLineMaterialProperty({
          color: new Cesium.Color.fromCssColorString(this.style.color),
          image: require("@/assets/img/glow_line.png"),
        });
        break
    }
   
  }

  updateStyle(style) {
    this.style = merge(defaultStyle, style);
    this.entity.polyline.width = this.style.lineWidth
    this.material.color = new Cesium.Color.fromCssColorString(this.style.color)
    if(this.style.type === 0) {
      this.material.power = this.style.power
    }
  }

  setSelect(enabled) {
    if (enabled) {
      this.addPoints()
    } else {
      this.removePoints()
    }
  }
}

export {
  GlowLine
}

MapWorks.js

import GUI from 'lil-gui'; 
// 初始视图定位在中国
import { GlowLine } from './GlowLine'

Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(90, -20, 110, 90);

let viewer = null;
let graphicLayer = null
let graphicList = []
let selectGraphic = null
let eventHandler = null
let gui = null

function initMap(container) {
  viewer = new Cesium.Viewer(container, {
    animation: false,
    baseLayerPicker: false,
    fullscreenButton: false,
    geocoder: false,
    homeButton: false,
    infoBox: false,
    sceneModePicker: false,
    selectionIndicator: false,
    timeline: false,
    navigationHelpButton: false, 
    scene3DOnly: true,
    orderIndependentTranslucency: false,
    contextOptions: {
      webgl: {
        alpha: true
      }
    }
  })
  viewer._cesiumWidget._creditContainer.style.display = 'none'
  viewer.scene.fxaa = true
  viewer.scene.postProcessStages.fxaa.enabled = true
  if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
    // 判断是否支持图像渲染像素化处理
    viewer.resolutionScale = window.devicePixelRatio
  }
  // 移除默认影像
  removeAll()
  // 地形深度测试
  viewer.scene.globe.depthTestAgainstTerrain = true
  // 背景色
  viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.0, 0.0, 0)
  // 太阳光照
  viewer.scene.globe.enableLighting = true;

  // 初始化图层
  initLayer()
  // 初始化鼠标事件
  initClickEvent()

  //调试
  window.viewer = viewer
}

function initGui() {
  let params = {
    ...selectGraphic.style
  }
  gui = new GUI()
  let layerFolder = gui.title('样式设置')
  if (params.type === 0) {
    layerFolder.add(params, 'power', 0, 1).step(0.01).onChange(function (value) {
      selectGraphic.updateStyle(params)
    })
  }
  layerFolder.add(params, 'lineWidth', 1, 30).step(1).onChange(function (value) {
    selectGraphic.updateStyle(params)
  })
  layerFolder.addColor(params, 'color').onChange(function (value) {
    selectGraphic.updateStyle(params)
  })
}


function initLayer() {
  const layerProvider = new Cesium.ArcGisMapServerImageryProvider({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  });
  viewer.imageryLayers.addImageryProvider(layerProvider);
  graphicLayer = new Cesium.CustomDataSource('graphicLayer')
  viewer.dataSources.add(graphicLayer)
}

function loadGrowLine(lines) {
  lines.forEach(line => {
    const glowLine = new GlowLine(viewer, line.points, {
      style: line.style
    })
    graphicList.push(glowLine)
    graphicLayer.entities.add(glowLine.entity)
  });
  viewer.flyTo(graphicLayer)
}

function initClickEvent() {
  eventHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  initLeftClickEvent()
  initMouseMoveEvent()
}

function initLeftClickEvent() {
  eventHandler.setInputAction((e) => {
    if (selectGraphic) {
      selectGraphic.setSelect(false)
      selectGraphic = null
    }
    if (gui) {
      gui.destroy()
    }
    let pickedObj = viewer.scene.pick(e.position);
    if (pickedObj && pickedObj.id) {
      if (pickedObj.id.type === 'glow_line') {
        selectGraphic = getGraphicById(pickedObj.id.id)
        if (selectGraphic) {
          selectGraphic.setSelect(true)
          initGui()
        }
      }
    }
  },Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

function initMouseMoveEvent() {
  eventHandler.setInputAction((e) => {
    const pickedObj = viewer.scene.pick(e.endPosition);
    if (pickedObj && pickedObj.id) {
      if (pickedObj.id.type === 'glow_line') {
        // 改变鼠标状态
        viewer._element.style.cursor = "";
        document.body.style.cursor = "pointer";
      } else {
        viewer._element.style.cursor = "";
        document.body.style.cursor = "default";
      }
    } else {
      viewer._element.style.cursor = "";
      document.body.style.cursor = "default";
    }
  },Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}

function getGraphicById(id) {
  let line = null
  for (let i = 0; i < graphicList.length; i++) {
    if (graphicList[i].entity.id === id) {
      line = graphicList[i]
      break
    } 
  }
  return line
}

function removeAll() {
  viewer.imageryLayers.removeAll();
}

function destroy() {
  viewer.entities.removeAll();
  viewer.imageryLayers.removeAll();
  viewer.destroy();
}


export {
  initMap,
  loadGrowLine,
  destroy
}

GlowLine.vue

<!--
 * @Description: 
 * @Author: maizi
 * @Date: 2023-04-07 17:03:50
 * @LastEditTime: 2024-08-27 17:02:06
 * @LastEditors: maizi
-->

<template>
  <div id="container">
  </div>
</template>

<script>
import * as MapWorks from './js/MapWorks'
export default {
  name: 'GlowLine',
  mounted() {
    this.init();
  },
  methods:{
    init(){
      let container = document.getElementById("container");
      MapWorks.initMap(container)
      let lines = [
        {
          points: [
            [104.068822,30.654807,10],
            [104.088822,30.654807,10],
          ],
          style: {
            type: 0
          },

        },
        {
          points: [
            [104.068822,30.655807,10],
            [104.088822,30.655807,10],
          ],
          style: {
            type: 1
          },
        },
      ];
      MapWorks.loadGrowLine(lines)
    }
  },

  beforeDestroy(){
    //实例被销毁前调用,页面关闭、路由跳转、v-if和改变key值
    MapWorks.destroy();
  }
}
</script>

<style lang="scss" scoped>
#container{
  width: 100%;
  height: 100%;
  background: rgba(7, 12, 19, 1);
  overflow: hidden;
  background-size: 40px 40px, 40px 40px;
  background-image: linear-gradient(hsla(0, 0%, 100%, 0.05) 1px, transparent 0), linear-gradient(90deg, hsla(0, 0%, 100%, 0.05) 1px, transparent 0);
}


</style>

4. 运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2087486.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VTK随笔十:VTK图形处理(封闭性检测、联通区域分析、多分辨率处理)

一、封闭性检测 如果一条边只被一个多边形包含&#xff0c;那么这条边就是边界边。 是否存在边界边是检测一个网格模型是否封闭的重要特征。 vtkFeatureEdges是一个非常重要的类&#xff0c;该类能够提取多边形网格模型中四种类型的边。 1)边界边。即只被一个多边形或者…

解释预测的艺术

如何以人性化的方式解释你的模型 可直接在橱窗里购买&#xff0c;或者到文末领取优惠后购买&#xff1a; 数据科学家职责的一个重要部分是解释模型预测。通常&#xff0c;接受解释的人不是技术人员。如果你开始谈论成本函数、超参数或 p 值&#xff0c;你将会遇到茫然的表情。我…

List集合和Set集合

Collection&#xff1a; Collection 不唯一&#xff0c;无序 List 不唯一&#xff0c;有序 Set 唯一&#xff0c;无序 ArrayList&#xff1a;内部使用长度可变的数组&#xff0c;遍历查询效率高 LinkedList&#xff1a;采用双向链表实现&#xff0c;增删改效率比较高 ArrayL…

【小白深度学习入门】【2】池化层详解:工作原理、维度计算、池化类型

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

Dataworks_PySpark开发流程

PySpark是由Spark官方开发的Python语言第三方库&#xff0c;Python开发者可以通过使用python语言来编写Spark程序和SparkSQL完成开发。 之所以采用PySpark而不采用Java/Scala&#xff0c;是由于&#xff1a; Dataworks可通过将代码在线写入DataWorks Python资源的方式&#xf…

Android 12系统源码_输入系统(一)认识Android的输入系统

前言 问渠那得清如许&#xff0c;为有源头活水来。对于大多数现代操作系统中&#xff0c;“事件”就是它们的“活水源头”&#xff0c;正是在“事件和消息”的不断产生、流转和处理中&#xff0c;整个软件系统才能“动”起来。 Android系统有一套从底层Linux内核到上层应用程…

合宙LuatOS产品规格书——Air780EQ

合宙Air780EQ&#xff0c; 基于移芯EC716E高端平台&#xff0c; 集成LTE 3GPP Release 13技术&#xff0c;确保高速、稳定的网络连接&#xff1b; 广泛兼容各大运营商网络&#xff0c;实现真正的全网通设计&#xff0c;提升产品市场适应性与灵活性。 Air780EQ 4G全网通模块核…

Unity(2022.3.41LTS) - 角色控制器和3D刚体

目录 一. 角色控制 二. 3D刚体 一. 角色控制 名称&#xff1a;功能&#xff1a;坡度限制将碰撞器限制为仅爬升比指示值更陡峭&#xff08;以度为单位&#xff09;的斜坡。步长偏移只有当楼梯离地面比指示值更近时&#xff0c;角色才会爬上楼梯。此值不应大于 Character Contr…

追求全能还是专精?——AI模型的未来趋势探讨

AI模型&#xff1a;追求全能还是专精&#xff1f; 近日&#xff0c;OpenAI预计在秋季推出代号为“草莓”的新AI。从专注于数学问题到处理主观营销策略&#xff0c;"草莓"模型展现出惊人的多样性。而这种全能型 AI 是否代表了未来趋势&#xff1f;相比专攻于某一领域的…

【离线查询 滑动窗口】2747. 统计没有收到请求的服务器数目

本文涉及知识点 离线查询 C算法&#xff1a;滑动窗口总结 LeetCode2747. 统计没有收到请求的服务器数目 给你一个整数 n &#xff0c;表示服务器的总数目&#xff0c;再给你一个下标从 0 开始的 二维 整数数组 logs &#xff0c;其中 logs[i] [server_id, time] 表示 id 为…

【Kafka】Windows下安装Kafka(全面)

目录 1.前提条件 2.下载 3.安装 4.环境变量配置 5.验证 1.前提条件 1.先安装zookeeper&#xff1a; 【Zookeeper】Windows下安装Zookeeper&#xff08;全面&#xff09;-CSDN博客https://blog.csdn.net/weixin_57259781/article/details/141679454 2.还需要安装scala: …

设计模式 -- 外观模式(Facade Pattern)

1 问题引出 组建一个家庭影院 DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能&#xff0c;其过程为&#xff1a; 直接用遥控器&#xff1a;统筹各设备开关 开爆米花机&#xff0c;放下屏幕 &#xff0c;开投影仪 &#xff0c;开音响&#xf…

坐牢第三十二天(c++)

一.作业 仿照string类&#xff0c;实现myString #include <iostream> #include <cstring> // 引入cstring以使用memcpy using namespace std; class myString {char *str; // 记录c风格的字符串int size; // 记录字符串的实际长度 public:// 无参构造myString():…

循环流网络的费用问题

循环流网络的费用问题 费用为负的网络流循环流网络的费用一些题目[UVa1659 Help Little Laura](https://onlinejudge.org/index.php?optioncom_onlinejudge&Itemid8&category24&pageshow_problem&problem4534)[Aizu-2230 How to Create a Good Game](https://…

[LLM][Prompt Engineering]:思维链(CoT)

思维链 思维链1. 思维链提示方法和增强策略1.1 简单的思维链提示1.2 示例形式的思维链提示1.3 思维链提示的后处理方案1.4 拓展推理结构 2. CoT的能力来源&#xff1a;为什么思维链提示能显著提升大语言模型在推理任务上的效果&#xff1f; 强大的逻辑推理是大语言模型“智能涌…

深度学习——LLM大模型分词

1. 前言 自从chatgpt出现&#xff0c;大模型的发展就进入了快车道&#xff0c;各种各样的大模型卷上天&#xff0c;作为一个在大模型时代的科研人&#xff0c;即使你不向前&#xff0c;也会被时代裹挟着向前&#xff0c;所以还是自己走快一点比较好&#xff0c;免得被后浪拍死…

呆错图床系统,一款开源免费的图床系统

源码介绍 呆错图床系统是一款免费的PHP图床程序&#xff0c;核心功能是提供图片外链服务、图床API服务、图片CDN加速与破解防盗链。 下载地址&#xff1a; https://download.csdn.net/download/huayula/89693127

基于七牛云上传,下载文件

准备工作 1.创建一个七牛云账号 2.登录账号&#xff0c;进入个人中心&#xff0c;创建一组密钥&#xff08;ak和sk&#xff09; 3. 创建一个公有的存储空间&#xff08;桶&#xff09; 注&#xff1a;存储地区的选择基于你的用户的分布主要在哪里。 七牛云直接白送10GB给我们…

给鼠标一个好看的指针特效 鼠标光标如何修改形状?

许多爱美的小伙伴们都想着如何给自己的电脑打扮一下&#xff0c;用各种各样的途径来美化我们的电脑。今天我们给大家分享一下&#xff0c;如何美化鼠标效果&#xff0c;给鼠标指针修改成一个非常好看的形状~ 一起来看几组鼠标的效果&#xff0c;小编我给大家做了个录屏&#x…

LuaJit分析(十一)去除string.dump函数

Lua脚本中的string.dump函数用于生成字节码文件&#xff0c;根据对 luajit -b命令的分析可以得出&#xff0c;最终dump出字节码文件都是使用的string.dump函数。 因此即使我们的指令顺序被打乱&#xff0c;通过loadfile系统调用&#xff0c;再通过string.dump调用&#xff0c;…