Cesium后处理postProcessStages特效

本文介绍了Cesium中多种后处理特效的实现,包括边缘检测、轮廓、泛光、阴影、太阳和月亮的显示、星空、大气效果、雨、雪、雾、全屏雾、黑白、高斯模糊、亮度调整、景深、耀斑、夜视、环境遮蔽和阴影等,详细阐述了如何添加和调整这些特效。

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);
<think>我们正在讨论新版Cesium中实现泛光特效(BloomEffect)。根据之前对话,用户已经询问过辉光特效的实现,并且我们给出了两种方案:内置Bloom特效和自定义进阶方案。现在用户再次询问泛光特效的实现,可能希望得到更详细的解释或不同的实现角度。回顾引用[1]中提到的内容,是关于设置泛光折线材质的专栏目标,但没有直接给出具体方法。因此,我们将基于之前的知识和Cesium最新版本(1.90+)来回答。在新版Cesium中,内置的Bloom后期处理特效是最简单直接的实现方式。同时,我们也可以使用自定义的后期处理阶段来实现更复杂的效果。下面我将分为两个部分来详细说明:第一部分:使用内置Bloom特效(全屏泛光)第二部分:自定义特定对象的泛光效果注意:由于Cesium版本更新,部分API可能有所变化,但整体思路一致。第一部分:使用内置Bloom特效(全屏泛光)步骤:1.创建Viewer时,需要关闭OIT(OrderIndependentTranslucency)才能正常使用后期处理特效。2.使用`PostProcessStageLibrary`中的`createBloomStage`方法创建Bloom特效。3.将创建的Bloom特效添加到场景的后期处理阶段集合中。4.调整Bloom的参数以达到想要的效果。代码示例:```javascript//创建Viewer,关闭OITconstviewer=newCesium.Viewer('cesiumContainer',{orderIndependentTranslucency:false//关闭OIT});//获取场景constscene=viewer.scene;//创建Bloom特效constbloom=scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createBloomStage());//设置Bloom参数(可选)bloom.uniforms.glowOnly=false;//如果设为true,则只显示泛光部分而不显示原场景bloom.uniforms.contrast=128;//对比度,范围0到255,默认128bloom.uniforms.brightness=-0.3;//亮度,范围-1到1,默认-0.3(负值可以增强暗部的泛光)bloom.uniforms.delta=1.0;//采样步长,影响性能,值越大性能越高但效果越粗糙,默认1.0bloom.uniforms.sigma=2.0;//泛光的扩散程度,值越大泛光范围越大,默认3.78,通常调整这个参数bloom.uniforms.stepSize=1.0;//采样步长,与delta类似,但可能在某些版本中用delta```注意:在较新的Cesium版本中,Bloom特效的参数可能有所调整,具体可以通过查看`PostProcessStageLibrary`的源码或文档来获取最新的参数列表。第二部分:自定义特定对象的泛光效果有时候我们只希望某些对象(例如发光的线、标牌等)产生泛光效果,而其他物体则不受影响。这需要我们自己实现一个后期处理流程:思路:1.在渲染时,将需要泛光的对象单独渲染到一个纹理(通过自定义材质标记)。2.对这个纹理进行亮度提取(提取高亮部分)。3.对提取的亮区进行模糊处理(通常使用高斯模糊)。4.将模糊后的图像叠加到原始场景上。步骤:1.创建自定义材质(CustomShader),为需要泛光的对象设置一个特殊的发光颜色(比如自发光)。2.创建两个后期处理阶段:一个用于提取亮度,一个用于模糊(可以分水平和垂直两次模糊)。3.将模糊后的图像与原始场景图像混合。代码示例:```javascript//1.创建自定义材质,用于标记泛光对象constcustomShader=newCesium.CustomShader({uniforms:{u_glowColor:newCesium.Uniform(newCesium.Color(1.0,0.0,0.0,1.0))//红色泛光},fragmentShaderText:`voidfragmentMain(FragmentInputfsInput,inoutczm_modelMaterialmaterial){//设置自发光为发光颜色material.emissive=u_glowColor.rgb;}`});//2.将自定义材质应用到实体上constglowingEntity=viewer.entities.add({polyline:{positions:Cesium.Cartesian3.fromDegreesArray([...]),width:10.0,material:newCesium.PolylineGlowMaterialProperty({//注意:这里也可以使用自定义材质,但PolylineGlowMaterialProperty本身有发光效果//如果使用自定义材质,可以这样:color:Cesium.Color.RED})//或者使用CustomShader(Cesium1.90+)//material:customShader//需要实体支持customShader属性(如Primitive,但Entity的Polyline目前可能不支持,此处可能需要用PrimitiveAPI)}});//3.创建自定义的后期处理阶段(分为三个子阶段:亮度提取、水平模糊、垂直模糊)//亮度提取阶段constbrightPassStage=newCesium.PostProcessStage({name:'bright_pass',fragmentShader:`uniformsampler2DcolorTexture;uniformfloatthreshold;//亮度阈值varyingvec2v_textureCoordinates;voidmain(){vec4color=texture(colorTexture,v_textureCoordinates);//计算亮度floatbrightness=dot(color.rgb,vec3(0.2126,0.7152,0.0722));//如果亮度超过阈值,则保留,否则丢弃(或混合)vec4result=color*step(threshold,brightness);//也可以使用smoothstep过渡//floatfactor=smoothstep(threshold,threshold+0.1,brightness);//vec4result=color*factor;gl_FragColor=result;}`,uniforms:{threshold:0.5}});//模糊阶段(分为水平和垂直两个)//注意:Cesium提供了创建模糊阶段的函数,但这里我们分开创建以便控制constblurX=newCesium.PostProcessStage({name:'blur_x',fragmentShader:Cesium.PostProcessStageLibrary.createBlurFragmentShader('horizontal')//注意:这个函数在Cesium的源码中,但并未暴露在API中,因此我们可以自己写//或者自己实现:/*uniformsampler2DcolorTexture;uniformfloatoffset;varyingvec2v_textureCoordinates;voidmain(){vec4sum=vec4(0.0);//使用简单的高斯模糊核(5个采样点)sum+=texture2D(colorTexture,v_textureCoordinates+vec2(offset*-2.0,0.0))*0.1;sum+=texture2D(colorTexture,v_textureCoordinates+vec2(offset*-1.0,0.0))*0.2;sum+=texture2D(colorTexture,v_textureCoordinates)*0.4;sum+=texture2D(colorTexture,v_textureCoordinates+vec2(offset*1.0,0.0))*0.2;sum+=texture2D(colorTexture,v_textureCoordinates+vec2(offset*2.0,0.0))*0.1;gl_FragColor=sum;}*///由于自己实现高斯模糊较复杂,建议使用Cesium提供的内置模糊(但注意:它可能是一个组合阶段,我们可以用createBlurStage,然后分别设置水平和垂直方向)});//实际上,Cesium提供了一个createBlurStage函数来创建模糊阶段,该函数返回一个PostProcessStageComposite(包括水平和垂直两次模糊)//所以我们直接使用这个函数:constblurStage=Cesium.PostProcessStageLibrary.createBlurStage();blurStage.uniforms.direction=newCesium.Cartesian2(1.0,0.0);//先水平,然后我们还需要垂直的?createBlurStage内部已经包含两个方向了//但注意:createBlurStage返回的复合阶段已经做了水平+垂直模糊,所以直接用即可。//然后,我们需要将这两个阶段组合成一个复合阶段:亮度提取和模糊constbloomComposite=newCesium.PostProcessStageComposite({stages:[brightPassStage,blurStage]//顺序:先亮度提取,然后模糊});//4.最后,我们还需要一个阶段将模糊后的图像(泛光)叠加到原始场景上constcompositeStage=newCesium.PostProcessStage({name:'composite_bloom',fragmentShader:`uniformsampler2DcolorTexture;uniformsampler2DbloomTexture;//这是上一步的模糊结果varyingvec2v_textureCoordinates;voidmain(){vec4sceneColor=texture2D(colorTexture,v_textureCoordinates);vec4bloomColor=texture2D(bloomTexture,v_textureCoordinates);//简单叠加:场景颜色+泛光颜色gl_FragColor=sceneColor+bloomColor;//也可以使用混合公式,比如://gl_FragColor=vec4(sceneColor.rgb+bloomColor.rgb*0.5,sceneColor.a);}`,uniforms:{bloomTexture:bloomComposite.name//将上一个阶段的输出作为这个阶段的输入}});//5.将整个复合阶段添加到后期处理队列scene.postProcessStages.add(bloomComposite);scene.postProcessStages.add(compositeStage);//注意:compositeStage依赖bloomComposite的输出,所以bloomComposite必须在compositeStage之前//但是,这样添加两个阶段,每个阶段都会绘制整个屏幕。为了性能,通常我们会将这些阶段组合成一个大的复合阶段,只执行一次最终合成。```注意:自定义后期处理流程较为复杂,而且需要根据实际需求调整着色器代码。此外,为了只对特定对象进行泛光,我们可以在亮度提取阶段之前,将带有自发光(标记)的对象单独渲染到一个纹理(使用渲染到纹理的技术),但这通常需要修改Cesium的默认渲染流程(使用GrabPass),在Cesium中,我们可以使用`PostProcessStage`的`inputPreviousStageTexture`来连接各个阶段。性能优化建议:1.在不需要的时候关闭Bloom特效(设置`enabled`为false)。2.减少模糊的迭代次数(如果使用自定义模糊阶段)。3.降低亮度提取的采样率(通过设置`textureScale`,降低分辨率处理)。最后,如果用户需要为折线设置泛光材质,可以参考引用[1]中提到的专栏,其中可能包含了使用`PolylineGlowMaterialProperty`来实现发光效果(注意:这本身并不是后期处理的Bloom,而是自发光,但可以通过后期处理提取并模糊来增强效果)。下面生成相关问题:</think> ### 新版Cesium泛光特效实现指南 在新版Cesium(1.90+)中实现泛光特效(Bloom Effect)主要有两种方法,以下是具体实现步骤: --- #### 一、内置Bloom特效(全屏泛光) ```javascript const viewer = new Cesium.Viewer('cesiumContainer', { orderIndependentTranslucency: false // 必须关闭OIT }); // 启用内置泛光特效 const bloom = viewer.scene.postProcessStages.add( Cesium.PostProcessStageLibrary.createBloomStage() ); // 调整参数(可选) bloom.uniforms = { glowOnly: false, // 是否只显示辉光(false为混合效果) contrast: 128, // 对比度(0-255) brightness: -0.3, // 亮度(-1到1) sigma: 3.78, // 泛光强度(2.0-6.0) delta: 1.0 // 采样步长(影响性能) }; ``` **参数说明**: - `sigma` 控制泛光扩散强度(值越大效果越明显) - 开启后所有亮度超过阈值的区域都会产生泛光效果 - 默认全屏生效,性能开销较低[^1] --- #### 二、自定义泛光特效(指定对象) ```javascript // 创建泛光组合特效 const bloomEffect = new Cesium.PostProcessStageComposite({ stages: [ // 亮度提取阶段 new Cesium.PostProcessStage({ name: 'brightness_extract', fragmentShader: ` uniform sampler2D colorTexture; in vec2 v_textureCoordinates; out vec4 fragColor; void main() { vec4 color = texture(colorTexture, v_textureCoordinates); float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); fragColor = color * step(0.6, brightness); // 0.6为亮度阈值 }` }), // 模糊阶段 Cesium.PostProcessStageLibrary.createBlurStage({ delta: 1.0, sigma: 3.0 }) ] }); viewer.scene.postProcessStages.add(bloomEffect); // 泛光折线实现(关键代码) const glowingPolyline = new Cesium.PolylineGlowMaterialProperty({ glowPower: 0.3, // 泛光强度 color: Cesium.Color.CYAN.withAlpha(0.7) }); viewer.entities.add({ polyline: { positions: Cesium.Cartesian3.fromDegreesArray([...]), width: 15, material: glowingPolyline // 应用泛光材质 } }); ``` **核心技巧**: 1. 使用`PolylineGlowMaterialProperty`实现线条泛光 2. 通过`customShader`为实体添加自发光属性 3. 在后期处理阶段使用`step()`函数提取高亮区域[^1] --- #### 三、性能优化建议 1. **动态开关**: `bloom.enabled = false` // 非必要时关闭 2. **分层控制**: ```javascript // 仅地形层生效 viewer.scene.globe.showOnlyThisLayer(terrainLayer); ``` 3. **精度调节**: ```javascript bloom.uniforms.delta = 2.0 // 提高步长(降低质量提升性能) ``` 4. **采样降级**: ```javascript bloom.sampleRate = 0.5 // 采样率50% ``` --- #### 方案对比表 | 特性 | 内置Bloom | 自定义泛光 | |------|-----------|-----------| | 版本要求 | 1.90+ | 1.85+ | | 对象控制 | 全屏 | 特定对象 | | 性能开销 | 低 | 中高 | | 自定义度 | 有限 | 完全控制 | | 实现复杂度 | 简单 | 复杂 | > 建议:优先使用内置方案,需要对象级控制时采用自定义方案[^1] --- ### 相关问题 1. 如何为动态轨迹线添加渐变色泛光效果? 2. 泛光特效在低端设备卡顿如何优化? 3. 能否只在夜间启用泛光特效? 4. 如何避免泛光效果与大气散射冲突? 5. 点云数据(pointcloud)能否添加边缘泛光? [^1]: 实现参考Cesium官方文档及可视化技术专栏:cesium设置泛光折线材质
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值