
一般cesium中瓦片底图使用的api为:
WebMapTileServiceImageryProvider
但是关于改api我们发现ceisum并不支持在该api直接修改着色器的属性。只有简单属性的修改
// this.tileLayer.brightness = params.brightness;
// this.tileLayer.contrast = params.contrast;
// this.tileLayer.hue = params.hue;
// this.tileLayer.saturation = params.saturation;
这并不满足需求。
翻阅资料我们发现viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources这个属性中是全局着色器的实现。我们在不想修改源代码的情况下可以改这里的代码,从而实现瓦片着色器的修改。只需写好着色器代码替换颜色相关的着色器代码就行。这里我移植three着色器代码到cesium中。
- three着色器
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>three-tile最小化应用</title>
<style>
html,
body {
color: white;
background-color: #333;
height: 100%;
min-height: 600px;
width: 100%;
padding: 0;
margin: 0;
display: flex;
overflow: hidden;
flex-direction: column;
text-align: center;
}
#map {
height: 100%;
width: 100%;
}
#loading {
position: absolute;
bottom: 0px;
left: 20px;
}
.controls {
position: absolute;
top: 20px;
right: 20px;
display: flex;
}
button {
background-color: #333;
border: 1px solid white;
border-radius: 5px;
padding: 0 5px;
box-shadow: 0 0 5px black;
margin-right: 10px;
}
</style>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.171.0/build/three.module.js",
"three-tile": "https://unpkg.com/three-tile@0.11.10/dist",
"three-tile/plugin": "https://unpkg.com/three-tile@0.11.10/dist/plugin"
}
}
</script>
</head>
<body>
<div id="map"></div>
<div id="loading">-</div>
<div class="controls">
<button onclick="handleReset()">原始样式</button>
<button onclick="handlFilter()">自定义着色器</button>
<button onclick="setStyle(0xaaccff)">蓝色</button>
<button onclick="setStyle(0x88ffcc)">绿色</button>
<button onclick="setStyle(0xffaaaa)">红色</button>
</div>
<script type="module">
import * as THREE from "three";
import * as tt from "three-tile";
import * as plugin from "three-tile/plugin";
console.log(`three-tile v${tt.version} start!`);
//==============================================================
// 定义着色器
class Filter extends THREE.MeshBasicMaterial {
constructor(params) {
super(params);
this.onBeforeCompile = (shader) => {
// 修改片段着色器 replace替换代码
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
vec4 texel = texture2D(map, vMapUv);
vec3 inverted = 1.0 - texel.rgb;
float luminance = dot(inverted, vec3(0.299, 0.587, 0.114));
vec3 grayscale = vec3(luminance);
vec3 finalColor = mix(grayscale, inverted, 0.6) * diffuse * 2.0;
gl_FragColor = vec4(finalColor, opacity * texel.a );
`
);
};
}
}
//==============================================================
// 修改影像加载器的材质为Filter
// const loader = tt.getImgLoader("image");
// loader.material = new Filter({
// });
//==============================================================
// 创建地图
const map = tt.TileMap.create({
// 影像数据源
imgSource: new plugin.GDSource({
style: 7
}),
minLevel: 4,
lon0: 90,
// 地图经纬度范围
bounds: [60, 0, 145, 60],
});
// 地图旋转到xz平面
map.rotateX(-Math.PI / 2);
// 初始化场景
const viewer = new plugin.GLViewer("#map");
viewer.scene.background = new THREE.Color(0x000022);
// 地图添加到场景
viewer.scene.add(map);
//==============================================================
// 地图中心经纬度高度(m)转为世界坐标
const centerPostion = map.geo2world(new THREE.Vector3(116.4, 39.92, 0));
// 摄像机经纬度高度(m)转为世界坐标
const cameraPosition = map.geo2world(new THREE.Vector3(116.4, 39.91, 10000));
viewer.flyTo(centerPostion, cameraPosition, false);
//==============================================================
// 显示地图加载进度
function showLoading(map, id) {
const el = document.querySelector("#loading");
if (el) {
map.addEventListener("loading-start", (evt) => {
el.innerHTML = "Started: " + evt.itemsLoaded + " of " + evt.itemsTotal + " files.";
});
map.addEventListener("loading-progress", (evt) => {
el.innerHTML = "Loading: " + evt.itemsLoaded + " of " + evt.itemsTotal + " files.";
});
map.addEventListener("loading-complete", () => {
el.innerHTML = "Loading complete!";
});
map.addEventListener("loading-error", (url) => {
el.innerHTML = "There was an error loading " + url;
});
}
}
showLoading(map);
//===========================================================
// 修改着色器
window.handlFilter = function() {
// 修改影像加载器的材质
const loader = tt.getImgLoader("image");
loader.material = new Filter({
color: 0xaacc
});
map.reload();
};
window.setStyle = (color) => {
loader.material.color.set(color);
map.reload();
};
</script>
</body>
</html>
- ceisum集成
const baseFragmentShader =
viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources;
// 循环修改着色器
for (let i = 0; i < baseFragmentShader.length; i++) {
const strS =
"color = czm_saturation(color, textureSaturation);\n#endif\n";
let strT =
"color = czm_saturation(color, textureSaturation);\n#endif\n";
strT += `
// 定义要保留的特定颜色范围(例如:水的蓝色)
vec3 targetColor = vec3(145.0/255.0, 171.0/255.0, 188.0/255.0); // 目标颜色
float colorThreshold = 0.25; // 颜色相似度阈值
// 计算当前颜色与目标颜色的差异
float colorDiff = length(color.rgb - targetColor);
// 只有当颜色差异大于阈值时才应用滤镜效果
if (colorDiff > colorThreshold) {
vec3 diffuse = vec3(0.17, 0.56, 0.99);
vec3 inverted = 1.0 - color.rgb;
float luminance = dot(inverted, vec3(0.299, 0.587, 0.114));
vec3 grayscale = vec3(luminance);
vec3 finalColor = mix(grayscale, inverted, 0.6) * diffuse * 2.0;
color.rgb = finalColor;
`;
baseFragmentShader[i] = baseFragmentShader[i].replace(strS, strT);
}
1240

被折叠的 条评论
为什么被折叠?



