:從DEM數(shù)據(jù)到3D立體地形圖渲染指南)
拿到一份 DEM 數(shù)據(jù)想要把它變成一張能放在報告封面、論文配圖甚至社交媒體上的立體地形圖R 語言的 rayshader 包是目前我試過最順手、效果也最驚艷的方案。它能在幾分鐘內(nèi)把平淡的柵格高程數(shù)據(jù)渲染成有光影、有景深、可以自由旋轉(zhuǎn)視角的 3D 模型而且全程不用離開 R 環(huán)境。這篇指南里我會把從數(shù)據(jù)獲取、預(yù)處理到 3D 渲染、導(dǎo)出成圖的完整流程拆開講清楚包含我踩過的坑和一些能直接抄作業(yè)的參數(shù)配置適合剛接觸地形可視化、或者已經(jīng)在 R 里處理過空間數(shù)據(jù)但想進(jìn)一步提升出圖質(zhì)量的讀者。1. 項目概述與核心思路1.1 這到底在解決什么問題做地理數(shù)據(jù)分析的人應(yīng)該都有這種體會DEM 數(shù)據(jù)本身只是一個二維的數(shù)值矩陣每一個像元記錄的是該位置的海拔高度雖然可以拉伸成灰度圖或者用色帶渲染成平面圖但人眼對三維形態(tài)的感知能力遠(yuǎn)比對顏色的感知能力敏銳得多。一個河谷的切割深度、一座火山的錐形輪廓、一條山脈的走向趨勢在等高線圖或者平面渲染圖里往往要盯著看半天才能浮現(xiàn)出來而一旦轉(zhuǎn)成 3D 透視圖整個地形的結(jié)構(gòu)關(guān)系能在一秒鐘之內(nèi)被大腦捕獲。rayshader 解決的就是這個“從數(shù)字到形態(tài)”的關(guān)鍵一步它把高程矩陣映射為三維曲面再通過模擬太陽光照、添加陰影紋理、疊加或影像配色生成接近真實地貌視覺效果的可視化成果。1.2 為什么選擇 R 語言加 rayshader 的組合做地形 3D 渲染其實有好幾條技術(shù)路線Blender 加 GIS 插件、QGIS 的 qgis2threejs、Cesium 或 Mapbox 這類 WebGIS 方案、還有 Python 的 pyvista 等。這些工具我多少都碰過但回到日常數(shù)據(jù)分析工作流里它們多多少少存在割裂感。數(shù)據(jù)清洗、統(tǒng)計建模在 R 里完成換個工具做可視化就免不了導(dǎo)出導(dǎo)入和格式轉(zhuǎn)換的麻煩。rayshader 最大的優(yōu)勢是直接嵌在 R 的生態(tài)里能用 tidyverse、sf、raster、terra 處理完數(shù)據(jù)之后立刻渲染整個環(huán)節(jié)不需要跳出 RStudio。另外一個原因在于 rayshader 本身的可控性相當(dāng)高光源角度、陰影強(qiáng)度、水面反射、霧效、相機(jī)位置都可以一一調(diào)整相比黑盒式的在線工具它給使用者保留了非常充足的創(chuàng)作空間。1.3 從 DEM 到 3D 渲染的整體管線可以把完整流程拆成四個環(huán)節(jié)數(shù)據(jù)準(zhǔn)備、數(shù)據(jù)預(yù)處理、3D 場景構(gòu)建、渲染輸出。數(shù)據(jù)準(zhǔn)備階段解決“DEM 從哪里來”的問題常見選擇包括本地已有的 GeoTIFF 文件或者通過 elevatr 包直接下載全球范圍的開源高程數(shù)據(jù)。預(yù)處理階段負(fù)責(zé)統(tǒng)一坐標(biāo)系、裁剪范圍、處理缺失值必要時可以做輕微的平滑或重采樣讓數(shù)據(jù)更利于后續(xù)渲染。3D 場景構(gòu)建是 rayshader 的主場包括把高度矩陣轉(zhuǎn)成紋理貼圖、設(shè)置相機(jī)視角、調(diào)整光照陰影、疊加水體圖層等。最后是渲染輸出可以選擇快速出圖用于預(yù)覽也可以啟用高質(zhì)量渲染獲得適合打印或出版的超大分辨率圖片。2. 環(huán)境準(zhǔn)備與數(shù)據(jù)獲取2.1 安裝 rayshader 及依賴環(huán)境的注意事項rayshader 的安裝整體不難但如果你用的是 Windows 且 R 版本較舊個別依賴包可能需要預(yù)先配置?;A(chǔ)安裝只需要一條命令install.packages(rayshader)建議同時安裝配套的空間數(shù)據(jù)處理包后面做數(shù)據(jù)裁剪和投影轉(zhuǎn)換時都會用到install.packages(c(elevatr, terra, sf, magrittr))Windows 用戶容易忽略的一個坑是 Rtools。如果你的計劃是從 GitHub 安裝開發(fā)版 rayshader或者有些依賴包需要從源碼編譯沒有 Rtools 會直接報錯。Rtools 的安裝版本需要與當(dāng)前 R 版本對應(yīng)這一點(diǎn)可以在 CRAN 的 Rtools 頁面確認(rèn)。我首次裝的時候就是 R 4.3 配了舊版 Rtools排查半天才發(fā)現(xiàn)版本不匹配。Linux 和 macOS 用戶則需要額外留意系統(tǒng)層面的圖形庫。這是因為 rayshader 底層會調(diào)用一些 C 圖形處理代碼如果系統(tǒng)缺少相關(guān)的依賴庫編譯階段會拋出找不到頭文件的錯誤。Ubuntu 系的話建議提前安裝sudo apt install libgdal-dev libproj-dev libssl-dev2.2 獲取 DEM 數(shù)據(jù)elevatr 包下載與本地數(shù)據(jù)讀取本地已經(jīng)有 GeoTIFF 格式的 DEM 數(shù)據(jù)的話用 terra 包讀取即可library(terra) dem - rast(your_dem.tif)沒有現(xiàn)成數(shù)據(jù)也不想自己去各個數(shù)據(jù)平臺翻的話elevatr 包提供了一條便捷通道。它在后端調(diào)用 AWS Terrain Tiles 提供的開源高程數(shù)據(jù)可以根據(jù)你定義的地理范圍自動裁剪和拼接默認(rèn)使用的是 Mapzen 的高程服務(wù)。核心代碼非常簡潔library(elevatr) library(sf) # 定義一個范圍比如某個研究區(qū)域的邊界框 bounds - st_as_sfc(st_bbox(c(xmin 116.3, ymin 39.8, xmax 116.6, ymax 40.2), crs 4326)) dem_elevatr - get_elev_raster(bounds, z 10)其中 z 參數(shù)控制數(shù)據(jù)分辨率z 值越高瓦片越精細(xì)、數(shù)據(jù)量也越大。z 10 大約對應(yīng) 30 米級別的分辨率適合展示大范圍地形如果關(guān)注的是一個小流域或者山體可以調(diào)高到 z 12 或 13。不過要注意下載時間會隨 z 值快速上升第一次使用建議從 z 9 或 10 開始測試流程。還有一點(diǎn)值得提醒get_elev_raster 返回的是 RasterLayer 對象在 terra 體系下可以用 rast() 轉(zhuǎn)換一下統(tǒng)一數(shù)據(jù)類型。同時不同渠道拿到的 DEM 數(shù)據(jù)坐標(biāo)系可能不同渲染本身不要求投影坐標(biāo)系但經(jīng)緯度坐標(biāo)系WGS84在后續(xù)涉及距離或面積計算時會有變形問題建議提前用 project() 轉(zhuǎn)換到合適的投影坐標(biāo)系。2.3 DEM 數(shù)據(jù)的預(yù)處理裁剪、重采樣、缺失值處理拿到原始 DEM 之后不要急著渲染先做三件小事。第一是裁剪到目標(biāo)區(qū)域把無關(guān)的周邊地形去掉這樣既能減少內(nèi)存占用也能避免無關(guān)地形搶走視覺焦點(diǎn)??梢杂?terra 的 crop 和 mask 操作完成。第二是檢查缺失值。SRTM 這類數(shù)據(jù)在陡峭山區(qū)和水體區(qū)域偶爾會出現(xiàn)空值直接渲染的話這些地方會呈現(xiàn)異常的凹陷或尖刺需要用 focal 函數(shù)做平滑插值或用鄰近像元填充。第三是確認(rèn)數(shù)據(jù)范圍是否需要重采樣。如果 DEM 分辨率太高、范圍又很大意味著矩陣規(guī)??赡苁巧先f乘上萬不僅渲染慢還有可能導(dǎo)致顯卡或內(nèi)存溢出??梢韵扔镁酆辖档头直媛时热缬?aggregate 做因子為 2 或 3 的聚合犧牲一點(diǎn)細(xì)節(jié)換取流程的順暢。這一點(diǎn)在實際項目中非常常用我一般預(yù)覽階段用低分辨率數(shù)據(jù)最終出圖再換回全分辨率。3. 核心渲染實現(xiàn)從高度矩陣到 3D 視圖3.1 數(shù)據(jù)格式的轉(zhuǎn)換邏輯rayshader 的核心渲染函數(shù)接收的不是 Spatial 對象或 RasterLayer而是普通的數(shù)值矩陣matrix。這個矩陣的每一個值對應(yīng)一個像元的高度行和列則對應(yīng)地物的平面坐標(biāo)。所以渲染前的關(guān)鍵一步是把 terra 的 SpatRaster 轉(zhuǎn)成矩陣。這個過程本身很簡單但有一個方向問題需要注意矩陣的行方向和地理坐標(biāo)的南北方向可能相反渲染出來的地形會出現(xiàn)上下顛倒的情況。處理方法是library(rayshader) library(terra) # 讀取 DEM dem - rast(your_dem.tif) # 轉(zhuǎn)換為矩陣 mat - matrix( extract(dem, ext(dem), cells TRUE)[, 3], nrow nrow(dem), ncol ncol(dem), byrow TRUE ) # 如果地形上下顛倒翻轉(zhuǎn)矩陣 mat - apply(mat, 2, rev)實際上 rayshader 社區(qū)更常見的做法是直接使用raster_to_matrix()函數(shù)它會把 RasterLayer 對象轉(zhuǎn)成矩陣并自動處理方向問題。配合 elevatr 下載的數(shù)據(jù)整個過程可以寫成dem_raster - raster::raster(dem_elevatr) mat - rayshader::raster_to_matrix(dem_raster)3.2 第一次 3D 渲染玩轉(zhuǎn) plot_3d 的關(guān)鍵參數(shù)矩陣準(zhǔn)備好之后最簡單的 3D 渲染只需要一行核心函數(shù)mat %% height_shade(texture texture_desert()) %% plot_3d(heightmap mat, zscale 100, solid TRUE, shadow TRUE)這行代碼做了兩件事height_shade 根據(jù)高度生成一張色彩紋理圖相當(dāng)于給地形“涂上顏色”然后 plot_3d 把這個帶有紋理的高度地圖渲染成 3D 場景。關(guān)鍵在于 zscale 參數(shù)它控制垂直方向的比例系數(shù)。由于 DEM 數(shù)據(jù)中一個像元的平面距離動輒幾十上百米而海拔變化可能只有幾百米如果不做垂直拉伸渲染出來的地形會平坦得像一塊板子zscale 設(shè)置得越小垂直方向的拉伸越明顯。經(jīng)驗值是平坦區(qū)域、大范圍場景用 200 到 500山地、小范圍場景用 20 到 80。可以多試幾個值找到視覺效果最舒服的倍數(shù)。plot_3d 還有一些值得調(diào)整的視覺參數(shù)。solid 控制是否在底部生成實體塊可以讓地形看起來像懸浮的模型shadow 控制是否生成陰影打開后會在地形底部產(chǎn)生一個深色投影空間感更強(qiáng)。threejs 或 rgl 窗口打開后你可以用鼠標(biāo)拖拽旋轉(zhuǎn)視角、滾輪縮放從不同角度檢查地形的形態(tài)。3.3 讓地形更真實光照、陰影和視角控制第一次渲染出來可能只是“有色地形”還不夠“3D”。這里的關(guān)鍵在于 add_shadow 和光照角度。可以這樣操作mat %% height_shade(texture texture_desert()) %% add_shadow(lamb_shade(mat, zscale 100, sunaltitude 30, sunangle 45), 0.5) %% plot_3d(heightmap mat, zscale 100, windowsize c(800, 600))lamb_shade 函數(shù)模擬的是朗伯體漫反射光照sunaltitude 是太陽高度角單位是度數(shù)值越小光線越傾斜、地形的陰影和立體感越強(qiáng)sunangle 是太陽方位角改變它會改變陰影的方向相當(dāng)于移動太陽的位置讓山脈的明暗關(guān)系發(fā)生變化。處理完光照之后用 add_shadow 把陰影疊加到紋理圖上第二個參數(shù)控制陰影的透明度。視角控制同樣重要。plot_3d 的默認(rèn)視角是 45 度左右的俯視但很多場景下低角度視角更有沖擊力。可以通過 render_camera 函數(shù)精細(xì)控制render_camera(phi 35, theta 30, zoom 0.6)phi 是相機(jī)與水平面的夾角可以理解為俯仰角theta 是相機(jī)繞地形旋轉(zhuǎn)的角度相當(dāng)于圓周方向的位置zoom 是縮放系數(shù)。建議在 RStudio 的 rgl 窗口里先手動旋轉(zhuǎn)找到一個心儀的角度再把對應(yīng)的 phi/theta 值填進(jìn)代碼保證后期重新渲染時視角一致。4. 視覺增強(qiáng)與配色方案選擇4.1 如何根據(jù)地形類型選擇合適的紋理色帶配色是決定一張地形圖質(zhì)感的核心因素。rayshader 內(nèi)置了不少紋理函數(shù)比如 texture_desert() 適合干旱區(qū)texture_imagination() 偏藝術(shù)化texture_water() 適合水文主題。但內(nèi)置紋理有時候滿足不了需求好在這個包提供了非常靈活的配色機(jī)制核心是使用 colorRampPalette 自定義色帶custom_palette - colorRampPalette(c(#285942, #4B8C5A, #A8B85A, #E8D9A0, #D9B36C, #A67B5B))(256) mat %% height_shade(texture custom_palette) %% plot_3d(heightmap mat, zscale 100)自定義色帶的邏輯并不復(fù)雜想一想這個地區(qū)的地貌特征低海拔是河谷常綠植被就用偏深的綠色中山區(qū)是草地或裸巖就過渡到黃褐色高海拔是裸巖或積雪就用灰色到白色收尾。這樣渲染出來的圖不僅能表達(dá)高度還能讓讀者一眼理解地表覆蓋的大致類型。需要注意 colorRampPalette 生成的色帶是離散的顏色向量256 個級別足夠平滑少于 64 會看到明顯的分層色帶。4.2 疊加衛(wèi)星影像或?qū)n}數(shù)據(jù)作為紋理除了用顏色表達(dá)高度之外rayshader 還允許把其他柵格數(shù)據(jù)作為紋理貼到 3D 地形上。最典型的是疊加衛(wèi)星影像這樣做出來的效果是“真實地球”風(fēng)格地形的高程來自 DEM顏色來自遙感影像兩者結(jié)合之后非常接近航拍視角。操作上也很直接# 假設(shè) img 是與 DEM 范圍一致的衛(wèi)星影像已轉(zhuǎn)成矩陣 mat %% sphere_shade(texture desert) %% add_overlay(img, alphalayer 1) %% plot_3d(heightmap mat, zscale 100)add_overlay 可以把任意 RGB 矩陣作為貼圖覆蓋在地形表面透明度由 alphalayer 控制。這個功能同樣適用于疊加土壤類型圖、土地覆蓋分類圖、人口密度圖等專題數(shù)據(jù)相當(dāng)于讓三維地形成為一個畫布上面展示的內(nèi)容可以根據(jù)研究目的自由替換。我自己的經(jīng)驗是疊加高分辨率影像時注意檢查兩個柵格數(shù)據(jù)的范圍、分辨率、投影是否一致不一致的話要先重采樣和裁剪對齊否則貼圖位置會發(fā)生偏移產(chǎn)生“張冠李戴”的錯誤。4.3 添加水面效果和霧效做出場景感很多地形可視化項目都涉及河流、湖泊、水庫一類的水體要素。ray shader 的水面模擬是我非常喜歡的功能它并不是簡單地把某塊區(qū)域涂成藍(lán)色而是渲染出帶反射效果的水面質(zhì)感。前提是準(zhǔn)備一個水體掩膜矩陣水體區(qū)域值為 1非水體區(qū)域為 0然后用 render_water 添加到場景中water_mask - matrix(0, nrow nrow(mat), ncol ncol(mat)) water_mask[湖泊對應(yīng)的行, 湖泊對應(yīng)的列] - 1 plot_3d(heightmap mat, zscale 100) render_water(heightmap mat, waterheight 80, watermask water_mask, wateralpha 0.7)waterheight 是水面的海拔高度只有當(dāng) DEM 值低于這個高度的區(qū)域才會被水覆蓋watermask 是可選的用來限定哪些位置可以出現(xiàn)水。wateralpha 控制水的透明度越大水體越不透明反射感越強(qiáng)。如果你只有一個固定的水面高度比如模擬海平面上升可以不傳 watermask直接讓所有低于 waterheight 的位置變成水面。霧效的加入則能大大增強(qiáng)場景的縱深感。render_atmosphere 可以在遠(yuǎn)處添加大氣散射效果讓地形邊緣自然淡出降低人工感render_atmosphere(altitude 1000, sunangle 45, haze 0.3)altitude 模擬相機(jī)距離地面的高度這個值越小霧效越濃haze 控制大氣的渾濁程度。實際使用中我在展示大范圍山脈的時候喜歡加一點(diǎn)霧效能讓遠(yuǎn)山有一種朦朧感更接近真實航拍。5. 高質(zhì)量渲染與結(jié)果導(dǎo)出5.1 預(yù)覽圖與最終圖的差異rgl 窗口里旋轉(zhuǎn)查看的場景是實時渲染的受限于顯示器分辨率和顯卡性能畫面往往比較粗糙有鋸齒、陰影不夠柔和。真正用于報告或出版的圖片需要用 render_snapshot 或 render_highquality 單獨(dú)輸出。兩者的區(qū)別可以這樣理解render_snapshot 捕獲的是當(dāng)前 3D 窗口的畫面速度非??爝m合做快速預(yù)覽render_highquality 則是重新啟動一個離屏渲染管線逐像素計算每一束光線的顏色和陰影效果接近電影級畫面但耗時顯著增加。一張 2000 像素寬的圖在普通電腦上可能要等一兩分鐘如果用 4K 分辨率、開抗鋸齒和軟陰影等上十幾分鐘也不奇怪。5.2 輸出參數(shù)詳解分辨率、抗鋸齒、文件名高質(zhì)量渲染的調(diào)用方式很直接render_highquality( filename terrain_3d.png, width 3000, height 2000, samples 16, antialias TRUE, clear FALSE )samples 控制在每個像素上采樣光線的次數(shù)數(shù)值越高畫質(zhì)越細(xì)膩噪點(diǎn)越少但渲染時間成倍增加。入門建議從 4 開始效果不滿意逐步上調(diào)到 16。antialias 開啟后可以顯著消除邊緣鋸齒代價同樣是時間。實際渲染前先把相機(jī)角度調(diào)整到理想位置再調(diào)用導(dǎo)出函數(shù)如果發(fā)現(xiàn)導(dǎo)出后視角不對可以直接在 rgl 窗口拖拽調(diào)整然后重新執(zhí)行 render_highquality不需要重復(fù)前面的 3D 場景構(gòu)建代碼。另外值得一提的還有 render_snapshot 的一個實用場景分享到社交媒體、嵌入網(wǎng)頁或快速給同事看一版效果時完全沒必要動用高畫質(zhì)渲染一張快圖能大大提高迭代速度。我的習(xí)慣是先用 snapshot 確認(rèn)構(gòu)圖和配色最后一步才上 highquality 出最終圖。5.3 動起來讓視角環(huán)繞地形的 GIF 與視頻靜態(tài)圖之外rayshader 還提供了一種非常有傳播力的輸出方式——旋轉(zhuǎn)視角動畫。render_movie 可以讓相機(jī)圍繞地形旋轉(zhuǎn) 360 度最終輸出一個 MP4 視頻或者一系列幀圖片配合 ffmpeg 還能轉(zhuǎn)成 GIF。代碼模板如下render_movie(filename terrain_rotate.mp4, phi 35, theta seq(0, 360, length.out 180))theta 參數(shù)傳入一個序列表示每一幀相機(jī)所處的角度。180 幀是一個比較流暢的配置如果機(jī)器性能一般可以減少到 120 幀。實際體驗中這種旋轉(zhuǎn)動畫在學(xué)術(shù)匯報、項目展示和社交媒體上都非常討喜幾分鐘的模型演示視頻比十張靜態(tài)圖更能直觀傳達(dá)地形全貌。我自己做區(qū)域規(guī)劃項目的匯報時經(jīng)常把主導(dǎo)航圖和一段 15 秒的三維旋轉(zhuǎn)動畫放在一起聽眾的專注度會明顯上一個臺階。6. 渲染過程中的常見問題與避坑指南6.1 高頻錯誤和排查方案速查表問題現(xiàn)象可能原因解決方案安裝 rayshader 報錯提示缺少 RtoolsWindows 環(huán)境未配置 Rtools到 CRAN 下載與當(dāng)前 R 版本匹配的 Rtools 并完成安裝加載包時提示找不到 GDAL系統(tǒng)缺少 GDAL 庫Linux 安裝 libgdal-devmacOS 用 Homebrew 安裝 gdal渲染出來的地形上下顛倒矩陣行順序與坐標(biāo)方向不一致用 apply(mat, 2, rev) 翻轉(zhuǎn)矩陣地形過于平坦幾乎沒有立體感zscale 設(shè)置太大試 50 到 100 之間的值按比例縮小疊加影像后紋理位置偏移兩個柵格數(shù)據(jù)的投影或范圍不一致用 project 和 resample 統(tǒng)一坐標(biāo)系與分辨率內(nèi)存不足R 會話直接崩潰DEM 范圍太大或分辨率太高用 aggregate 降低矩陣規(guī)模或裁剪小范圍測試render_highquality 渲染很久沒結(jié)果samples 或分辨率設(shè)置過高先用小圖和 samples4 測試再逐步加碼窗口能顯示圖像但導(dǎo)出 PNG 全黑rgl 窗口被遮擋或顯卡驅(qū)動兼容問題嘗試調(diào)用 rgl.clear() 后重建場景或更新顯卡驅(qū)動6.2 關(guān)于數(shù)據(jù)范圍和分辨率匹配的經(jīng)驗規(guī)劃一個地形可視化項目時最先確定的不是配色或視角而是“主角”的范圍和尺度。范圍決定了地形的敘事尺度同一座山放進(jìn)十公里的大場景里它是山脈的一部分放進(jìn)兩公里的小場景里它是獨(dú)立的視覺主體。相應(yīng)地分辨率也要匹配范圍大范圍用高分辨率數(shù)據(jù)渲染矩陣會非常龐大普通筆記本可能直接卡死不如主動降低分辨率先把構(gòu)圖跑通之后再用局部放大或者提高分辨率產(chǎn)出終稿。這一步看起來很簡單但很多人容易忽略結(jié)果浪費(fèi)了大量時間在等待渲染上。實際使用中我還有一個習(xí)慣把范圍邊界多向外擴(kuò)一點(diǎn)留出視覺緩沖空間避免地形模型的邊緣正好切在山頂或山谷這種視覺焦點(diǎn)位置。好比拍照時在主體周圍留白畫面的構(gòu)圖會松弛很多。6.3 投影與坐標(biāo)那點(diǎn)事別等到出圖才發(fā)現(xiàn)由于 rayshader 本身只是在畫數(shù)值矩陣它對坐標(biāo)的依賴其實很低——你完全可以把 DEM 當(dāng)成一張普通的灰度圖像來處理。但這不代表可以忽略投影問題。如果后續(xù)需要把渲染圖與矢量邊界、標(biāo)注點(diǎn)、比例尺等要素合成或者導(dǎo)出坐標(biāo)信息供 GIS 軟件讀取那么從源數(shù)據(jù)開始就使用統(tǒng)一的投影坐標(biāo)系會省很多事。更實際的一點(diǎn)是球面坐標(biāo)經(jīng)緯度在高緯度地區(qū)的面積變形非常嚴(yán)重如果一個研究區(qū)緯度較高直接渲染會讓地形在東西方向被拉伸變形看起來非常別扭。這種情況下應(yīng)該在預(yù)處理階段用 project() 轉(zhuǎn)換到適合當(dāng)?shù)氐耐队白鴺?biāo)系比如 UTM 分區(qū)投影。6.4 配色與光照的視覺錯覺陷阱最后分享一個比較容易踩坑的地方配色和光照疊加后可能產(chǎn)生視覺誤導(dǎo)。例如當(dāng)使用從低海拔綠色到高海拔白色的漸變時如果光線恰好從某個角度照射白色雪頂區(qū)域會反射大量光線導(dǎo)致過曝丟失紋理細(xì)節(jié)。這在渲染高海拔、多雪區(qū)域時尤其明顯。解決辦法是把光線角度調(diào)得低一些或者使用更柔和的陰影疊加層。另外自定義色帶時注意避免使用紅綠這一類色盲用戶難以區(qū)分的顏色組合。我通常會在渲染后把圖給身邊同事瞄一眼確認(rèn)沒有明顯的視覺歧義再定稿。7. 從靜態(tài)圖到交互應(yīng)用一些擴(kuò)展玩法rayshader 并不只停留在靜態(tài)出圖這一步。借助另一個包你可以把渲染結(jié)果導(dǎo)出為交互式 3D 場景發(fā)布到網(wǎng)頁上讓讀者自己拖拽旋轉(zhuǎn)這個功能在做數(shù)據(jù)新聞、在線報告或教學(xué)材料時非常加分。核心操作是用save_3d相關(guān)的函數(shù)將 R 中的 3D 模型保存為 HTML 格式之后用瀏覽器打開就能直接交互瀏覽。步驟上并不復(fù)雜關(guān)鍵是先把 3D 場景構(gòu)建好再調(diào)一次導(dǎo)出函數(shù)library(rayshader) library(htmlwidgets) plot_3d(heightmap mat, zscale 100) # 這里調(diào)整好視角后導(dǎo)出為交互式網(wǎng)頁 save_3d(filename terrain_interactive.html)打開這個 HTML 文件后讀者可以像操縱一個真實模型一樣旋轉(zhuǎn)、縮放地形從任意角度觀察。這種做法相比靜態(tài)圖最大的優(yōu)勢在于它把“探索感”交給了讀者而不是由作者固定一個觀看視角。我拿一個流域的地形做過測試地理專業(yè)的同事說這種交互方式在講解地形與水文關(guān)系的時候比 PPT 里的靜態(tài)圖直觀太多了。另外rayshader 也可以與 Shiny 應(yīng)用結(jié)合把渲染過程封裝成一個交互式應(yīng)用讓使用者在網(wǎng)頁端自行選擇渲染區(qū)域、調(diào)整 zscale 和配色。當(dāng)然這會涉及更多的工程開發(fā)內(nèi)容通常適合需要面向非技術(shù)用戶交付成果的團(tuán)隊。8. 實操中的幾點(diǎn)體會用 rayshader 做地形可視化上手周期其實很短但想要出真正養(yǎng)眼、信息傳達(dá)準(zhǔn)確的圖還是需要在使用中慢慢積累感覺。我自己總結(jié)了三條經(jīng)驗第一數(shù)據(jù)預(yù)處理花的時間永遠(yuǎn)值得裁剪、投影、缺失值處理這些前期工作決定了最終渲染質(zhì)量的上限第二zscale 和視角是地形表現(xiàn)力的靈魂花時間試不同組合一定會有回報第三配色要克制避免過于花哨的顏色分帶讓地形本身的形態(tài)和光影表達(dá)主要的信息顏色只是輔助。另外在沒有特殊要求的情況下建議始終按照“小圖快測大圖精渲”的節(jié)奏推進(jìn)。先用較低分辨率和較小的導(dǎo)出尺寸確認(rèn)畫面構(gòu)圖和參數(shù)是否合適再把數(shù)據(jù)與分辨率升到最高做最終渲染。這樣既能把試錯成本保持在幾秒鐘又能在最終出圖時獲得最好的畫質(zhì)。你手上如果有現(xiàn)成的 DEM 數(shù)據(jù)不管是一片山地還是一個城市周邊完全可以從今天這篇文章里的代碼開始花十分鐘跑通第一張三維地形圖。等到跑通了再回來慢慢調(diào)整配色和光影相信你會發(fā)現(xiàn)原來從數(shù)據(jù)到觸手可及的立體山川距離就這么近。