近期有个需求是想使用自己的3d引擎去渲染地球逻辑,如果从头实现一遍会比较耗费时间,而且后续还要实现倾斜摄影等等,所以打算使用cesium来帮我们做调度然后用自己的3d引擎渲染。
在github上找到了个cesium-three发现该项目的策略是three.js去渲染three到物体,cesium去渲染cesium物体,这样实现起来比较容易,但是问题是当一个复杂场景出现的时候,排序怎么办,当然还有更多问题根本是无法解决的。正所谓一山不容二虎,当二虎有分歧时听谁的那?
看了下cesium代码发现cesium的逻辑和渲染分离的比较好,每帧的渲染就是执行最终的drawCommand,本来以为一天就能搞定,没想到还是花了几天时间,里面还是涉及到一些细节问题,现在分享给大家思路和方法(目前cesium地球调度还有一两个小点没有完全弄清楚,不过我这边选择了跳过,不影响瓦片逻辑,如果有知道的大神欢迎评论和指导,目前自己的引擎我暂且使用three.js来表示吧)

渲染顺序如下:

  1. frameState的更新-----主要是传入Cesium需要的framestate需要的各种参数,摄影机,viewPort,视锥等
    这其中我们需要禁掉一些cesium不必要的开销,如阴影等等(因为阴影我们还是要用自己的引擎实现),当然由于摄影机操作也需要自己实现一套,摄影机操作和更新肯定是自己的引擎做的事情,同时cesium摄影机也并不太符合自己的操作习惯,摄影机操作其实也不是太简单,后续有时间也可以分享一下

  2. Cesium调度------主要是地块数据的创建与更新 + image的请求与下载,这一块基本上是最复杂的,需要完全理清楚cesium的逻辑,其中需要把一些不必要的逻辑停掉,尽量最大化性能(比如pick肯定要停掉,因为pick肯定是自己的引擎去实现,一定要明确一个思路,只用cesium地球调度,所以无关紧要的全部停掉,使性能达到最优)。当然中间还需要停掉cesium很多逻辑,如attribute的创建和上传(cesium直接创建buffer了这可不行,浪费内存啊),贴图sample对象的创建等等

  3. 渲染-----这时候我们拿到当前帧要渲染的地块tile(上面有imagery, data等各种信息),然后就去创建mesh挂到我们自己的scene下面执行渲染。每帧先清空地球节点下面的所有mesh,然后这帧cesium告诉我们渲染哪些就去挂上去(这样做完全是模拟cesium的drawCommand逻辑)。当然这里要做好mesh的缓存,material的缓存,texture的缓存以及各种uniform对象的缓存(其实这里还有个比较核心的就是地球的shader,这个其实还是比较复杂的,后续再花时间补上吧)

哎,说个小插曲,刚开始做的时候我理清楚了这个逻辑,但是由于我们这边渲染引擎的渲染比较复杂,导致我cesium的更新没有在引擎渲染之前(我一直以为是执行的上述逻辑,哎),然后一直出现缩小两边闪白块的问题(其实白块就是因为地球没有渲染,那一块白色的其实是大气。我还曾经一度怀疑是cesium将前后几帧的图全渲到targetBuffer然后混合出的结果那,但是实验了一下发现不是。最后又找了自己的原因,原来是先执行渲染了,相当于比cesium快了一帧)

下面详细说一下这三步如何实现的:
1.第一步 frameState的更新:
查看一下frameState这个类,看看里面都需要传入哪些信息,这一步应该比较容易,当然pick,depth,postProcess,creditDisplay(证书),shadow这些逻辑我们不需要(如果需要当然是用自己的引擎实现,不需要额外的开销)。fog的话其实可以使用cesium的逻辑,计算出fog的浓度,但是我这边自己实现了fog,所以也禁掉了fog的逻辑。
第一步核心就是摄影机和视锥,具体信息如下
frameState.camera = {
positionWC:frameState.positionWC,
positionCartographic: frameState.positionCartographic,
directionWC:frameState.directionWC,
frustum:frameState.perspectiveOffCenterFrustum,
}
frameState.cullingVolume = frameState.perspectiveOffCenterFrustum.computeCullingVolume(frameState.positionWC, cameraDirectionWC, cameraUpWC);
(很多参数具体追一下cesium代码就知道如何计算的,不过要注意webgl引擎坐标系和cesium坐标系的转换)

2.第二步 cesium调度
首先要先理清cesium的地块渲染逻辑(这里由于篇幅原因不详细讲了,如果不清楚,cesium最长的一帧可以参考一下)
我们目前只是使用地块最核心的部分自己去手动调接口进行渲染调度,
(1)首先创建QuadtreePrimitive
(2)beginFrame: 接下来就可以可以开始调用它的接口手动更新了
直接调用:this._surface.beginFrame(this._frameState),这里主要是释放和创新创建0级的tile,不需要做更改
(3)render: 这块是比较核心的地方:直接调用this._surface.render(this._frameState);

这里把endUpdate干掉,其实我们的draw基本就是和endUpdate做一样的事情(生成drawComand,使用var tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;最终的这个tilesToRenderByTextureCount数据,从里面取我们的tile,imagery和terrian),当然和pick有关的逻辑一定要干掉,接下来就是调用selectTilesForRendering来获取当前需要创建的网格(不过这些可能需要对一些参数进行相应的更改,毕竟像context这种webgl的上下文我们不可能传入framestate中,当然render之后你如果需要使用cesium的截流或者别的功能也可以手动去更新)
(4)endFrame:接下来就是最核心的部分:直接调用this._surface.endFrame(this._frameState);在processTileLoadQueue中,遍历更新队列中所有的GlobeSurfaceTile,解析tile数据,下载图片

测试发现updateHeighs在持续飞行很长时间会掉帧很厉害,这块我先注释掉了,没有细看,如果有知道的可以留言,谢谢
接下来就是 GlobeSurfaceTile.processStateMachine,这里会遍历所有tile如果状态是START就去prepareNewTile,如果是LOADING就去processTerrainStateMachine,这里处理地形的下载以及地块网格的生成逻辑,水面的生成。这部分cesium解析成功之后就直接去生成attribute了,我们要做的就是跳过attribute的逻辑,手动去标记地块(地形)网格ready的状态。
接下来就是图片的下载,这部分处理起来最复杂,我刚开始是用自己的引擎去下载图片资源,虽然没问题,但是就无法使用cesium的截流(可以设置每帧最大请求数,多余请求可以拦截下来,这样再持续飞行的时候能够解决内存泄露的问题)。所以建议还是使用cesium的下图逻辑,但是拦截掉sampler的创建就行了,不过注意需要绑定texture对象,因为cesium在没有下载到新图的时候回递归查找最近的图,这一点很重要,具体细节可以看TileImagery.prototype.processStateMachine的逻辑。
reprojectTexture我们可以不需要,将其与createTexture合并在一起,然后重点修改createTexture的代码,将创建sampler的代码改成自己引擎生成texture的代码即可。(好了,cesium代码基本改造完了,对了,还有卸载,在cesium卸载tile和image的时候注意卸载你自己的资源就行了)
3最后一步:自己引擎的渲染逻辑,由于是大尺度下的渲染,所以引擎首先要实现logDepth。然后开始准备地球的shader(就是把cesium的shader看一遍,理解了就行了,不过注意一些坐标转换,当然这部分也有一定难度,后续可以分享一下)。然后就可以开始渲染逻辑了。专门为地球创建一个节点,然后每帧先清空,然后遍历this._surface.tileProvider._tilesToRenderByTextureCount去执行渲染,注意缓存tile和material,也要注意缓存uniform,这一块实现之后一个流畅的地球已经出现了,没想到完美实现一个hello world并不是那么容易

当然我们可以加入各种地图滤镜效果:

使用three.js渲染瓦片地球-第一篇相关推荐

  1. 关于学习渲染的心得第一篇

    学习渲染没有捷径那就是经验和感觉,首先要做的是对于渲染插件的熟悉,在不熟悉软件的情况怎么看视频都是白扯,材质,灯光,一定要在自己亲身渲染的过程中去领悟,养成自己的一套渲染习惯,灯光的打法基本都差不多, ...

  2. threejs 绘制球体_Three.js 第一篇:绘制一个静态的3D球体

    第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地 ...

  3. vue 单相绑定_Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)...

    Vuejs第一篇之入门教程详解(单向绑定.双向绑定.列表渲染.响应函数) 2018-12-30 什么是组件? 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素 ...

  4. html仿qq最小化怎么实现,JS仿QQ好友列表展开、收缩功能(第一篇)

    JS仿QQ好友列表展开.收缩功能(第一篇) 发布时间:2020-10-17 14:20:03 来源:脚本之家 阅读:96 作者:erdouzhang 效果图如下所示: html: 我的好友 张三 李四 ...

  5. 第一篇:web之前端之html

    前端之html 前端之html 本节内容 前端概述 html结构 标签探秘 <!DOCTYPE html>标签 head标签 body标签 1.前端概述 一个web服务的组成分为前端和后端 ...

  6. 【前端三剑客三】JavaScript手术刀剖析第一篇

    文章目录 一.初始JavaScript 1.JavaScript是什么 2.JavaScript . HTML . CSS 之间的关系 3.JavaScript 运行过程 4.JavaScript 的 ...

  7. Vue项目实战 —— 后台管理系统( pc端 ) 第一篇

    前期回顾     我只写注释 -- 让Ai写代码_0.活在风浪里的博客-CSDN博客前期回顾 Vue项目实战 -- 哔哩哔哩移动端开发-- 第二篇_0.活在风浪里的博客-CSDN博客https://b ...

  8. Webpack系列-第一篇基础杂记

    系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 公司的前端项目基本都是用Webpack来做工程化的,而Webpack虽然 ...

  9. 微信公众号开发入门教程第一篇

    微信公众号开发入门教程第一篇 关键字:微信公众平台开发 作者:方倍工作室 在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序.MySQL数据库.计算机网络通讯.及HTTP/XML/CSS/ ...

最新文章

  1. 空类,虚函数类,虚继承类的空间大小
  2. +[NSTimer scheduledTimerWithTimeInterval:repeats:block:]: unrecognized selector sent to xxx
  3. 成长型思维模式Not yet
  4. python opencv findcontours_OpenCV之视频分析 – 背景消除与前景ROI提取
  5. 如果股市出现震荡行情,投资者应如何应对?
  6. 直击平昌!2天40位大咖的平昌区块链论坛精华都在这了!
  7. Struts2中的ModelDriven机制及其运用、refreshModelBeforeResult属性解决的问题
  8. 拓端tecdat|R语言用泊松Poisson回归、GAM样条曲线模型预测骑自行车者的数量
  9. 废弃qq号大全密码2020_被永久封禁的QQ号解封历程
  10. 前台登录账号改变时迅速清空记录的登录密码
  11. SHT20温湿度传感器工作原理
  12. Python爬虫 | 手把手教你扒一扒贝壳网成交房源数据
  13. 停止dockerd进程
  14. dell服务器系统备份软件,使用 AlienRespawn 备份 Alienware 电脑的系统
  15. android:layout_height=match_parent和android:layout_marginTop=100dp同时作用
  16. Linux分区efi,什么时候建立分区的时候需要建立EFI分区
  17. lemonldap java_Java LDAP操作
  18. K8s 污点(Taints)与容忍(Tolerations)
  19. c++ 发邮件(含附件)
  20. 计算机cfd教学,CFD数值模拟过程

热门文章

  1. 7-20 空心字母金字塔
  2. oracle学习第二天
  3. wps2019数据分析加载项_WPS加载项——集成创新 体验升级
  4. 微信开发常用文档及参考资料
  5. vue如何将图片压缩成webp格式并用webpack打包
  6. 6.网络技术——路由器原理:静态路由+默认路由(后附实验习题)
  7. 如何创建自己的网站平台?
  8. HC32L110国产超低功耗华大MCU芯片介绍
  9. apche 反射api的使用心得
  10. Python计算机视觉——第四章 照相机模型与增强现实