基于Cesium实现逼真的水特效
基于Cesium实现逼真的水特效
基于Cesium实现逼真的水特效
Cesium 自带有水特效材质,实例代码如下:
1 var primitives = scene.primitives.add( 2 new Cesium.Primitive({ 3 geometryInstances: new Cesium.GeometryInstance({ 4 geometry: new Cesium.RectangleGeometry({ 5 rectangle: Cesium.Rectangle.fromDegrees( 6 -180.0, 7 -90.0, 8 180.0, 9 90.0 10 ), 11 vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT, 12 }), 13 }), 14 appearance: new Cesium.EllipsoidSurfaceAppearance({ 15 aboveGround: false, 16 }), 17 show: true 18 }) 19 );
1 primitive.appearance.material = new Cesium.Material({ 2 fabric: { 3 type: "Water", 4 uniforms: { 5 specularMap: "../images/earthspec1k.jpg", 6 normalMap: Cesium.buildModuleUrl( 7 "Assets/Textures/waterNormals.jpg" 8 ), 9 frequency: 10000.0, 10 animationSpeed: 0.01, 11 amplitude: 1.0, 12 }, 13 }, 14 });
说明:
specularMap: 着色器源码:float specularMapValue = texture2D(specularMap, materialInput.st).r;用于判断当前区域是否为水域。
normalMap:水波动的法线纹理贴图
frequency:波的数量
animationSpeed:水震动的速度
amplitude:振幅大小
使用发现自带的水特效效果不是特别好,于是简单改改,将水透明化,代码如下:
1 fragmentShaderSource: \'varying vec3 v_positionMC;\n\' + 2 \'varying vec3 v_positionEC;\n\' + 3 \'varying vec2 v_st;\n\' + 4 \'void main()\n\' + 5 \'{\n\' + 6 \'czm_materialInput materialInput;\n\' + 7 \'vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));\n\' + 8 \'#ifdef FACE_FORWARD\n\' + 9 \'normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n\' + 10 \'#endif\n\' + 11 \'materialInput.s = v_st.s;\n\' + 12 \'materialInput.st = v_st;\n\' + 13 \'materialInput.str = vec3(v_st, 0.0);\n\' + 14 \'materialInput.normalEC = normalEC;\n\' + 15 \'materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);\n\' + 16 \'vec3 positionToEyeEC = -v_positionEC;\n\' + 17 \'materialInput.positionToEyeEC = positionToEyeEC;\n\' + 18 \'czm_material material = czm_getMaterial(materialInput);\n\' + 19 \'#ifdef FLAT\n\' + 20 \'gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n\' + 21 \'#else\n\' + 22 \'gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n\' + 23 \'gl_FragColor.a=0.85;\n\' + 24 \'#endif\n\' + 25 \'}\n\'
结合倾斜摄影数据,改改水的相关参数也还凑合,可以看。但是你想要的水面倒影,水折射肯定是没有的。
下面我们可以看看three.js的水,看着挺清澈透明的,现实生活中也就生活用水有这个效果。但几乎有水的折射和反射效果了。
这里借鉴一下three.js的水特效代码:
1 vertexShader: [ 2 3 \'#include <common>\', 4 \'#include <fog_pars_vertex>\', 5 \'#include <logdepthbuf_pars_vertex>\', 6 7 \'uniform mat4 textureMatrix;\', 8 9 \'varying vec4 vCoord;\', 10 \'varying vec2 vUv;\', 11 \'varying vec3 vToEye;\', 12 13 \'void main() {\', 14 15 \' vUv = uv;\', 16 \' vCoord = textureMatrix * vec4( position, 1.0 );\', 17 18 \' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );\', 19 \' vToEye = cameraPosition - worldPosition.xyz;\', 20 21 \' vec4 mvPosition = viewMatrix * worldPosition;\', // used in fog_vertex 22 \' gl_Position = projectionMatrix * mvPosition;\', 23 24 \' #include <logdepthbuf_vertex>\', 25 \' #include <fog_vertex>\', 26 27 \'}\' 28 29 ].join( \'\n\' ), 30 31 fragmentShader: [ 32 33 \'#include <common>\', 34 \'#include <fog_pars_fragment>\', 35 \'#include <logdepthbuf_pars_fragment>\', 36 37 \'uniform sampler2D tReflectionMap;\', 38 \'uniform sampler2D tRefractionMap;\', 39 \'uniform sampler2D tNormalMap0;\', 40 \'uniform sampler2D tNormalMap1;\', 41 42 \'#ifdef USE_FLOWMAP\', 43 \' uniform sampler2D tFlowMap;\', 44 \'#else\', 45 \' uniform vec2 flowDirection;\', 46 \'#endif\', 47 48 \'uniform vec3 color;\', 49 \'uniform float reflectivity;\', 50 \'uniform vec4 config;\', 51 52 \'varying vec4 vCoord;\', 53 \'varying vec2 vUv;\', 54 \'varying vec3 vToEye;\', 55 56 \'void main() {\', 57 58 \' #include <logdepthbuf_fragment>\', 59 60 \' float flowMapOffset0 = config.x;\', 61 \' float flowMapOffset1 = config.y;\', 62 \' float halfCycle = config.z;\', 63 \' float scale = config.w;\', 64 65 \' vec3 toEye = normalize( vToEye );\', 66 67 // determine flow direction 68 \' vec2 flow;\', 69 \' #ifdef USE_FLOWMAP\', 70 \' flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0;\', 71 \' #else\', 72 \' flow = flowDirection;\', 73 \' #endif\', 74 \' flow.x *= - 1.0;\', 75 76 // sample normal maps (distort uvs with flowdata) 77 \' vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 );\', 78 \' vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 );\', 79 80 // linear interpolate to get the final normal color 81 \' float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;\', 82 \' vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );\', 83 84 // calculate normal vector 85 \' vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );\', 86 87 // calculate the fresnel term to blend reflection and refraction maps 88 \' float theta = max( dot( toEye, normal ), 0.0 );\', 89 \' float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 );\', 90 91 // calculate final uv coords 92 \' vec3 coord = vCoord.xyz / vCoord.w;\', 93 \' vec2 uv = coord.xy + coord.z * normal.xz * 0.05;\', 94 95 \' vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) );\', 96 \' vec4 refractColor = texture2D( tRefractionMap, uv );\', 97 98 // multiply water color with the mix of both textures 99 \' gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );\', 100 101 \' #include <tonemapping_fragment>\', 102 \' #include <encodings_fragment>\', 103 \' #include <fog_fragment>\', 104 105 \'}\' 106 107 ].join( \'\n\' )
融入到Cesium当中效果勉强可以看了,效果图如下:
图1
图2
图一和图二是同一份数据,,图一的水折射用的是影像图,图二的水折射是在水面几何数据下贴了石块纹理图,其实实际上的水是透明无色的。
版权声明:本文为wanghui2011原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。