2.5 Cesium視域分析的實現

Cesium 視域分析html

好玩的東西你們都喜歡,但好玩又難嚼的東西就總讓人心癢癢。視域分析應該說是GIS空間分析裏比較經典又實用很廣的功能,理論起來很簡單,就是看得見與看不見的區分,上面實現的功能看得見綠色表示,看不見紅色表示,對於工程師而已就是0與1的區分。函數

那麼怎麼來實現呢?在羣裏屢次討論過,爲尋方便,就放這裏了。this

首先要明確一點,實現視域分析思路並不難,關鍵在於細節處理。記住這點,你就能實現它!spa

僅僅利用Cesium自帶的API來懟出來是不太切合實際的,看過有人畫面來貼建築,示意線也畫出來了,但真的好無趣,最後只能是浪費大量時間。咱們地走正路,從圖形學的角度出發,實現視域分析大方向能夠經過模板和深度來實現,可能有的人眼前一亮,0與1之間的區分,模板不是最直接的選擇嗎,但從筆者實踐來看,模板在Cesium裏實現起來可沒有深度那麼來得方便,綜合最終效果而言,我的也比較推薦用深度來實現比較好。code

好了,大政方針肯定了,開始實施。orm

咱們視域分析的結果,無論可見與不可見,最終像素它都是在所分析對應的觀察視角的CVV裏,以外的像素是不用關心的,所以先將相機移到咱們的觀察視角,正常獲取一張深度圖(至於如何在Cesium裏獲取到深度圖可參照另一篇文章:Cesium渲染流程https://www.cnblogs.com/GISCesium/p/10420492.html)。在和正常場景渲染的深度圖作對比,便可肯定那些像素對於觀察視角可見,那些不可見。htm

也能夠本身獲取深度圖,咱們須要本身先建立一個Framebuffer來承載咱們的深度信息,在Cesium裏就是放在一個紋理對象中來管理以下:對象

var framebuffer = new Framebuffer({
context : context,
depthStencilTexture : new Texture({
context : context,
width : context.drawingBufferWidth,
height : context.drawingBufferHeight,
pixelFormat : PixelFormat.DEPTH_STENCIL,
pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8
})
});blog

具體參數就不過多介紹了,此時此刻,咱們擁有了一個正常批次渲染中的「一幀」,再綁定到PassState上便可獲取到了:ci

 this._scene.getViewDepth(clearCommand, PassState, myCamera);
 this._pickDepth.update(context, this._PassState.framebuffer.depthStencilTexture);
 this._pickDepth.executeCopyDepth(context, this._PassState);

建議是經過自定義的方式獲取,這樣比較靈活,磨刀不誤砍柴工,我一開始就本身封裝好了不一樣階段深度信息的獲取類,到後面才真正體驗到那叫一個方便啊。

原始場景的深度信息獲取就更簡單了,方式也多樣,好比能夠直接經過屏幕座標反算得出:

.......
var drawingBufferPosition = SceneTransforms.transformWindowToDrawingBuffer(this._scene, windowCoordinate, new Cartesian2());
drawingBufferPosition.y = this._scene.drawingBufferHeight - drawingBufferPosition.y;
pickDepth.getDepth(context, drawingBufferPosition.x, drawingBufferPosition.y);

......

固然最偷懶的方式經過相機矩陣,利用向量變換也能夠還原出實際深度值。

可能咱們仍是以爲這樣一通操做,仍是麻煩了,以前也說過,利用Cesium自帶的ShadowMap也能夠實現視域分析,這種方式確實在Cesium基礎之上改一改就完事。對於要增強Cesium源碼掌控的不建議這樣作,但爲了儘快出效果能夠先試試這種方式。基於ShadowMap的思路比較簡單,這裏就簡明扼要的記錄一下。

Cesium以Command的方式周而復始地實時刷新場景的樣子,讓咱們看到一個個三維場景,而有的命令具有這樣的特徵:一方面它具備通用特性,甚至是影響全局的;另一方面它並非每一幀都須要的。針對這些命令把他們放在derivedCommands的計算流程裏,根據實際狀況進行必要的計算。

在updateDerivedCommands函數裏咱們看得就比較清晰:


這裏可謂分工明確,其中就有咱們關心的陰影生成相關係的shadows分支命令的計算。這裏須要強調一下,Scene場景下用於陰影分支計算的是單獨的ShadowMap,而非本身實例化的ShadowMap,這裏處理
很差,會影響後面視域分析結果與原生陰影之間的關係,甚至衝突。

至於Shader,直接看ShadowMap這個類就好了,判斷一下那些在陰影區,那些不在,判斷的方法Cesium也提供了直接的方法,咱們惟一要作的就是添加指定顏色uniform變量以及其它調控參數便可,上圖並
不是惟一的效果,你也能夠改出這樣的的效果:




由於採用了傳統透視投影的視錐體示意,徹底能夠根據弧度本身畫示意線便可,這都不是什麼核心問題了。



總結一下,利用Cesium原生的技術便可完成視域分析功能這條路確實行得簡單脫俗,但這裏面隱藏了不少值得去深挖的問題,一個牽扯一個,環環相扣;再改造Cesium源碼的過程當中不少表面上莫名其妙
的報錯每每是由於沒有看清源碼意圖致使的,因此有時間仍是實戰一把對技術提高必將大有裨益。開源如此炫麗,但問題的根本不在於誰在用開源,而在於誰利用得好。
 
 
 
 
 
 

 

 
 
 
 

 

 

祝願週末沒事,技術繼續分享交流,羣685834990

相關文章
相關標籤/搜索