Cesium.Entity图片纹理在不同观察角度有不同亮度

Cesium.Entity图片纹理在不同观察角度有不同亮度

测试代码:

viewer.entities.add({
  rectangle: {
    coordinates: Cesium.Rectangle.fromDegrees(-92.0, 30.0, -76.0, 40.0),
    material: "../images/rect.png",
  }
});

测试图片:

rect.png

这个图片可以比较明显的观察到亮度的变化!

如果亮度变化不明显,可以监测rgb的值,也会发现有所不同

测试结果:

entity rectangle使用了图片纹理,在改变查看角度后

图片的亮度发生变化

分析过程1:

光的反射分为镜面反射和漫反射两类

镜面反射导致的??

镜面反射会受到“观察角度”与“光源角度”的影响

在cesium中,调整太阳角度,观察角保持不变,并没有出现纹理亮度的变化

所以排除了纹理使用镜面反射的原因。

漫反射导致的??

在光源(太阳)和物体相对位置和角度保持不变的时候

只改变观察者的位置

是不应该出现亮度变化的

所以也排除了漫反射。

分析过程2:源码跟踪

发现是因为shader中,在眼睛坐标系下给了2个固定的光源

vec4 czm_phong(vec3 toEye, czm_material material, vec3 lightDirectionEC)
{
    // Diffuse from directional light sources at eye (for top-down)
    float diffuse = czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 0.0, 1.0), material);//固定光源1
    if (czm_sceneMode == czm_sceneMode3D) {
        // (and horizon views in 3D)
        diffuse += czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 1.0, 0.0), material);//固定光源2
    }

    float specular = czm_private_getSpecularOfMaterial(lightDirectionEC, toEye, material);

    // Temporary workaround for adding ambient.
    vec3 materialDiffuse = material.diffuse * 0.5;

    vec3 ambient = materialDiffuse;
    vec3 color = ambient + material.emission;
    color += materialDiffuse * diffuse * czm_lightColor;
    color += material.specular * specular * czm_lightColor;

    return vec4(color, material.alpha);
}

思考:

关于这2个固定光源:

这2个固定光源,可以让人在任何角度,都可以看到明亮的entity

如果没有这2个光源,大家就要调整合适的太阳角度去照亮特定的entity

至于为啥要加这2个固定光源的更多原因,欢迎大家留言。

关于环境光:

为啥cesium不引入环境光这个参数信息?

解决方案:

Entity.rectangle.material="图片地址"

上述代码最后会使用ImageMaterialProperty类

模仿ImageMaterialProperty类写一个自定义的MaterialProperty

在下述shader中,把diffuse改成emission就可以了

Material.ImageType = "Image";
Material._materialCache.addMaterial(Material.ImageType, {
  fabric: {
    type: Material.ImageType,
    uniforms: {
      image: Material.DefaultImageId,
      repeat: new Cartesian2(1.0, 1.0),
      color: new Color(1.0, 1.0, 1.0, 1.0),
    },
    components: {
      //下述diffuse改成了emission就可以了
      diffuse:
        "texture2D(image, fract(repeat * materialInput.st)).rgb * color.rgb",
      alpha: "texture2D(image, fract(repeat * materialInput.st)).a * color.a",
    },
  },
  translucent: function (material) {
    return material.uniforms.color.alpha < 1.0;
  },
});

上述代码引的是ImageMaterialProperty类使用的shader

自定义shader的时候,记着修改相关变量,比如Material.ImageType的值

(关于自定义MaterialProperty,请查询相关资料,在此不深入来说)

你可能感兴趣的:(Cesium,cesium,webgl,3d,gis)