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')

 效果:

image

贴图:

2   4

 

 

 

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

posted @ 2026-07-08 15:36  莫小龙  阅读(8)  评论(0)    收藏  举报