主要是两个着色器
let postProccessStage = new Cesium.PostProcessStage({
//unform着色器对象 textureScale
fragmentShader:
// 声明一个纹理采样器 colorTexture 用于读取纹理颜色
'uniform sampler2D colorTexture;' +
// 声明一个纹理采样器 depthTexture 用于读取深度纹理
'uniform sampler2D depthTexture;' +
'in vec2 v_textureCoordinates;' +
'out vec4 outColor;' +
'void main(void)' +
'{' +
'float depth = czm_readDepth(depthTexture, v_textureCoordinates);' +
'vec4 color = texture(colorTexture, v_textureCoordinates);' +
'if(depth<1.0 - 0.000001){' +
'outColor = color;' +
'}' +
'else{' +
'outColor = vec4(1.0,0.0,0.0,1.0);' +
'}' +
'}'
});
//PostProcessStage:要使用的片段着色器。默认sampler2D制服是colorTexture和depthTexture。
let postProccesStage_1 = new Cesium.PostProcessStage({
// name:obj.name+'_1',
fragmentShader: 'uniform sampler2D colorTexture;' +
'uniform sampler2D redTexture;' +
'uniform sampler2D silhouetteTexture;' +
'in vec2 v_textureCoordinates;' +
'out vec4 outColor;' +
'void main(void)' +
'{' +
'vec4 redcolor=texture(redTexture, v_textureCoordinates);' +
'vec4 silhouetteColor = texture(silhouetteTexture, v_textureCoordinates);' +
'vec4 color = texture(colorTexture, v_textureCoordinates);' +
'if(redcolor.r == 1.0){' +
'outColor = mix(color, vec4(5.0,0.0,0.0,1.0), silhouetteColor.a);' +
'}' +
'else{' +
'outColor = color;' +
'}' +
'}',
//uniform着色器对象
uniforms: {
redTexture: postProccessStage.name,
silhouetteTexture: edgeDetection.name
}
});
全部代码
<template>
<div id="cesiumContainer" style="height: 100vh;"></div>
<div id="toolbar" style="position: fixed;top:20px;left:220px;">
<el-breadcrumb :separator-icon="ArrowRight">
<el-breadcrumb-item>三维分析</el-breadcrumb-item>
<el-breadcrumb-item>天际线</el-breadcrumb-item>
</el-breadcrumb>
<el-row class="mb-4" style="margin-top: 15px">
<el-button type="primary" @click="openSkylineAnay">打开</el-button>
<el-button type="primary" @click="closeSkylineAnay">关闭</el-button>
</el-row>
</div>
</template>
<script setup>
import {ArrowRight} from '@element-plus/icons-vue'
import {onMounted, ref} from "vue";
import * as Cesium from "cesium";
import InitCesium from "../js/InitCesiumHide.js";
let viewer = null;
const clouds = new Cesium.CloudCollection();
let silhouette = null;
let skylineAnayStages = null;
onMounted(() => {
let initCesium = new InitCesium('cesiumContainer');
viewer = initCesium.initViewer({});
flyToRight2();
})
//打开天际线分析
function openSkylineAnay() {
if (skylineAnayStages) {
silhouette.enabled = true;
return;
}
skylineAnayStages = viewer.scene.postProcessStages;
let edgeDetection = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
let postProccessStage = new Cesium.PostProcessStage({
//unform着色器对象 textureScale
fragmentShader:
// 声明一个纹理采样器 colorTexture 用于读取纹理颜色
'uniform sampler2D colorTexture;' +
// 声明一个纹理采样器 depthTexture 用于读取深度纹理
'uniform sampler2D depthTexture;' +
'in vec2 v_textureCoordinates;' +
'out vec4 outColor;' +
'void main(void)' +
'{' +
'float depth = czm_readDepth(depthTexture, v_textureCoordinates);' +
'vec4 color = texture(colorTexture, v_textureCoordinates);' +
'if(depth<1.0 - 0.000001){' +
'outColor = color;' +
'}' +
'else{' +
'outColor = vec4(1.0,0.0,0.0,1.0);' +
'}' +
'}'
});
//PostProcessStage:要使用的片段着色器。默认sampler2D制服是colorTexture和depthTexture。
let postProccesStage_1 = new Cesium.PostProcessStage({
// name:obj.name+'_1',
fragmentShader: 'uniform sampler2D colorTexture;' +
'uniform sampler2D redTexture;' +
'uniform sampler2D silhouetteTexture;' +
'in vec2 v_textureCoordinates;' +
'out vec4 outColor;' +
'void main(void)' +
'{' +
'vec4 redcolor=texture(redTexture, v_textureCoordinates);' +
'vec4 silhouetteColor = texture(silhouetteTexture, v_textureCoordinates);' +
'vec4 color = texture(colorTexture, v_textureCoordinates);' +
'if(redcolor.r == 1.0){' +
'outColor = mix(color, vec4(5.0,0.0,0.0,1.0), silhouetteColor.a);' +
'}' +
'else{' +
'outColor = color;' +
'}' +
'}',
//uniform着色器对象
uniforms: {
redTexture: postProccessStage.name,
silhouetteTexture: edgeDetection.name
}
});
//如果inputPreviousStageTexture 是 true,则每个阶段输入是场景渲染到的输出纹理或之前执行阶段的输出纹理
//如果inputPreviousStageTexture是false,则合成中每个阶段的输入纹理都是相同的
silhouette = new Cesium.PostProcessStageComposite({
//PostProcessStage要按顺序执行 的 s 或组合的数组。
stages: [edgeDetection, postProccessStage, postProccesStage_1],
//是否执行每个后处理阶段,其中一个阶段的输入是前一个阶段的输出。否则每个包含阶段的输入是组合之前执行的阶段的输出
inputPreviousStageTexture: false,
//后处理阶段制服的别名
uniforms: edgeDetection.uniforms
})
skylineAnayStages.add(silhouette);
}
//关闭天际线分析
function closeSkylineAnay() {
silhouette.enabled = false;
}
const flyToRight2 = async () => {
let tileset = await Cesium.Cesium3DTileset.fromUrl('/src/assets/tileset/12/tileset.json', {});
update3dtilesMaxtrix(tileset);
viewer.scene.primitives.add(tileset);
viewer.flyTo(tileset);
/*viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(113.05965738392063, 22.638603971034342, 300.0), // 设置位置
orientation: {
heading: Cesium.Math.toRadians(20.0), // 方向
pitch: Cesium.Math.toRadians(-30.0),// 倾斜角度
roll: 0
},
duration: 5, // 设置飞行持续时间,默认会根据距离来计算
complete: function () {
// 到达位置后执行的回调函数
},
cancle: function () {
// 如果取消飞行则会调用此函数
},
pitchAdjustHeight: -90, // 如果摄像机飞越高于该值,则调整俯仰俯仰的俯仰角度,并将地球保持在视口中。
maximumHeight: 5000, // 相机最大飞行高度
flyOverLongitude: 100, // 如果到达目的地有2种方式,设置具体值后会强制选择方向飞过这个经度(这个,很好用)
});*/
}
function update3dtilesMaxtrix(tileSet) {
//调整参数
let params = {
tx: 113.06265738392063, //模型中心X轴坐标(经度,单位:十进制度)
ty: 22.646603971034342, //模型中心Y轴坐标(纬度,单位:十进制度)
tz: 45, //模型中心Z轴坐标(高程,单位:米)
rx: 0, //X轴(经度)方向旋转角度(单位:度)
ry: 0, //Y轴(纬度)方向旋转角度(单位:度)
rz: 2, //Z轴(高程)方向旋转角度(单位:度)
scale: 1.35, //缩放比例
};
//旋转
const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
const rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
const rotationY = Cesium.Matrix4.fromRotationTranslation(my);
const rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
//平移
const position = Cesium.Cartesian3.fromDegrees(
params.tx,
params.ty,
params.tz
);
const m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(m, rotationX, m);
Cesium.Matrix4.multiply(m, rotationY, m);
Cesium.Matrix4.multiply(m, rotationZ, m);
//比例缩放
const scale = Cesium.Matrix4.fromUniformScale(params.scale);
Cesium.Matrix4.multiply(m, scale, m);
// console.log("矩阵m:", m);
//赋值给tileset
tileSet._root.transform = m;
}
</script>
<style scoped>
#cesiumContainer {
overflow: hidden;
}
</style>
<style>
.el-breadcrumb__inner, .el-breadcrumb__separator {
color: #ffffff !important;
}
</style>
效果图