Ceisum 自定义Primitive 并使用双精度RTC解决随视角转动模型抖动的情况

主要参考:

1.精度丢失导致扭曲与抖动-CSDN博客

2.Cesium DrawCommand [1] 不谈地球 画个三角形 - 岭南灯火 - 博客园 (cnblogs.com)

3.溯源:Cesium.Appearance 中的顶点着色器 - 岭南灯火 - 博客园 (cnblogs.com)

使用自定义Primitive主要是为了自定义着色器 来完成一些更加灵活自由的操作

之前使用自定义 Primitive添加三角网时 随着视角转动 三角网抖动的非常严重

查了一下才发现是向着色器传点时存在精度问题导致的

外部点的精度可能大于着色器的最大精度 所以会有抖动的现象

自定义Primitive 的代码不是重点 以后有时间了再开一个帖子讲

这个帖子主要解决精度问题导致的抖动

由于Cesium 要加载整个地球的坐标 那对于地表上的某一点可能坐标的值就非常大了 小数位数很多

这就产生了精度问题

我一开始觉得有精度问题 那直接在传点时把绝对坐标转为相对坐标 或者直接限制小数位数

这样不就可以了吗?

但是经过试验发现 这样还是存在抖动的现象 并没有解决问题

但是使用Cesium原生的api加载一些多边形时肯定是没有这个问题的

那Cesium是如何解决这个问题的呢?

就是利用了双精度+RTC

双精度是指Cesium会把本来精度较大的值拆成两个精度较小的值 这样传入着色器时就避免了因为精度不同导致的误差

代码如下

const eCartesian3 = Cesium.EncodedCartesian3.fromCartesian(cartesian);

得到的eCartesian3  中有high和low两个成员 分别记录高精度的值和低精度的值

关系为eCartesian3 .high+eCartesian3 .low=cartesian

之后便是往着色器里传值

首先定义一个attributeLocations  

  const attributeLocations = {
    "position3DHigh": 0,
    "position3DLow": 1,
  }

然后生成两个VertexArray  分别对应High 和 Low


  const positionBufferHigh = Cesium.Buffer.createVertexBuffer({
    usage: Cesium.BufferUsage.STATIC_DRAW,
    typedArray: positionsHigh,
    context: frameState.context,
  });
   const positionBufferLow = Cesium.Buffer.createVertexBuffer({
    usage: Cesium.BufferUsage.STATIC_DRAW,
    typedArray: positionsLow,
    context: frameState.context,
  });
  const vertexArray = new Cesium.VertexArray({
    context: frameState.context,
    attributes: [{
      index: 0, 
      vertexBuffer: positionBufferHigh,
      componentsPerAttribute: 3,
      componentDatatype: Cesium.ComponentDatatype.FLOAT
    },
                {
      index: 1, 
      vertexBuffer: positionBufferLow,
      componentsPerAttribute: 3,
      componentDatatype: Cesium.ComponentDatatype.FLOAT
    }]
  })

之后就是着色器的部分 只用修改顶点着色器即可

const vertexShaderText = `in vec3 position3DHigh ;
                          in vec3 position3DLow ;
void main() {
  vec4 localpoint=czm_translateRelativeToEye(position3DHigh,position3DLow);
 
  gl_Position = czm_modelViewProjectionRelativeToEye * localpoint;
}`

czm_translateRelativeToEye 函数是将点坐标转换到相机坐标系下(仅位移) 

相机的坐标也是用双精度存储的 这就是所谓的RTC 

将绝对坐标转为相对坐标 以缩小坐标的值 提高精度

效果展示:

未使用双精度时: 抖动非常严重

使用了双精度:几乎和原生的三角形api效果一致了

三角网也不再抖动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值