cesium之用着色器添加建筑贴图
cesium之用着色器添加建筑贴图
ceslum版本:1.88.0
方法:
addTileset(url, color, name) {
const Cesium = window.Cesium;
// 必须开启 ModelExperimental 才能使用 customShader
Cesium.ExperimentalFeatures.enableModelExperimental = true;
let tileset = new Cesium.Cesium3DTileset({
url: url,
maximumScreenSpaceError: 2,
maximumNumberOfLoadedTiles: 1000,
})
tileset.style = new Cesium.Cesium3DTileStyle({
// // color: `rgba(0.0156*255, 0.768*255, 0.8235*255, 1)`,
// color: `rgba(0,239,242, 1)`,
// 去掉 color,交给 customShader 控制
showOutline: true
});
// 绑定着色器到3DTiles:贴图 + 上下渐变 + 动态光环
const customShader = new Cesium.CustomShader({
mode: Cesium.CustomShaderMode.REPLACE_MATERIAL,
lightingModel: Cesium.LightingModel.UNLIT,
varyings: {
v_normalMC: Cesium.VaryingType.VEC3
},
uniforms: {
u_color: {
type: Cesium.UniformType.VEC4,
value: new Cesium.Cartesian4(
(color.split(',')[0] || 0.0156) * 1,
(color.split(',')[1] || 0.768) * 1,
(color.split(',')[2] || 0.8235) * 1,
(color.split(',')[3] || 0.8) * 1
)
},
u_minHeight: {
type: Cesium.UniformType.FLOAT,
value: 0.0
},
u_maxHeight: {
type: Cesium.UniformType.FLOAT,
value: 100.0
},
u_texture: {
type: Cesium.UniformType.SAMPLER_2D,
value: new Cesium.TextureUniform({
url: "img/4.png"
})
},
u_textureTop: {
type: Cesium.UniformType.SAMPLER_2D,
value: new Cesium.TextureUniform({
url: "img/2.png"
})
}
},
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout vec3 positionMC)
{
v_normalMC = vsInput.attributes.normalMC;
}
`,
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
// 用法线Y分量判断:abs(normalMC.y) 接近1为顶面,接近0为侧面
float topFactor = abs(v_normalMC.y);
// 侧面UV:水平位置 + 高度,让贴图在墙面上正常平铺
vec2 uvSide = vec2(length(fsInput.attributes.positionMC.xz), fsInput.attributes.positionMC.y) * 0.05;
// 顶面UV:XZ平面
vec2 uvTop = fsInput.attributes.positionMC.xz * 0.05;
vec4 texSide = texture2D(u_texture, uvSide);
vec4 texTop = texture2D(u_textureTop, uvTop);
// 侧面贴图混合,顶部贴图混合
vec3 sideColor = mix(u_color.rgb, texSide.rgb, 0.5);
vec3 topColor = mix(u_color.rgb, texTop.rgb, 0.8);
// vec3 sideColor = texSide.rgb;
// vec3 topColor = texTop.rgb;
vec3 baseColor = mix(sideColor, topColor, topFactor);
// 上下渐变:底部暗,顶部亮
float height = fsInput.attributes.positionMC.y;
float t = clamp((height - u_minHeight) / (u_maxHeight - u_minHeight), 0.0, 1.0);
vec3 bottomColor = baseColor * 0.3;
vec3 topBright = baseColor * 1.5;
vec3 gradientColor = mix(bottomColor, topBright, t);
// 动态扫描光环(往返运动 0→1→0)
float time = fract(czm_frameNumber / 360.0);
float scanPos = abs(time - 0.5) * 2.0;
float glowWidth = 0.05;
float dist = abs(t - scanPos);
float glow = 1.0 - smoothstep(0.0, glowWidth, dist);
// 光环叠加亮度
vec3 glowColor = baseColor * 3.0;
vec3 finalColor = mix(gradientColor, glowColor, glow * 0.8);
material.diffuse = finalColor;
material.alpha = u_color.a;
}
`,
});
tileset.customShader = customShader;
tileset.name = name
this.viewer.scene.primitives.add(tileset);
var height = -10;//设置高度调整参数
tileset.readyPromise.then(function (argument) {
var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude + 0.000079, cartographic.latitude - 0.000041, cartographic.height + height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
argument.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
})
},
调用:
this.addTileset('./tileset/1/tileset.json', '0.7725, 0.756, 0.286, 0.8', 'yqjz')
效果:

贴图:

钻研不易,转载请注明出处。。。。。。

浙公网安备 33010602011771号