基于Cesium实现逼真的水特效
Cesium 自带有水特效材质,实例代码如下:
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
})
);
primitive.appearance.material = new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
specularMap: "../images/earthspec1k.jpg",
normalMap: Cesium.buildModuleUrl(
"Assets/Textures/waterNormals.jpg"
),
frequency: 10000.0,
animationSpeed: 0.01,
amplitude: 1.0,
},
},
});
说明:
specularMap: 着色器源码:float specularMapValue = texture2D(specularMap, materialInput.st).r;用于判断当前区域是否为水域。
normalMap:水波动的法线纹理贴图
frequency:波的数量
animationSpeed:水震动的速度
amplitude:振幅大小
使用发现自带的水特效效果不是特别好,于是简单改改,将水透明化,代码如下:
fragmentShaderSource: 'varying vec3 v_positionMC;
' +
'varying vec3 v_positionEC;
' +
'varying vec2 v_st;
' +
'void main()
' +
'{
' +
'czm_materialInput materialInput;
' +
'vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));
' +
'#ifdef FACE_FORWARD
' +
'normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
' +
'#endif
' +
'materialInput.s = v_st.s;
' +
'materialInput.st = v_st;
' +
'materialInput.str = vec3(v_st, 0.0);
' +
'materialInput.normalEC = normalEC;
' +
'materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);
' +
'vec3 positionToEyeEC = -v_positionEC;
' +
'materialInput.positionToEyeEC = positionToEyeEC;
' +
'czm_material material = czm_getMaterial(materialInput);
' +
'#ifdef FLAT
' +
'gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
' +
'#else
' +
'gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);
' +
'gl_FragColor.a=0.85;
' +
'#endif
' +
'}
'
结合倾斜摄影数据,改改水的相关参数也还凑合,可以看。但是你想要的水面倒影,水折射肯定是没有的。
下面我们可以看看three.js的水,看着挺清澈透明的,现实生活中也就生活用水有这个效果。但几乎有水的折射和反射效果了。
这里借鉴一下three.js的水特效代码:
融入到Cesium当中效果勉强可以看了,效果图如下:
图1
图2
图一和图二是同一份数据,,图一的水折射用的是影像图,图二的水折射是在水面几何数据下贴了石块纹理图,其实实际上的水是透明无色
转自:https://www.cnblogs.com/wanghui2011/articles/13100925.html
评论
vs =
'attribute vec3 position;' +
'attribute vec2 st;' +
'uniform mat4 u_modelViewMatrix;' +
'uniform mat4 u_invWorldViewMatrix;' +
//'uniform vec2 u_texCoordOffset;' +
//'uniform vec2 u_texCoordScale;' +
//'uniform float u_frameTime;' +
'uniform int u_clampToGroud;' +
'uniform vec3 u_camPos;' +
'uniform vec3 u_scale;' +
//'varying vec3 eyeDir;' +
'varying vec3 vToEye;' +
//'varying vec2 texCoord;' +
'varying vec2 vUv;' +
//'varying float myTime;' +
//'varying vec4 projectionCoord;' +
'varying vec4 vCoord;' +
'void main(void)' +
'{' +
//gl_Position = ftransform();
'vec4 positionW = u_modelViewMatrix * vec4(position.xyz, 1.0);' +
'vec4 eyep = czm_modelView * positionW;' +
'gl_Position = czm_projection * eyep; ' +
'if (u_clampToGroud == 1)' +
'{' +
//'eyeDir = (u_camPos - position.xyz) * u_scale;' +vToEye
'vToEye = (u_camPos - position.xyz) * u_scale;' +
'} else {' +
'vec4 pos = u_modelViewMatrix * vec4(position.xyz,1.0);' +
//'eyeDir = vec3(u_invWorldViewMatrix*vec4(pos.xyz,0.0));' +
'vToEye = vec3(u_invWorldViewMatrix*vec4(pos.xyz,0.0));' +
//'projectionCoord = gl_Position;' +
'vCoord = gl_Position;' +
'}' +
//'texCoord = (st+u_texCoordOffset)*u_texCoordScale;' +
//'vUv = (st+u_texCoordOffset)*u_texCoordScale;' +
'vUv = st;' +
//'myTime = 0.01 * u_frameTime;' +
'}';
var fs = [
'uniform sampler2D tReflectionMap;',
'uniform sampler2D tRefractionMap;',
'uniform sampler2D tNormalMap0;',
'uniform sampler2D tNormalMap1;',
'uniform sampler2D tFlowMap;',
'uniform vec3 color;',
'uniform float reflectivity;',
'uniform vec4 config;',
'varying vec4 vCoord;',
'varying vec2 vUv;',
'varying vec3 vToEye;',
'void main() {',
' float flowMapOffset0 = config.x;',
' float flowMapOffset1 = config.y;',
' float halfCycle = config.z;',
' float scale = config.w;',
' vec3 toEye = normalize( vToEye );',
// determine flow direction
' vec2 flow;',
//' #ifdef USE_FLOWMAP',
//' flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0;',
' flow = texture2D( tFlowMap, vUv ).rg;',
//' #else',
//' flow = flowDirection;',
//' #endif',
//' flow.x *= - 1.0;',
// sample normal maps (distort uvs with flowdata)
' vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 );',
' vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 );',
' float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;',
' vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );',
' vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );',
// calculate the fresnel term to blend reflection and refraction maps
' float theta = max( dot( toEye, normal ), 0.0 );',
' float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 );',
// calculate final uv coords
' vec3 coord = vCoord.xyz / vCoord.w;',
' vec2 coord1 = gl_FragCoord.xy / czm_viewport.zw;',
' vec2 uv = coord1.xy + coord.z * normal.xz * 0.05;',
' vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) );',
' vec4 refractColor = texture2D( tRefractionMap, uv );',
' gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );',
'gl_FragColor = refractColor;',
'}'
].join('
');