当前位置: 首页 > article >正文

Cesium着色器的创意和方法(五——Polyline)

不接受反驳,线段在三维里面的渲染比多边形的渲染更复杂。因为线是没有宽度的,并且还需要时时刻刻向着你。

首先看下Cesium的线段的一些效果。这条线段非常宽(20个像素),有两个需要留意观察的。一是线段并非实时面对我,到了某个角度会重新调整朝向。二是远处跟地形还有点叠加冲突。

20241107_224526

1、线段是矩形

这个道理很多人都理解的。当前WebGL并不能凭空添加未知的点,因此需要用线段去模拟带宽度的线。

当然也不能直接是固定的矩形,因为这条线段还需要随着视野远近不断的改变,使之保持视觉上的一致。因此,线段的VertexArray(GeometryAttributes)跟普通的矩形不一样,它存储了position、prevPosition、nextPosition、expandAndWidth等数据。其中prevPosition和nextPosition是为了动态计算而进行存储的。

线段在渲染的顶点数是   顶点数*4-4。即一条线段(2个顶点)共计4个渲染顶点,两条线段(3个顶点)共计8个渲染顶点。亦即不考虑节点处的共享顶点情况。

2、expandAndWidth

它的存储数量跟渲染顶点数量一致,记录每个渲染顶点的朝向,或者说序号。对每个顶点它存储两个值,第一个值交替记录-1或者1,第二个值存储正负线宽(±lineWidth)。具体情况看下图。

3、 getPolylineWindowCoordinates

顾名思义,这个函数是要计算线段在屏幕上的位置。在这个函数中,Cesium会对每段线段进行空间判断,看看是否会被截断或丢弃。

这部分代码比较晦涩难懂。需要首先理解的是点投影到平面的公式,即

vec4 positionEC = czm_translateRelativeToEye(position.xyz, new vec3(0f));
vec4 positionPEC = czm_modelViewRelativeToEye * positionEC;
vec4 positionWC = czm_eyeToWindowCoordinates(positionPEC);

这里第一行是把全球空间笛卡尔位置转换到摄像头的相对位置,第二行是调整旋转角度,是一个View矩阵,第三行是把坐标转换为屏幕坐标,其中positionWC.xy是屏幕像素的位置。

其中EC为EyeCoordinate的简写,PEC是ProjectEyeCoordinate的简写,WC是windowCoordinate的简写。

Cesium判断线段被截断或丢弃的代码是clipLineSegmentToNearPlane函数,这个函数首先判断线段是否在近裁剪平面之前,方法是判断 czm_currentFrustum.x + positionPEC .z是否大于0。如果小于0,则表示不会被近裁剪面裁剪,反之会被截断或“灯下黑”。

czm_currentFrustum.x是近裁剪面的距离,为正值,Cesium在距离地面很远的情况,这个值并不是0.1,而可能是几万的值。

positionPEC .z是已经跟摄像头观察矩阵一致的坐标,因为Z轴代表正视方向。

4、线段宽度

第二部分谈论了线段宽度的传递,第三部分讨论了线段顶点在屏幕的坐标。设置线段宽度并不是像素级±宽度,而是需要利用线段前后节点的方向。因此计算方法可以简单的理解为

(positionWCPre-positionWCNext)的垂直向量*线段宽度

当然具体过程又复杂了,包括首尾节点的处理情况、垂直向量为Zero、顶点重叠等异常情况。

5、测试工具

glsl代码理解是很费神的一件事情,因为缺乏调试器。不过我为此做了一个小工具,采用C#来动态调试glsl。在开源项目里面,后面单独写篇文章介绍该程序的使用。ReprojectWebMercator: 仿照Cesium 的ReprojectWebMercator,可视化测试。


http://www.kler.cn/a/386755.html

相关文章:

  • websocket初始化
  • Java结合ElasticSearch根据查询关键字,高亮显示全文数据。
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • elementui el-table中给表头 el-table-column 加一个鼠标移入提示说明
  • LeetCode【0035】搜索插入位置
  • 什么时候需要复写hashcode()和compartTo方法
  • opencv保姆级讲解-guI和pymsql实现人脸识别打卡(6)
  • 【WebRTC】视频编码链路中各个类的简单分析——VideoEncoder
  • C++20 概念与约束(2)—— 初识概念与约束
  • 三分钟学会Docker基本操作,快速入门容器技术!
  • 还在网盘?分享百兆级大文件传输工具--Wormhole:不限速在线文件传输下载利器
  • Java 类和对象
  • Spring Boot开发入门教程
  • 第二届计算机网络技术与电子信息工程国际学术会议(CNTEIE 2024,12月6-8日)
  • Android 应用插件化及其进程关系梳理
  • Python异常检测 - LSTM(长短期记忆网络)
  • “2048”游戏网页版html+css+js
  • 100种算法【Python版】第40篇——卡恩算法
  • 基于springboot信用分析管理系统设计与实现
  • Linux下的 MySQL 中添加用户并设置远程访问
  • 十六:Spring Boot (1)-- spring-boot-starter 应用
  • EHOME视频平台EasyCVR视频融合平台支持哪些摄像机接入?监控摄像头镜头的种类有哪些?
  • 启明云端触觉智能与您相约2024年慕尼黑国际电子元器件博览会,不见不散!
  • 半年总结-还有很多要学习
  • clickhouse自增id的处理
  • JS 循环语句