一、前言
之前有一个项目用的是UE5+cesium for unreal插件,甲方想要海洋效果,最后是同事缓存了一份在线数据实现的,今天偶尔发现新版本的cesium有这个例子,果断搬过来感慨一下。
二、效果
三、环境
版本:cesium1.101
四、关键代码
createWaterEffect(viewer) {
let worldRectangle = viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
}),
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
aboveGround: false,
}),
show: true,
}),
);
worldRectangle.appearance.material = new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
specularMap: "./data/material/earthspec1k.jpg",
normalMap: Cesium.buildModuleUrl("./data/material/waterNormals.jpg"),
frequency: 10000.0, //频率
animationSpeed: 0.01, //动画速度
amplitude: 5.0, //振幅
specularIntensity:0.2, //镜面反射强度
blendColor:Cesium.Color.POWDERBLUE //边缘混合颜色
},
},
});
},
这是官方给的例子里面的一段代码,逻辑很简单:创建一个大的矩形,再给矩形应用了一个材质,specularMap是一个单通道的黑白图片,用于区分陆地和海洋,这个图片像素有点粗,陆地和海洋衔接处有些生硬,如果项目要求高的话可以二次加工一下。
顺便说一句官方的水材质源文件在Cesium1101Source\packages\engine\Source\Shaders\Materials\Water.glsl,其内容如下:
// Thanks for the contribution Jonas
// http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog
uniform sampler2D specularMap;
uniform sampler2D normalMap;
uniform vec4 baseWaterColor;
uniform vec4 blendColor;
uniform float frequency;
uniform float animationSpeed;
uniform float amplitude;
uniform float specularIntensity;
uniform float fadeFactor;
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float time = czm_frameNumber * animationSpeed;
// fade is a function of the distance from the fragment and the frequency of the waves
float fade = max(1.0, (length(materialInput.positionToEyeEC) / 10000000000.0) * frequency * fadeFactor);
float specularMapValue = texture2D(specularMap, materialInput.st).r;
// note: not using directional motion at this time, just set the angle to 0.0;
vec4 noise = czm_getWaterNoise(normalMap, materialInput.st * frequency, time, 0.0);
vec3 normalTangentSpace = noise.xyz * vec3(1.0, 1.0, (1.0 / amplitude));
// fade out the normal perturbation as we move further from the water surface
normalTangentSpace.xy /= fade;
// attempt to fade out the normal perturbation as we approach non water areas (low specular map value)
normalTangentSpace = mix(vec3(0.0, 0.0, 50.0), normalTangentSpace, specularMapValue);
normalTangentSpace = normalize(normalTangentSpace);
// get ratios for alignment of the new normal vector with a vector perpendicular to the tangent plane
float tsPerturbationRatio = clamp(dot(normalTangentSpace, vec3(0.0, 0.0, 1.0)), 0.0, 1.0);
// fade out water effect as specular map value decreases
material.alpha = mix(blendColor.a, baseWaterColor.a, specularMapValue) * specularMapValue;
// base color is a blend of the water and non-water color based on the value from the specular map
// may need a uniform blend factor to better control this
material.diffuse = mix(blendColor.rgb, baseWaterColor.rgb, specularMapValue);
// diffuse highlights are based on how perturbed the normal is
material.diffuse += (0.1 * tsPerturbationRatio);
material.diffuse = material.diffuse;
material.normal = normalize(materialInput.tangentToEyeMatrix * normalTangentSpace);
material.specular = specularIntensity;
material.shininess = 10.0;
return material;
}
原创不易,记得点赞加关注哦,我会持续分享实用的功能(:-