如何在Cesium自定义材质属性中绘制固定像素大小的图像?
Cesium自定义材质相关问题解答
问题1:01范围st坐标转0分辨率范围坐标的实现方法
materialInput.st是绑定到几何面的纹理坐标,范围0~1对应整个几何面的对角,本身不携带实际尺寸信息,要实现固定尺寸的图案绘制有两种常用方案:
- 如果你需要屏幕像素尺寸固定的效果:可以调用Cesium内置uniform
czm_viewport获取当前视口宽高,将片元的世界坐标materialInput.positionWC通过czm_modelViewProjection矩阵投影到屏幕空间,换算后即可得到0~视口分辨率的屏幕坐标。 - 如果你需要地理空间尺寸固定的效果:建议直接使用
materialInput.positionWC(世界坐标,单位为米)的分量作为计算基准,不需要依赖st坐标,即可实现不管几何面大小、缩放层级如何,图案尺寸始终固定的效果。如果必须使用st坐标,可以自定义两个uniform参数传入当前几何面的实际宽高(单位米),用st乘以对应宽高即可得到地理空间坐标。
问题2:缩放层级变化时材质出现拉伸、镜像重复的原因
你遇到的形变问题核心原因是使用st坐标作为图案计算的基准:
st坐标的插值依赖几何面的顶点,当相机拉远时,Cesium会对大范围的几何面做LOD简化,减少顶点数量,导致st坐标插值异常;如果是贴地形的面,地形瓦片的加载切换也会导致st坐标计算错误,最终出现拉伸、镜像的异常效果,你提供的两张示例图就是典型的LOD切换导致的st插值错误:

解决方法也很简单:放弃st坐标作为图案计算的基准,改用世界坐标positionWC或者经纬度坐标计算图案位置,这样图案的位置和地理空间绑定,不受LOD切换、相机缩放的影响,不会出现形变。
问题3:materialInput.positionToEyeEC属性详解及示例
materialInput.positionToEyeEC是眼坐标(EC坐标,原点为相机位置,z轴负方向为相机朝向)下,从当前片元指向相机的向量:
- 向量的长度就是当前片元到相机的直线距离,单位为米
- 向量归一化后就是从片元指向相机的方向向量
常见使用场景示例:
- 距离雾效果:根据片元到相机的距离调整透明度,实现近处清晰、远处逐渐透明的效果
float disToCamera = length(materialInput.positionToEyeEC); // 距离超过10000米时完全透明 float alpha = 1.0 - clamp(disToCamera / 10000.0, 0.0, 1.0); material.alpha = alpha;
- 高光计算:光照计算中需要用到视线方向,该向量归一化后取反就是视线方向,可以直接带入Blinn-Phong等光照模型使用。
现有代码优化示例
针对你当前的点阵材质,可以修改为使用世界坐标计算,避免拉伸问题,修改后的着色器代码如下:
uniform float time; uniform vec4 color; czm_material czm_getMaterial (czm_materialInput materialInput) { czm_material material = czm_getDefaultMaterial(materialInput); // 改用世界坐标计算,每个格子边长为300米 vec2 coord = materialInput.positionWC.xy / 300.0; vec4 f = color; vec4 bg = vec4(f.rgb, f.a * .2); float x = mod(floor(coord.x + time * .3), 2.); float y = mod(floor(coord.y + time * .3), 2.); f.a *= x * y * .5; f += bg; material.diffuse = f.rgb; material.emission = f.rgb; material.alpha = f.a; return material; }
内容的提问来源于stack exchange,提问作者GuangWu
相关产品推荐
相关产品推荐

