基於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;\n' +
'varying vec3 v_positionEC;\n' +
'varying vec2 v_st;\n' +
'void main()\n' +
'{\n' +
'czm_materialInput materialInput;\n' +
'vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));\n' +
'#ifdef FACE_FORWARD\n' +
'normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n' +
'#endif\n' +
'materialInput.s = v_st.s;\n' +
'materialInput.st = v_st;\n' +
'materialInput.str = vec3(v_st, 0.0);\n' +
'materialInput.normalEC = normalEC;\n' +
'materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);\n' +
'vec3 positionToEyeEC = -v_positionEC;\n' +
'materialInput.positionToEyeEC = positionToEyeEC;\n' +
'czm_material material = czm_getMaterial(materialInput);\n' +
'#ifdef FLAT\n' +
'gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n' +
'#else\n' +
'gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n' +
'gl_FragColor.a=0.85;\n' +
'#endif\n' +
'}\n'
結合傾斜攝影數據,改改水的相關參數也還湊合,可以看。但是你想要的水面倒影,水折射肯定是沒有的。
下面我們可以看看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('\n');