cesium中对3dtile做特效处理的时候,目前只能对所有3dtile处理或者小区域内的3dtile(例如3dtile挖洞,淹没分析等)进行处理,本身上还是对drawcommand进行着色器的部分的改动。通常所作我们只能对选中的featrue进行更改颜色,无法做到更大限度去更改当前选中的feature,本文介绍一种方法对单个feature进行特效处理。
一、原理
通过点击选中场景某个feature,给其赋值一个颜色,将其颜色同时传到着色器中,在片源着色器中读取 tile_featureColor的颜色与传入的颜色做对比,如果两个颜色相同,则对其进行特效处理。若不同则不做任何处理。
Note:为什么选中tile_featureColor与传入的颜色作对比?
' vec2 st = computeSt(' + batchIdAttributeName + '); \n' +
' vec4 featureProperties = texture2D(tile_batchTexture, st); \n' +
上面代码取自于Cesium3DTileBatchTable类的部分着色器,computeSt方法就是根据当前batchId获取当前uv坐标值,通过坐标获取tile_batchTexture对应的颜色,该颜色也就是每一个feature的颜色,通过该颜色与传入的选中颜色值进行对比,然后进行着特效处理。featureProperties 最终会被赋值为tile_featureColor,因此我们可以在着色器中直接取用tile_featureColor的值与传入颜色进行对比。
二、示例
1、feature赋值
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
var pickingEntity = viewer.scene.pick(movement.position);
//判断选择是否为Cesium3DTileFeature
if (pickingEntity instanceof Cesium.Cesium3DTileFeature) {
//赋值特征颜色
pickingEntity.color = new Cesium.Color(1.0,0.0,0.0,1.0);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
2、颜色传值
同时将new Cesium.Color(1.0,0.0,0.0,1.0)通过uniform传入到着色器
3、着色器处理
'varying vec3 v_postion;\n'+
'varying vec3 v_elevationPos;\n'+
'uniform vec3 u_changeColor; \n' +//为传入的颜色值
'void main() \n' +
'{ \n' +
' czm_floodanlysis_main();\n'+
'vec3 test=tile_featureColor.rgb-u_changeColor.rgb;\n'+
'if((test.r+test.b+test.g)==0.0)\n'+//判断两个颜色是否相同,是否进行特效处理
'{\n'+
'gl_FragColor.rgba =vec4(0.0,0.5,1.0,1.0);\n'+
'float vtxf_a11 = fract(czm_frameNumber / 220.0) * 3.14159265 * 2.0;'+
' float vtxf_a12 = v_elevationPos.z / 2000.0 + sin(vtxf_a11) * 0.1;'+
' gl_FragColor *= vec4(vtxf_a12, vtxf_a12, vtxf_a12, 1.0);'+
'float vtxf_a13 = fract(czm_frameNumber / 360.0);'+
'float vtxf_h = clamp(v_elevationPos.z / 4000.0, 0.0, 1.0);'+
'vtxf_a13 = abs(vtxf_a13 - 0.5) * 2.0;'+
' float vtxf_diff = step(0.005, abs(vtxf_h - vtxf_a13));'+
'gl_FragColor.rgb += gl_FragColor.rgb * (1.0 - vtxf_diff);\n'+
'} \n'+
'}\n';
return ShaderP
三、在哪里处理着色器?
ModelUtility.modifyVertexShaderForLogDepth = function(shader, toClipCoordinatesGLSL) {
shader = ShaderSource.replaceMain(shader, 'czm_depth_main');
shader +=
'\n' +
'void main() \n' +
'{ \n' +
' czm_depth_main(); \n' +
//在这里处理
' czm_vertexLogDepth(' + toClipCoordinatesGLSL + '); \n' +
'} \n';
return shader;
};
关于如何往着色器进行传值有空再讲。。。。。。。。。。。。。。