基于Cesium实现逼真的水特效[转]

基于Cesium实现逼真的水特效

Cesium 自带有水特效材质,实例代码如下:

var primitives = 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
})
);

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的水特效代码:

vertexShader: [

'#include <common>',
'#include <fog_pars_vertex>',
'#include <logdepthbuf_pars_vertex>',

'uniform mat4 textureMatrix;',

'varying vec4 vCoord;',
'varying vec2 vUv;',
'varying vec3 vToEye;',

'void main() {',

' vUv = uv;',
' vCoord = textureMatrix * vec4( position, 1.0 );',

' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
' vToEye = cameraPosition - worldPosition.xyz;',

' vec4 mvPosition = viewMatrix * worldPosition;', // used in fog_vertex
' gl_Position = projectionMatrix * mvPosition;',

' #include <logdepthbuf_vertex>',
' #include <fog_vertex>',

'}'

].join( '\n' ),

fragmentShader: [

'#include <common>',
'#include <fog_pars_fragment>',
'#include <logdepthbuf_pars_fragment>',

'uniform sampler2D tReflectionMap;',
'uniform sampler2D tRefractionMap;',
'uniform sampler2D tNormalMap0;',
'uniform sampler2D tNormalMap1;',

'#ifdef USE_FLOWMAP',
' uniform sampler2D tFlowMap;',
'#else',
' uniform vec2 flowDirection;',
'#endif',

'uniform vec3 color;',
'uniform float reflectivity;',
'uniform vec4 config;',

'varying vec4 vCoord;',
'varying vec2 vUv;',
'varying vec3 vToEye;',

'void main() {',

' #include <logdepthbuf_fragment>',

' 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;',
' #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 );',

// linear interpolate to get the final normal color
' float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;',
' vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );',

// calculate normal vector
' 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 uv = coord.xy + coord.z * normal.xz * 0.05;',

' vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) );',
' vec4 refractColor = texture2D( tRefractionMap, uv );',

// multiply water color with the mix of both textures
' gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );',

' #include <tonemapping_fragment>',
' #include <encodings_fragment>',
' #include <fog_fragment>',

'}'

].join( '\n' )

融入到Cesium当中效果勉强可以看了,效果图如下:


 

 图1

  图2


图一和图二是同一份数据,,图一的水折射用的是影像图,图二的水折射是在水面几何数据下贴了石块纹理图,其实实际上的水是透明无色


转自:https://www.cnblogs.com/wanghui2011/articles/13100925.html

 

评论

#11楼 [楼主]

@shenwuyuexy

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');
posted on 2021-04-06 16:51  3D入魔  阅读(5174)  评论(1编辑  收藏  举报