在Blender和Godot中显示真实区域3D地形

4 篇文章 0 订阅
2 篇文章 0 订阅

目标

在Blender和Godot中显示真实区域3D地形。

方法

用QGIS处理和导出真实区域的高度图。
在Blender中利用高度图制作3D地形模型。
通过Godot Terrain3D插件,将高度图导入Godot中进行处理和显示。

地图数据处理

地图分辨率

比如福州市范围是北纬[25°15′, 26°39′]、东经[118°08′, 120°31′]。
地球长半轴6378.137千米(参考《GB 22021》附录A),可得福州市东西向距离约240.0千米、南北向距离约155.8千米。
要在分辨率为1920*1080的一屏内完整地显示福州市俯瞰图,那么东西向125.0米每像素、南北向144.3米每像素。
当分辨率为3840*2160时,东西向62.5米每像素、南北向72.1米每像素。
一般选用与实际显示分辨率相当或略高的地图数据。

数字高程数据

本例选用最佳开源DEM——哥白尼DEM,数据下载参考最佳开源DEM全国、省、市、县DEM数据分享
只需下载“哥白尼全国dem\原始数据\全国原始DEM数据(float32)”中的原始数据。
其中每个文件包含经纬度范围6°*6°的数据,每个像素对应地球表面的1角秒*1角秒,或称地面分辨率为30米。

小知识:角度单位秒,又称角秒、弧秒(arc second),1秒=(1/3600)度=(1/60)分。
在以地球长半轴为半径的大圆上,圆心角1秒对应大圆上的弧长30.92米,1度对应111.3千米。

QGIS

安装QGIS,后续将使用它处理地图数据。
本例中使用QGIS 3.36。

合并

  • 把原始地图数据文件逐个(用鼠标拖拽)导入QGIS图层(Layers)窗口,能完全覆盖所需区域即可。

  • 为检查区域覆盖情况,需导入行政区划界线数据。
    可参考民政部:行政区域界线资源阿里云DataV.GeoAtlas地理小工具EasyMapruiduobao/shengshixian.com等获得行政区划数据文件。
    本例从阿里云DataV.GeoAtlas下载json格式的福州市区划文件。

  • 使用合并(merging)功能(在ArcGIS中称为镶嵌mosaicking,菜单项Raster->Miscellaneous->Merge…,或Processing Toolbox->GDAL/Raster miscellaneous/Merge),合并多个地图文件以覆盖目标区域,方便后续处理。
    福州市可被单个地图文件(115E21N_COP30)覆盖,可以跳过这一步。
    如果是福建省,就要使用两个地图文件(另加115E27N_COP30)进行合并。

本步骤完成后:
QGIS Merged

重投影

卫星遥感数据一般采用WGS84地理坐标系(参考《GB/T 17798》附录C)。
地理坐标系不适合直接用于制图,制图要采用投影坐标系。

地图投影方式参考《GB 35650》第6章 数学基础,根据地图比例尺:

  • 1:500…1:10000
    采用高斯-克吕格投影,按经差3°分带(zone 自西向东编号);
  • 1:25000…1:500000
    采用高斯-克吕格投影,按经差6°分带(CM 起始经度);
  • 1:1000000
    采用双标准纬线正轴等角圆锥投影,按纬差4°分带。

显示比例尺S可根据《GB 35650》表7、表8大致确定范围,也可参考《GB/T 35634》第4章 分级来计算:
S = 1:(Gr*Sr)/0.0254
其中,

  • Gr(地面分辨率)单位为米每像素(m/像素);
  • Sr(屏幕分辨率)取值为96 dpi;
  • 0.0254是英寸和米的转换常数,1 in = 0.0254 m。

哥白尼DEM的地面分辨率约为30米每像素,对应比例尺为1:113386。
因此,本例中福州市的投影坐标系要采用“Gauss-Kruger CM 117E”坐标系。

使用重投影(reproject)功能(菜单项Raster->Projections->Warp(reproject)…,或Processing Toolbox->GDAL/Warp (reproject)),在“Target CRS”输入框选择合适的投影坐标系,将地图数据从地理坐标系变换到投影坐标系。
本例中“Target CRS”选择:“EPSG:4509 - CGCS2000 / Gauss-Kruger CM 117E”:
QGIS Reproject

重投影后(调整了图层顺序和显示开关):
QGIS Reprojected
注意:图层窗口中重投影后的图层(Reprojected)的数据值范围与重投影前相差很大。
这是因为图层属性信息是通过二次采样数据得到的,并没有遍历全部数据。
在图层属性信息窗口中,也会显示“STATISTICS_APPROXIMATE=YES”表示统计信息是基于部分数据得到的近似值。

裁剪

使用裁剪(clip)功能,可选择按范围(by extent)或按掩码层(by mask layer)等方法对地图区域进行裁剪。

如果按行政区划界线进行按掩码层裁剪,要注意公开地图内容表示的要求和风险(参考《GB/T 35764》)。

本例采用福州市行政区划的外接长方形进行范围裁剪:

  • 选中Layers窗口中上一步处理后的图层;
  • 选择菜单项Raster->Extraction,或Processing Toolbox->GDAL/Raster extraction;
  • 在弹出窗口的“Clipping extent”输入框旁的向下按钮选项中选择“Calculate from Layer”,并选择福州市的界线图层;
  • 在“Clipped (extent)”输入框输入合适的文件名;
    QGIS Clip

裁剪后:
QGIS Clipped

重采样

如果原始数据的分辨率过高,使得最终每个像素要代表多个采样数据,那么最好使用重采样(resample)来合并优化数据。

重采样也使用重投影(reproject)功能来实现。
在重投影弹出窗口中为“Resempling method to use”选择合适的重采样算法,推荐Lanczos Windowed Sinc方法(参考:投影重采样),并设置合适的输出分辨率“Output file resolution in target georeferenced units”。
如果不使用QGIS而使用ArcGIS,重采样算法可采用三次卷积(cubic)或双线性(blinear)方法。

本例有继续放大显示图像的需求,可以跳过这一步。

重设比例

地图数据处理最终输出的高度值将采用16位无符号二进制数表示,取值范围是[0, 65534](65535保留给可能的NoData使用)。
将地图数据变换到给定的取值范围,就称为重设比例(rescale)。

使用GRASS插件的r.rescale重设比例功能:

  • 确保打开了“处理工具箱”窗口,可选择菜单项Processing->Toolbox或使用快捷键CTRL+ALT+T;
  • 在窗口的搜索输入框中输入“r.rescale”,并选择“GRASS->Raster (r.*)->r.rescale”;
  • 在弹出窗口中的“The output data range”下的“Min”和“Max”分别输入0和65534;
  • 在“Rescaled”输入框输入合适的文件名。
    QGIS Rescale

重设比例后:QGIS Rescaled
从图层属性窗口的“Symbology”页可知,高度[-29, 1799]米变换为高度值[0, 65534]。

通过r.rescale这种方法生成的图最终在Godot Terrain3D中使用会出错。
还可以采用栅格计算器来重设比例:

  • 删除之前生成的Rescaled图层;
  • 选择菜单项Raster->Raster Calculator…;
  • 在弹出窗口中选择上一步处理后的高度值,本例中是“Clipped@1”;
  • 点击“Use Selected Layer Extent”按钮;
  • 在“Output layer”输入框输入合适的文件名;
  • 在“Raster Calculator Expression”输入框输入变换公式:(“Clipped@1”+29)*65534/(1799+29)
    QGIS Rescale by Raster Calculator

处理结果:
QGIS Rescaled 2

输出高度图

上一步处理后的地图数据仍是Float32类型,而高度图要采用16位无符号二进制数表示高度值,因此需要进行类型变换。

使用变换(translate)功能:

  • 选中Layers窗口中上一步处理后的图层(本例中为Rescaled);
  • 选择菜单项“Raster->Conversion->Translate (covert format)…”;
  • 在弹出窗口中设置“Assign a specified NoData value to output bands”为65535;
  • 设置“Advanced Parameters->Output data type”为“UInt16”;
  • 在“Converted”输入框输入合适的文件名,文件类型为“TIF files (*.tif)”。
    QGIS Translate

完成:
QGIS Translated

Blender

利用上一步输出的高度图,使用Blender制作3D地形模型。
本例使用Blender 4.0.2
具体步骤可参考3D渲染地图教程Creating Shaded Relief in Blender

场景物体

  • 平面、摄像机和日光。
  • 在平面上增加:材质、细分修改器。
    Blender scene

属性

以高度图分辨率=7335*5330为例,设置以下属性:

  • Scene/Render/Render Engine:Cycles
  • Scene/Render/Feature Set:Experimental
  • Scene/Output/Format/Resolution X:1467 px
  • Scene/Output/Format/Resolution Y:1066 px
  • Scene/Output/Format/Resolution %:100%
    X/Y比例和高度图X/Y一致。
    如果设置X*Y=7335*5330,当分辨率%为100%时只能渲染出2048*2048大小(Blender 3.3.0),因此要缩小比例。
  • 平面/Object/Transform/Scale X:7.335,对应长度14.67m
  • 平面/Object/Transform/Scale Y:5.330,对应长度10.66m
    X/Y比例和高度图X/Y一致,长度以在编辑器中看清物体全貌时也能看到周围坐标网格为宜。
  • 平面/Modifiers:Simple、Adaptive Subdivision
  • 平面/Modifiers/Dicing Scale:0.20,对应输出分辨率放大5倍
  • 平面/Material/Settings/Surface/Displacement:Displacement Only
  • 平面/Material/Viewport Display/Settings:Backface Culling
  • 摄像机/Object/Transform/Location Z:10 m,在待渲染物体之上
  • 摄像机/Data/Lens/Type:Orthographic
  • 摄相机/Data/Lens/Orthographic Scale:14.67
    正交比例的数值使得用摄像机视角时能看到物体全景。
  • 摄相机/Data/Lens/Clip End:25 m
    略大于待渲染物体最远端到摄像机的距离。
  • 日光/Object/Transform/Location Z:15 m
  • 日光/Object/Transform/Rotation X:26°,取当地纬度
    绕X轴的旋转角要控制在当地纬度和南北回归线纬度差以内。
    比如福州市在北纬[25°15′,26°39′],南北回归线的纬度是±23°26′,则绕X轴的旋转角应在[2°49′,50°05′]范围内。
  • 日光/Data/Light/Sun/Angle:0.533°
    太阳直径d=1.392×10⁶km,距地距离R=1.496×10⁸km,可得角直径=d*180/(R*π)=0.533°。

着色器

在Blender着色器编辑器中修改平面材质对应的着色器。

节点

  • 原理化BSDF(Principled BSDF,创建材质时自动生成)
  • 材质输出(Material Output)
  • 图像纹理(高度图)
  • 置换(Displacement)
  • 颜色渐变(Color Ramp)

数据流线

  • 图像纹理/颜色 到 置换/高度
  • 置换/置换 到 材质输出/置换
  • 原理化BSDF/BSDF 到 材质输出/表(曲)面
  • 图像纹理/颜色 到 颜色渐变/系数;
  • 颜色渐变/颜色 到 原理化BSDF/基础色

属性

  • 图像纹理/Extension:Extend
  • 图像纹理/Color Space:Non-Color
  • 图像纹理/Alpha:None
  • 置换/Scale:0.124
    本例从图片属性信息可知,地形在投影坐标系的四至(extent)为(637607,2794477 : 854333,2951961)(保留到个位),对应地理范围为216726m*157484m,对应场景中平面大小为14.67m*10.66m,比例尺为1:14773。
    高度[-29, 1799]米变换为高度值[0, 65534],无缩放时对应场景中高度范围[0, 1)m。
    所以,真实比例的Scale=(1799+29)/14773=0.124
  • 颜色渐变/Color Mode:RGB

参考配色方案:

  • 颜色断点0:位置0.000,颜色蓝B=1
  • 颜色断点1:位置0.016,颜色黑(全0),略高于海平面数值((0+29)/(1799+29)=0.0159)
  • 颜色断点2:位置0.017(断点1位置+0.001),颜色淡绿G=0.25,阻断断点1向后的颜色渐变
  • 颜色断点3:位置0.500,颜色绿G=1
  • 颜色断点4:位置1.000,颜色白(全1)

图示

Blender Shader

效果

  • 材质预览
    Blender Material Preview

  • 渲染(和灯光、环境等设置有关)
    Blender Render

河流上游、水库和湖泊等水体的海拔可能较高,甚至高于下游陆地,因此不能完全依赖高度来确定是否水体。

地表贴图(可选)

采用去云处理后的卫星光学影像。
在着色器中增加图像纹理节点替换颜色渐变节点。
略。

Godot

高度图预处理

Godot Terrain3D插件要求使用exr或r16/raw格式的高度图,参考Terrain3D: Height map

将QGIS导出的TIF格式的高度图转换为OpenEXR格式,有几种办法:

  • GIMP
    用GIMP打开TIF文件,选择菜单项“文件->导出为”,导出文件名后缀改为exr。

  • OpenImageIO中的iconvert工具
    在MSYS2/MinGW64中:

pacman -S --needed mingw-w64-x86_64-openimageio
iconvert.exe --compression zip G:/download/game/DEM/ht_3501.tif G:/download/game/DEM/ht_3501_oiio.exr

导入高度图

参考Terrain3D: Importing Data

因为本例没有做重采样降低分辨率,所以高度图分辨率和原始数据的地面分辨率相近,为29.55米每像素;也可在QGIS的图层属性信息窗口查看“Pixel Size”。
高度范围[-29, 1799]m,按真实高度比例可设置“Import Scale”=(1799+29)/29.55=62。

用Godot Terrain3D插件导入:
Godot Terrain3D Importer

参考

百家号:一文了解DEM数字地形“全家桶”
百度网盘:哥白尼全国dem
163:常用免费DEM数据汇总
微信:常见卫星图源下载教程
知乎:常用卫星参数及数据获取网站介绍
微信:GIS基础教程之坐标系
民政部:行政区划代码
国家统计局:统计用区划代码和城乡划分代码
百家号:2个免费下载全国行政边界数据网站

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值