前言
搞定地圖畫線以後,接下來就是繪製面和體了:優化
面做爲地圖渲染的基本元素之一,在地圖中能夠表明各類形式的區域,例如海面、綠地等。面數據一般以離散點串形式存儲,所以渲染時最關注的是如何將其展示爲閉合的圖形。url
體能夠理解爲帶有高度的面,在地圖中表明各類建築,一般是由其頂部面數據和高度數據處理獲得。.net
本文記錄了繪製面和體的流程以及解決閃爍問題的方案。3d
繪製多邊形區域面
面數據一般以離散點串形式存儲,面的繪製與線的繪製原理相似。渲染的基本單位是三角形,線是經過擴展線寬構造三角形後渲染,而面是經過將多邊形拆分爲多個三角形後渲染。對象
拆分爲三角形的過程被稱爲三角剖分,經常使用的三角剖分算法是耳切法(Ear Clipping),比較成熟的方案是Mapbox的earcut,對於有 [公式] 個頂點的多邊形,其時間複雜度爲 [公式] ,值得注意的是,三角剖分的解多是不惟一的,任何一種剖分方式都可以渲染獲得面,但細小的三角形更容易使面中的同一像素繪製屢次,形成過分繪製(Overdraw),所以根據多邊形特徵作一些剖分次序的調整能夠做爲一個優化點。blog
剖分完成的多邊形區域,在指定了每個頂點的顏色以後,就能繪製獲得純色的面。和道路線的Z-fighting問題相似,區域面也須要處理同一高度疊加顯示的問題。同時,二維的道路線和區域面總體也處於同一個高度上,所以也須要統一考慮層級關係,將全部的道路線置於區域面之上。統一處理完成就能夠獲得二維的地圖底板了。ip
繪製多邊形建築體
二維地圖底板完成後,就輪到地圖上的樓塊建築了。爲了減小數據量,一般的存儲方式是頂面點串和其對應的拔起高度,在渲染時增長頂點構成閉合體。get
頂面渲染流程和閉合區域面一致,側面則是根據樓高進行繪製,在每兩個相鄰頂點間渲染一個矩形從而構成閉合體的側面,爲了減小繪製次數一般只繪製朝向外側的側面,底面在正常視角下看不到,也能夠酌情選擇是否繪製。
建築體的渲染只比區域面多了拔高產生的側面,邏輯比較簡單,處理獲得全部三角形數據後,配置好頂點顏色便可完成渲染。
奇怪的建築體Z-fighting問題
理論上來講,建築體數據的頂面一般不會重合,所以在拔起渲染後不會出現Z-Fighting問題,但奇怪的是,渲染後仍然發現一些體存在側面閃爍問題。經過全鏈路的排查,才查出是多邊形數據的問題。
三角剖分在使用時有一個前置條件:使用對象必須爲簡單多邊形,即多邊形中的任何兩條邊僅能夠在頂點處相交。下圖(a)多邊形爲知足定義的簡單多邊形,圖(b)多邊形邊01和23在非頂點處相交,所以是非簡單多邊形。
對於非簡單多邊形,使用三角剖分只能得出較爲滿意的結果,但不能保證其正確性。從下圖四個頂點構成的非簡單多邊形的三角剖分結果能夠看到,多邊形渲染時會丟失頂點而且產生錯誤的三角形,沒法還原數據真實狀況。
按照這種想法對現有數據進行了邊的相交檢測,確實存在一小部分的多邊形不是簡單多邊形。而體元素的立面拔起是按照原始數據在每一組相鄰頂點間繪製矩形,所以會產生問題。以上述的非簡單多邊形(b)爲例,邊12拔起生成矩形1245,邊23拔起生成矩形2364,兩個側面矩形在面1245上徹底重合,當外立面貼上不一樣的紋理後就會產生Z-Fighting現象。同時,由於外立面僅僅繪製朝向外側一面,面1245在對側查看時會消失,產生很是詭異的效果。
針對這個問題,比較容易想到的解決方法主要是如下三個:
一、直接過濾,簡單粗暴。
二、根據多邊形計算外接矩形,減小細節
三、根據三角剖分結果剔除多餘頂點,從新生成簡單多邊形
以上三個方案對於多邊形的細節保留由少到多,但並非徹底還原真實數據。尤爲對於一些複雜建築,某一個面的錯誤會致使最終拼裝獲得的渲染結果錯誤。所以比較理想的方式是修復非簡單多邊形,將其分解爲多個簡單多邊形,分別渲染還原細節。
簡單多邊形的斷定與修復
根據簡單多邊形的定義,很容易想到採用暴力解法進行斷定:一個 邊形有 條邊,每條邊只須要和其餘的 條不相鄰邊判斷是否相交便可達到目的,其時間複雜度爲 ,對於僅須要進行一遍數據清洗的靜態數據來講已經足夠。但對於須要實時處理的動態數據來講,其須要遍歷全部組合,尤爲對於可能僅存在少許相交點的狀況,冗餘計算太多,所以能夠引入時間複雜度更低的相交斷定算法進行處理。
對於一個非簡單多邊形,在分解爲多個簡單多邊形後,繪製全部面積不爲0的圖形就能夠了。這種方案能夠最大限度還原原始數據,而且規避閃爍問題。
小結
解決了數據形成的閃爍問題後,就能夠在建築的側面和頂面使用純色或者紋理貼圖進行裝飾,搭配天空盒和一些純色元素去裝飾,已經能夠簡略模仿出城市的效果。但在當前的建築拔起渲染方式下,只能經過貼圖的形式去表達建築細節,若是須要更精細的表達效果,例如玻璃窗體結構、樓頂設施等,須要增長額外的三角形去進行呈現。
做者:程序員阿Tu
連接:https://zhuanlan.zhihu.com/p/266870185
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。