Bootstrap

Cesium 光照和后处理 postProcessStages

前言

查了一堆的资料,最终落位于后处理

概念

Silhouette

https://sandcastle.cesium.com/?src=Post%20Processing.html&label=All
silhouette的效果可以理解为物体轮廓、描边,相当于把物体的外轮廓线勾勒出来
在这里插入图片描述

Ambient Occlusion

https://sandcastle.cesium.com/?src=Ambient%20Occlusion.html&label=All
简称AO,一般译作环境光遮蔽。
AO是来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果,可以解决或改善漏光、飘和阴影不实等问题,解决或改善场景中缝隙、褶皱与墙角、角线以及细小物体等的表现不清晰问题,综合改善细节尤其是暗部阴影,增强空间的层次感、真实感,同时加强和改善画面明暗对比,增强画面的艺术性。AO简单来说就是根据周围物体对光线的遮挡程度,改变明暗效果。

var ambientOcclusion = viewer.scene.postProcessStages.ambientOcclusion;
ambientOcclusion.enabled = true;
ambientOcclusion.uniforms.ambientOcclusionOnly = false;
ambientOcclusion.uniforms.intensity = 3;
ambientOcclusion.uniforms.bias = 0.1;
ambientOcclusion.uniforms.lengthCap = 0.03;
ambientOcclusion.uniforms.stepSize = 1;
ambientOcclusion.uniforms.blurStepSize = 0.86;

在这里插入图片描述

Bloom

泛光,一个明亮的物体真的有种明亮的感觉。泛光可以极大提升场景中的光照效果,并提供了极大的效果提升
在这里插入图片描述

问题整理

1. 开启日照阴影

let viewer = new Cesium.Viewer('cesium-container');
viewer.scene.globe.enableLighting = true;// 开启全球光照
viewer.shadows = true

2. 亮度设置

  • 方法1 api自带后处理
  // 亮度设置
  var stages = viewer.scene.postProcessStages;
  viewer.scene.brightness =  viewer.scene.brightness || stages.add(Cesium.PostProcessStageLibrary.createBrightnessStage());
  viewer.scene.brightness.enabled = true;
  viewer.scene.brightness.uniforms.brightness = Number(2);
  • 方法2 自己写后处理
var fs =
    'uniform sampler2D colorTexture;\n' +
    'varying vec2 v_textureCoordinates;\n' +
    'uniform float scale;\n' +
    'uniform vec3 offset;\n' +
    'void main() {\n' +
    '    vec4 color = texture2D(colorTexture, v_textureCoordinates);\n' + //获取片段颜色
    '    gl_FragColor = vec4(color.rgb * scale + offset, 10.0);\n' +
    '}\n'; //放大片段颜色系数

  viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({
    fragmentShader: fs,
    uniforms: {
      scale: 1.1,
      offset: function () {
        // return new Cesium.Cartesian3(0.1, 0.2, 0.3);
        return new Cesium.Cartesian3(0.01, 0.02, 0.03);
      }
    }
  }));

3. 去锯齿

参考文章

cesium中有个属性viewer.resolutionScale,默认值是1.0。
JavaScript中有个属性window.devicePixelRatio,属性返回的是当前显示设备的物理像素分辨率与CSS像素分辨率的比率,即一个CSS像素和一个物理像素的大小比值
cesium中viewer.resolutionScale默认值是1.0,也就是说无论在哪个屏幕上,cesium都把当前显示器的物理像素分辨率与CSS像素分辨率的比率(window.devicePixelRatio)当成是1.0来渲染,而实际上的比率可能是1.0或者1.25或者2.0(比如mac电脑Retina屏),所以造成锯齿和模糊。

	//是否开启抗锯齿
	if(Cesium.FeatureDetection.supportsImageRenderingPixelated()){//判断是否支持图像渲染像素化处理
	  viewer.resolutionScale = window.devicePixelRatio;
	}
	viewer.scene.fxaa = true;
	viewer.scene.postProcessStages.fxaa.enabled = true;
	this.labelInfo=this.viewer.entities.add(new Cesium.Entity());
	this.labelInfo.position=position;
	this.labelInfo.label={
		   show:true,
           showBackground:true,
           backgroundColor:Cesium.Color.fromCssColorString('#000'),
           scale:0.5, //这里非常巧妙的先将字体大小放大一倍在缩小一倍
           font:'normal 32px MicroSoft YaHei',
           text:`blabla~~`,
           pixelOffset :new Cesium.Cartesian2(-120, -100),
           horizontalOrigin:Cesium.HorizontalOrigin.LEFT
	}

4. cesium模型变黑的解决

github issue

lightColor : new Cesium.Cartesian3(100.0,100.0, 100.0),表示,rgb的倍数,这样就是白光增强到100倍。对Pbrt材质有效,倾斜摄影不生效。

tileset.lightColor = new Cesium.Cartesian3(1000,1000,1000)

5. Imagey的光照调整

官网示例
不适用于3dtiles

function updateViewModel() {
  if (imageryLayers.length > 0) {
    var layer = imageryLayers.get(0);
    viewModel.brightness = layer.brightness;
    viewModel.contrast = layer.contrast;
    viewModel.hue = layer.hue;
    viewModel.saturation = layer.saturation;
    viewModel.gamma = layer.gamma;
  }

6. 解决Cesium显示画面模糊的问题

参考文章

viewer._cesiumWidget._supportsImageRenderingPixelated = Cesium.FeatureDetection.supportsImageRenderingPixelated();
viewer._cesiumWidget._forceResize = true;
if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
    var vtxf_dpr = window.devicePixelRatio;
    // 适度降低分辨率
    while (vtxf_dpr >= 2.0) {
        vtxf_dpr /= 2.0;
    }
    //alert(dpr);
    viewer.resolutionScale = vtxf_dpr;
}

7. 开启泛光

官方示例

function updatePostProcess() {
  var bloom = viewer.scene.postProcessStages.bloom;
  bloom.enabled = Boolean(viewModel.show);
  bloom.uniforms.glowOnly = Boolean(viewModel.glowOnly);
  bloom.uniforms.contrast = Number(viewModel.contrast);
  bloom.uniforms.brightness = Number(viewModel.brightness);
  bloom.uniforms.delta = Number(viewModel.delta);
  bloom.uniforms.sigma = Number(viewModel.sigma);
  bloom.uniforms.stepSize = Number(viewModel.stepSize);
}

学习资料

  1. cesium| PostProcessStage后期处理

  2. Cesium后处理postProcessStages特效

  3. Cesium源码剖析—Post Processing之物体描边(Silhouette)

备份

1. 边缘检测(天际线)createEdgeDetectionStage

var collection = viewer.scene.postProcessStages;
 
        var edgeDetection = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
 
        var postProccessStage = new Cesium.PostProcessStage({
            name: 'czm_skylinetemp',
            fragmentShader: 'uniform sampler2D colorTexture;' +
                'uniform sampler2D depthTexture;' +
 
                'varying vec2 v_textureCoordinates;' +
 
                'void main(void)' +
                '{' +
                'float depth = czm_readDepth(depthTexture, v_textureCoordinates);' +
                'vec4 color = texture2D(colorTexture, v_textureCoordinates);' +
                'if(depth<1.0 - 0.000001){'+
                'gl_FragColor = color;' +
                '}'+
                'else{'+
                'gl_FragColor = vec4(1.0,0.0,0.0,1.0);'+
                '}'+
            '}'
        });
 
        var postProccessStage1 = new Cesium.PostProcessStage({
            name: 'czm_skylinetemp1',
            fragmentShader: 'uniform sampler2D colorTexture;' +
                'uniform sampler2D redTexture;' +
                'uniform sampler2D silhouetteTexture;' +
 
                'varying vec2 v_textureCoordinates;' +
 
                'void main(void)' +
                '{' +
                'vec4 redcolor=texture2D(redTexture, v_textureCoordinates);'+
                'vec4 silhouetteColor = texture2D(silhouetteTexture, v_textureCoordinates);' +
                'vec4 color = texture2D(colorTexture, v_textureCoordinates);' +
                'if(redcolor.r == 1.0){'+
                'gl_FragColor = mix(color, vec4(1.0,0.0,0.0,1.0), silhouetteColor.a);' +
                '}'+
                'else{'+
                'gl_FragColor = color;'+
                '}'+
            '}',
            uniforms: {
                redTexture: postProccessStage.name,
                silhouetteTexture: edgeDetection.name
            }
        });
 
        var postProccessStage = new Cesium.PostProcessStageComposite({
            name: 'czm_skyline',
            stages: [edgeDetection, postProccessStage, postProccessStage1],
            inputPreviousStageTexture: false,
            uniforms: edgeDetection.uniforms
        });
 
        collection.add(postProccessStage);

2. 轮廓(描边)createSilhouetteStage

Cesium.PostProcessStageLibrary.createSilhouetteStage (edgeDetectionStages)
此时边缘检测可作为轮廓函数的options参数,但是也可以省略边缘检测参数,直接调用轮廓函数:

 var collection = viewer.scene.postProcessStages;
  var silhouette = collection.add(Cesium.PostProcessStageLibrary.createSilhouetteStage());
  silhouette.enabled = true;
  silhouette.uniforms.color = Cesium.Color.YELLOW;

3. 泛光 bloom

 var bloom = viewer.scene.postProcessStages.bloom;
            bloom.enabled = true;
            bloom.uniforms.glowOnly = false;
            bloom.uniforms.contrast = 128;
            bloom.uniforms.brightness = -0.3;
            bloom.uniforms.delta = 1;
            bloom.uniforms.sigma = 2;
            bloom.uniforms.stepSize = 1;

4. 阴影shadowMap

viewer.scene.shadowMap = new Cesium.ShadowMap({    
	lightCamera: viewer.camera,    
	context: viewer.scene.context    
}) 
viewer.scene.shadowMap.enabled = true;

5. 开太阳

viewer.scene.sun.show = true;
scene.sun.glowFactor = 10; //太阳变大

6. 开月亮

 viewer.scene.moon.show = true;
 scene.moon.onlySunLighting = true;

7. 开星空

viewer.scene.skyBox.show = true;

8. 开大气

 viewer.scene.skyAtmosphere.show = true;
 scene.skyAtmosphere.hueShift = -1; //1
 scene.skyAtmosphere.saturationShift = -1 ;//1
 scene.skyAtmosphere.brightnessShift = -1; //1

9. 添加雨

var viewer = new Cesium.Viewer("cesiumContainer");
 
viewer.scene.skyBox.show = true;
viewer.scene.skyAtmosphere.show = true;
 
 var Rain = `
uniform sampler2D colorTexture;//输入的场景渲染照片
  varying vec2 v_textureCoordinates;
 
  float hash(float x){
       return fract(sin(x*133.3)*13.13);
  }
  
  void main(void){
   
      float time = czm_frameNumber / 60.0;
      vec2 resolution = czm_viewport.zw;
  
      vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
      vec3 c=vec3(.6,.7,.8);
  
      float a=-.4;
      float si=sin(a),co=cos(a);
      uv*=mat2(co,-si,si,co);
      uv*=length(uv+vec2(0,4.9))*.3+1.;
  
      float v=1.-sin(hash(floor(uv.x*100.))*2.);
      float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;
      c*=v*b; //屏幕上雨的颜色
  
      gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5); //将雨和三维场景融合
  }`;
 
 Cesium.PostProcessStageLibrary.createRainStage = function() {
        var rain= new Cesium.PostProcessStage({
              name : 'czm_rain',
              fragmentShader : Rain
          });
          return rain;
     };
 
 var collection = viewer.scene.postProcessStages;
 var rain= Cesium.PostProcessStageLibrary.createRainStage();
  collection.add(rain);
 var scene = viewer.scene;
  scene.skyAtmosphere.hueShift = -0.8;
  scene.skyAtmosphere.saturationShift = -0.7;
  scene.skyAtmosphere.brightnessShift = -0.33;
  
  scene.fog.density = 0.001;
  scene.fog.minimumBrightness = 0.8;

10. 添加雪

var viewer = new Cesium.Viewer("cesiumContainer");
 
viewer.scene.skyBox.show = true;
viewer.scene.skyAtmosphere.show = true;
 
 var Snow = `
uniform sampler2D colorTexture; //输入的场景渲染照片
  varying vec2 v_textureCoordinates;
  
  float snow(vec2 uv,float scale)
  {
      float time = czm_frameNumber / 60.0;
      float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
      uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
      uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
     p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
     k=smoothstep(0.,k,sin(f.x+f.y)*0.01);
     return k*w;
 }
 
 void main(void){
     vec2 resolution = czm_viewport.zw;
     vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
     vec3 finalColor=vec3(0);
     //float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));
     float c = 0.0;
     c+=snow(uv,30.)*.0;
     c+=snow(uv,20.)*.0;
     c+=snow(uv,15.)*.0;
     c+=snow(uv,10.);
     c+=snow(uv,8.);
     c+=snow(uv,6.);
     c+=snow(uv,5.);
     finalColor=(vec3(c)); //屏幕上雪的颜色
      gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5);  //将雪和三维场景融合
}
  `;
 
 Cesium.PostProcessStageLibrary.createSnowStage = function() {
        var snow = new Cesium.PostProcessStage({
              name : 'czm_snow',
              fragmentShader : Snow
          });
          return snow;
     };
 
 var collection = viewer.scene.postProcessStages;
  var snow = Cesium.PostProcessStageLibrary.createSnowStage();
  collection.add(snow);

11. 添加雾

scene.fog.enabled = true;
scene.fog.density = 0.001;
 scene.fog.minimumBrightness = 0.8;

12. 添加全屏雾特效

this.FogStage=new Cesium.PostProcessStage({
    "name":"czm_fog",
    fragmentShader:"  uniform sampler2D colorTexture;\n" +
        "  uniform sampler2D depthTexture;\n" +
        "  varying vec2 v_textureCoordinates;\n" +
        "  void main(void)\n" +
        "  {\n" +
        "      vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);\n" +
        "      vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);\n" +
        "\n" +
        "      float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n" +
        "      vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);\n" +
        "\n" +
        "      float f=(depthcolor.r-0.22)/0.8;\n" +
        "      if(f<0.0) f=0.0;\n" +
        "      else if(f>1.0) f=1.0;\n" +
        "      gl_FragColor = mix(origcolor,fogcolor,f);\n" +
        "   }"
});
 
this.viewer.scene.postProcessStages.add(this.FogStage);
this.FogStage.enabled=true;

13. 黑白

 var collection = viewer.scene.postProcessStages;
 var silhouette = collection.add(Cesium.PostProcessStageLibrary.createBlackAndWhiteStage ());
 silhouette.enabled = true;
silhouette.uniforms.gradations =15.0; 调节黑白程度(1-20

14. 高斯模糊

	var collection = viewer.scene.postProcessStages;
	var silhouette = collection.add(Cesium.PostProcessStageLibrary.createBlurStage());
	silhouette.enabled = true;
	silhouette.uniforms.delta=1.0;
	silhouette.uniforms.sigma=1.0;
	silhouette.uniforms.stepSize=20.0;(行之有效)

15. 亮度

 var collection = viewer.scene.postProcessStages;
 var silhouette = collection.add(Cesium.PostProcessStageLibrary.createBrightnessStage());
 silhouette.enabled = true;
silhouette.uniforms.brightness=0.1; (调节亮度0-3最佳)

16. 景深

 var collection = viewer.scene.postProcessStages;
 var silhouette = collection.add(Cesium.PostProcessStageLibrary.createDepthOfFieldStage());
 silhouette.enabled = true;
silhouette.uniforms.focalDistance=1;1000)
silhouette.uniforms.delta=1;5)
silhouette.uniforms.sigma=1;5)
silhouette.uniforms.stepSize=1;10

17. 耀斑

var viewer = new Cesium.Viewer("cesiumContainer");
var lensFlare = viewer.scene.postProcessStages.add(
 Cesium.PostProcessStageLibrary.createLensFlareStage()
);

function updatePostProcess() {
 lensFlare.enabled = 5;
 lensFlare.uniforms.intensity = 5;
 lensFlare.uniforms.distortion = 5;
 lensFlare.uniforms.ghostDispersal =5;
 lensFlare.uniforms.haloWidth = 5;
 lensFlare.uniforms.dirtAmount =5;
 lensFlare.uniforms.earthRadius = 5;
}
updatePostProcess();

var camera = viewer.scene.camera;
camera.position = new Cesium.Cartesian3(
 40010447.97500168,
 56238683.46406788,
 20776576.752223067
);
camera.direction = new Cesium.Cartesian3(
 -0.5549701431494752,
 -0.7801872010801355,
 -0.2886452346452218
);
camera.up = new Cesium.Cartesian3(
 -0.3016252360948521,
 -0.13464820558887716,
 0.9438707950150912
);
camera.right = Cesium.Cartesian3.cross(
 camera.direction,
 camera.up,
 new Cesium.Cartesian3()
);

viewer.clock.currentTime = new Cesium.JulianDate(
 2458047,
 27399.860215000022
);

18. 夜视

 var collection = viewer.scene.postProcessStages;
 var silhouette = collection.add(Cesium.PostProcessStageLibrary.createNightVisionStage());
 silhouette.enabled = true;

19. 环境遮蔽

var viewer = new Cesium.Viewer("cesiumContainer");
var silhouette = Cesium.PostProcessStageLibrary.createAmbientOcclusionStage();
 silhouette.enabled = true;
 silhouette.uniforms.intensity = 5.0;
 silhouette.uniforms.bias = 15.0;
 silhouette.uniforms.lengthCap = 5.0;
 silhouette.uniforms.stepSize = 5.0;
 silhouette.uniforms.frustumLength = 5.0;

20. 阴影

viewer.scene.shadowMap = new Cesium.ShadowMap({
 lightCamera:viewer.camera,
 context: viewer.scene.context
});
viewer.scene.shadowMap.enabled = true ;
;