惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
Jina AI
Jina AI
The Cloudflare Blog
V
Visual Studio Blog
博客园_首页
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 【当耐特】
爱范儿
爱范儿
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
博客园 - 司徒正美
阮一峰的网络日志
阮一峰的网络日志
Last Week in AI
Last Week in AI
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
博客园 - Franky

博客园 - 莫小龙

wps之使用宏修改全篇表格样式 geoserver之强制配置OnlineResource mysql之将shp转化为wkt,然后存储再geomerty字段内 uniapp之plus.downloader.createDownload下载文件传参 谷歌之将网页保存为图片 elementui之table中相同数据的单元格合并 krpano之使用教程 threejs之灯光不跟随OrbitControls控制器旋转 threejs之将张纹理图片组成材质组 canvas之修改Base64图片中不透明部分的颜色 threejs之将PlaneGeometry转换为BufferGeometry threejs之利用shape通过线绘制面和体 threejs之添加渐变背景 threejs之创建发光墙体 paperjs之fitBounds适应区域前后屏幕坐标和输入坐标的转换 arcmap之通过点数据获取等值线 uniapp之安卓APP打开百度地图、高德地图APP openlayer之添加带箭头的线 geoserver之图片图标样式 SHP转WKT文件工具 openlayers之geoserver的wms图层mysql数据源数据修改后更新问题 通过日照时数计算每天RAD(太阳辐射)值 Uniapp之安卓签名证书(.keystore)生成
cesium之用着色器添加建筑贴图
莫小龙 · 2026-07-08 · via 博客园 - 莫小龙
        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')