cesium風場圖【譯】


cesium風場圖

以下大部分內容來源於 開源博客 的英文翻譯,為自己以后查閱方便 。

這是Rayman Ng的特邀帖子,介紹了他基於CesiumJS構建的開源風向圖。

風是研究天氣和氣候的重要元素,它以各種方式影響我們的日常生活。在許多領域,例如氣候分析和風電場管理,分析風是至關重要的。可視化它對於能夠快速了解​​測量設備收集的數值風數據至關重要。
已經有一些風力可視化應用程序,例如Earth Nullschool和Windy,但是不幸的是,似乎它們都無法顯示地形,這對於估計特定位置的風力影響非常重要。

鑒於找不到適合我所有要求的現有可視化應用程序,我決定自己制作。我找到了Cesium,其中包含了幾乎所有我需要的東西:3D地球和地形,Web Map Service圖層顯示以及功能強大的渲染引擎。
基本上,我只需要實現風可視化部分。您可以在瀏覽器中運行實時演示,或訪問GitHub上的源代碼

圖:Cesium使用Cesium World Terrain可以輕松可視化動態風數據

圖:動態風覆蓋在WMS風速層上

怎么運行的

可視化風的常用技術是使用粒子系統,該系統會將大量粒子放置在風場中,並根據風力定期更新其位置。運動粒子的蹤跡可用於揭示風的流動模式。

最初,嘗試使用Entity API繪制粒子軌跡,但是當放置超過10,000個粒子時,性能無法令人滿意。經過一番調查后,意識到Entity API在CPU上執行計算,而對於超過10,000個粒子的計算對於CPU來說實在太多了。為了獲得更好的性能,需要將計算移至GPU,但仍然必須渲染軌跡,這意味着必須使用低級Cesium Renderer模塊。
在Cesium中,渲染過程的關鍵對象是Cesium.DrawCommand:它在渲染引擎中創建Cesium.Primitive,由調度Cesium.Scene並在渲染引擎中執行。
Cesium.DrawCommand包含在渲染所需的一切,例如Cesium.FramebufferCesium.Texture和Cesium.ShaderProgram。要執行自定義渲染,需要自定義DrawCommand
要構建DrawCommand,第一初始化組件,其是ShaderProgram,Texture,Uniforms,和Framebuffer,一塊一塊,然后將它們結合在一起來創建DrawCommand對象。要將其注入DrawCommand渲染引擎,需要一個自定義的原始對象。它不需要實現的所有方法Cesium.Primitive,僅需要update isDestroyed,和destroy方法。在每次渲染開始之前將調用update方法。
至於在GPU(也稱為GPGPU)上的計算,通過使用渲染到紋理的技術,類似於進行自定義渲染;只需將全屏四邊形用作頂點着色器,然后將計算代碼寫入片段着色器即可。幸運的是,Cesium已經提供了渲染到紋理的功能-我所要做的只是簡單地將片段着色器代碼傳遞給Cesium.ComputeCommand並用於Cesium.ComputeEngine執行GPGPU。最后一步是將CustomPrimitive包含自定義的的添加DrawCommand到的PrimitiveCollectionScene

圖:使用GPU可以計算這么多的粒子,因為否則太慢了,無法實時渲染。

下面是一個完整注釋的示例,說明如何使用自定義繪制命令創建圖元並將其添加到場景中。


class CustomPrimitive {
    constructor() {

        // most of the APIs in the renderer module are private,
        // so you may want to read the source code of Cesium to figure out how to initialize the below components,
        // or you can take my wind visualization code as a example (https://github.com/RaymanNg/3D-Wind-Field)
        var vertexArray = new Cesium.VertexArray(parameters);
        var primitiveType = Cesium.PrimitiveType.TRIANGLES // you can set it to other values
        var uniformMap = {
            uniformName: function() {
                // return the value corresponding to the name in the function
                // value can be a number, Cesium Cartesian vector, or Cesium.Texture
            }
        }
        var modelMatrix = new Cesium.Matrix4(parameters);
        var shaderProgram = new Cesium.ShaderProgram(parameters);
        var framebuffer = new Cesium.Framebuffer(parameters);
        var renderState = new Cesium.RenderState(parameters);
        var pass = Cesium.Pass.OPAQUE // if you want the command to be executed in other pass, set it to corresponding value


        this.commandToExecute = new Cesium.DrawCommand({
            owner: this,
            vertexArray: vertexArray,
            primitiveType: primitiveType,
            uniformMap: uniformMap,
            modelMatrix: modelMatrix,
            shaderProgram: shaderProgram,
            framebuffer: framebuffer,
            renderState: renderState,
            pass: pass
        });
    }

    update(frameState) {
        // if (!this.show) return;
        // if you do not want to show the CustomPrimitive, use return statement to bypass the update

        frameState.commandList.push(this.commandToExecute);
    }

    isDestroyed() {
        // return true or false to indicate whether the CustomPrimitive is destroyed
    }

    destroy() {
        // this method will be called when the CustomPrimitive is no longer used
    }}

// To begin the custom rendering, add the CustomPrimitive to the Scenevar viewer = new Cesium.Viewer('cesiumContainer');
var customPrimitive = new CustomPrimitive();
viewer.scene.primitives.add(customPrimitive);

結論

與Entity API相比,帶有自定義繪制命令的Primitive API提供了較低級別的功能,可以實現更好的性能,但需要更多的編碼工作。通過使用功能強大的渲染引擎,可以以令人滿意的性能實現風的可視化,我相信還有許多其他方式可以使用此功能強大而通用的渲染引擎。例如,能夠在不同的圖像層之間切換非常有用,因此您可以在全局上下文中查看動態風數據,並輕松地將其與歷史風數據進行比較。這在下面使用滑塊顯示。

致謝

我花了幾個星期來編寫此演示程序。如果沒有以下幫助,它肯定會花更長的時間:銫論壇的專家,尤其是銫團隊成員Omar Shehata。GitHub上Cesium自定義基元教程的作者,該教程提供了在Cesium中自定義渲染的代碼示例


已驗證以上分享出來的開源代碼可以正常運行,轉載到自己的git上留存。
cesium3D-Wind-Field


后面補充
風場數據的解析:
A) 風場數據部分的前半部分:
1.lon經度網格,范圍是0~359.5,網間格距 0.5,網格數共720;
2.lat緯度網格,范圍-90~90,網間格距 0.5 ,網格數共361 ;
3.lon、lat經緯度網格,總網格數量= data.lon.array.length * data.lat.array.length = 720 * 361 = 259920 ;
4.data.U.array.length = 259920 , data.V.array.length = 259920 ,兩者剛好一致的,也必須是一致的;
B) 風場數據部分的后半部分,網格數據data部分

  1. data.U 和 data.V 都是按行存儲的,data.U.array(index) , X經度lon =index%lonsize,Y緯度 lat=index/lonsize;
  2. data.U 中記錄了在正東方向的風速值,每個值對應網格上一個點。
  3. data.V 中記錄了在正北方向的風速值,每個值對應網格上一個點。
  4. 最后渲染的時候,每個網格點上的正北方向、正東方向的風速值,需要對兩個值向量加運算,即該點的風速向量。

此博客中的代碼比較接近cesium和gpu底層,我現在的功力有些看不懂Cesium.DrawCommand自定義封裝的部分,尤其是風場數據如何渲染,顏色如何更改變換,始終沒看懂;說不定過幾個月之后就懂了。

本文轉自 https://www.jianshu.com/p/bff42183ce2c,如有侵權,請聯系刪除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM