Cesium 三维场景中通过自定义着色器实现多种特效(纹理、光带、点光源、反射)
整体功能概述
构建一个基于 Cesium 的三维场景,加载三维瓦片集模型,同时提供多种特效,像夜景纹理、上下扫光、点光源以及反射纹理等,利用 dat.gui 库创建交互界面。
代码详解
白膜特效
nightFs.glsl
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {// 将法线值,直接作为颜色输出,这样可以确定模型的坐标轴// material.diffuse = normalize(v_normalMC);vec3 positionMC = fsInput.attributes.positionMC;// 如果片元在楼顶上,就不用贴图,直接给一个颜色if(dot(vec3(0., 0., 1.), v_normalMC) > 0.95) {material.diffuse = vec3(0.01, 0.1, 0.1);} else {// 先尝试使用x,z两个方向上的坐标来贴图// z的取值大概是0-500左右,x,y大概是0-200左右的取值vec2 uv = vec2(1., 1.);// // 确定uv的x轴// uv.x=fract(positionMC.x/pictureSize);// uv.y=fract(positionMC.z/pictureSize);// material.diffuse=texture2D(u_texture,uv).rgb;// 结论:只使用x,z进行贴图,在模型面垂直于x轴的情况下,由于x的变化非常小,所以导致贴图的质量很低// 所以我们需要判断,x轴和当前面的法向量的夹角float dotX = dot(vec3(1.0, 0.0, 0.0), v_normalMC);// 当前面和法向量垂直,这时,我们使用y,z贴图,这里注意,还考虑cos为负数的情况if(dotX > 0.9 || dotX < -0.9) {uv.x = fract(positionMC.y / u_pictureSize);} else {uv.x = fract(positionMC.x / u_pictureSize);}uv.y = fract(positionMC.z / u_pictureSize);material.diffuse = texture2D(u_texture, uv).rgb;}
}
这段代码用于Cesium引擎的GLSL着色器代码,主要用于动态调整3D模型表面的材质贴图方式。其核心功能是根据模型面的朝向智能选择贴图轴,避免拉伸,并区分楼顶和墙面。具体作用如下:
1. 楼顶处理
-
条件判断:通过法线方向(点积
dot(vec3(0., 0., 1.), v_normalMC) > 0.95
)检测当前片元是否属于楼顶(法线接近垂直向上)。 -
颜色固定:若为楼顶,直接赋予深青色
(0.01, 0.1, 0.1)
,跳过贴图逻辑,简化渲染。
2. 墙面贴图优化
-
动态UV选择:
-
计算法线与X轴的点积
dotX
,判断墙面是否垂直于X轴(|dotX| > 0.9
)。 -
垂直于X轴:使用Y和Z坐标生成UV的X分量,避免因X变化小导致的贴图拉伸。
-
其他情况:使用X和Z坐标生成UV的X分量,正常贴图。
-
-
贴图平铺:通过
fract(positionMC.axis / u_pictureSize)
对坐标分块,实现纹理重复,适应大尺寸模型。
3. 解决的问题
-
贴图拉伸:在垂直于X轴的墙面,改用Y轴生成UV,避免纹理因坐标变化不足而过度压缩。
-
视觉一致性:通过分块贴图(
fract
)保证纹理在不同面上均匀重复,提升细节表现。
4. 代码总结
-
输入:模型坐标
positionMC
、法线v_normalMC
、贴图尺寸u_pictureSize
。 -
输出:材质颜色
material.diffuse
,楼顶为固定色,墙面为动态贴图结果。 -
关键逻辑:基于法线方向动态选择UV轴,平衡贴图质量和性能。
该代码通过智能UV映射优化了建筑类模型的纹理表现,使墙面贴图更自然,同时简化楼顶渲染,是3D场景中常见的材质优化策略。
relfect.glsl
vec3 createPointLight(vec3 positionWC){// pow(clamp(1.-lightDistance/u_lightRadius,0. ,1.),2. );// lightDistance就是当前片元和点光源中心点的距离// length可以计算向量模,这里用当前的世界坐标-点光源的世界坐标float lightDistance=length(positionWC-u_lightPosition);float intensity=pow(clamp(1.-lightDistance/u_lightRadius,0. ,1.),2.);return u_lightColor*intensity;
}
vec3 createReflectColor(vec3 normal,vec3 positionEC){vec3 worldNormal=normalize(normal);vec3 eyeToSurfaceDir=normalize(positionEC);vec3 direction=reflect(eyeToSurfaceDir,worldNormal);// 使用反射向量的x,z进行贴图,看一下效果vec4 color=texture2D(u_envTexture,vec2(direction.x,direction.z));return color.rgb;
}
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material){vec3 positionWC=fsInput.attributes.positionWC;vec3 normalEC=fsInput.attributes.normalEC;// positionEC就是物体在相机坐标系下的坐标,在这里也可以理解为相机--->物体的向量vec3 positionEC=fsInput.attributes.positionEC;vec3 lightColor=createPointLight(positionWC);// 构造反射贴图的函数vec3 reflectColor=createReflectColor(normalEC,positionEC);// 将模型的颜色应用反射material.diffuse=reflectColor;vec3 positionMC=fsInput.attributes.positionMC;float czm_height=clamp((positionMC.z-380.)/320.,0.0,1.0);// 给白膜添加渐变material.diffuse*=czm_height;// 添加点光源material.diffuse+=lightColor;
}
这段代码是用于Cesium引擎的GLSL着色器程序,主要实现了一个结合 环境反射、高度渐变颜色 和 点光源照明 的复杂材质效果。以下是详细解析:
1. 核心函数解析
(1)createPointLight
函数
-
功能:计算点光源的衰减光强。
-
输入:片元的世界坐标
positionWC
。 -
逻辑:
-
计算片元与点光源的距离:
lightDistance = length(positionWC - u_lightPosition)
。 -
通过公式
intensity = pow(clamp(1.0 - lightDistance / u_lightRadius, 0.0, 1.0), 2.0)
计算光强衰减(距离越远,强度越低)。 -
返回光源颜色
u_lightColor
与强度的乘积。
-
-
作用:模拟点光源(如路灯、灯泡)的局部照明和衰减效果。
-
(2)createReflectColor
函数
-
功能:生成基于反射向量的环境贴图颜色。
-
输入:片元的法线
normal
和相机坐标系位置positionEC
。 -
逻辑:
-
标准化法线
worldNormal
和视线方向eyeToSurfaceDir
(从相机指向片元)。 -
计算反射方向
direction = reflect(eyeToSurfaceDir, worldNormal)
。 -
使用反射向量的 X和Z分量 作为UV坐标采样环境贴图
u_envTexture
。
-
-
作用:模拟环境反射(如镜面、金属表面),但此处仅用X/Z分量可能是为了简化效果(如地面或水平面反射)。
-
(3)fragmentMain
主函数
-
功能:组合所有效果,生成最终材质颜色。
-
逻辑流程:
-
环境反射:将材质基础色设为
reflectColor
。 -
高度渐变:根据模型坐标Z值(
positionMC.z
)生成渐变系数czm_height
,使底部(Z=380)到顶部(Z=700)颜色渐深。 -
叠加点光源:将点光源颜色
lightColor
直接叠加到材质颜色上。
-
-
2. 关键作用
(1)环境反射
-
实现:通过反射向量采样环境贴图,模拟表面反射周围环境。
-
简化设计:仅用X/Z分量可能针对特定场景(如地面反射),忽略垂直方向变化以提高性能。
(2)高度渐变
-
参数含义:
positionMC.z
表示模型坐标的垂直高度,(positionMC.z - 380)/320
将高度映射到[0, 1]
,实现从底部到顶部的颜色渐变。 -
用途:模拟建筑高度变化(如水位线、楼层颜色过渡)。
(3)点光源叠加
-
直接叠加:将点光源颜色
lightColor
直接加到材质颜色,模拟光源对表面的照明影响(如夜间建筑的局部亮斑)。
3. 潜在问题与优化
(1)反射方向问题
-
可能的Bug:
eyeToSurfaceDir
应是从表面指向相机的方向(即normalize(-positionEC)
),但代码中直接使用positionEC
可能导致反射方向错误。 -
修复建议:修改为
eyeToSurfaceDir = normalize(-positionEC)
。
(2)环境贴图采样
-
局限性:仅用X/Z分量可能导致反射扭曲(如垂直面反射异常)。
-
优化方案:改用立方体贴图(
textureCube
)或完整反射向量direction.xy
。
(3)光照模型简化
-
问题:直接叠加点光源可能过曝(未区分漫反射/高光)。
-
改进:采用Phong或PBR光照模型,分离漫反射与高光计算。
4. 代码总结
-
输入:片元的世界坐标、法线、模型坐标,光源参数(位置、颜色、半径),环境贴图。
-
输出:材质颜色 = 环境反射色 × 高度渐变 + 点光源颜色。
-
应用场景:建筑白模的复杂材质效果(如玻璃幕墙反射、楼层渐变、夜间灯光照明)。
通过组合反射、渐变和点光源,这段代码实现了动态的视觉表现,适用于需要高细节的3D场景(如城市建模、游戏场景)。
scanFs.glsl
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material){// 1.尝试在模型的中间生成一条光带vec3 positionMC=fsInput.attributes.positionMC;// czm_height取值范围在0-1之间,由于模型在地下有一段高度groundHeight,所以需要减去float czm_height=clamp((positionMC.z-groundHeight)/maxHeight,0.0,1.0);// 通过czm_height能够很快速的确定片元的高度// if(czm_height>0.5 && czm_height<0.505){// material.diffuse=vec3(1.,1.,1.);// }else{// material.diffuse=vec3(0.01,0.1,0.1);// }// 假设我们只需要一条固定光带 宽度为0.05// 将0.5变为iTime,这样可以让光带动起来float iTime=czm_frameNumber/120.;// 可以将iTime修改为一个来回运动的函数,这样光带的运动轨迹也是来回运动的iTime=abs(fract(iTime)*2.-1.);float czm_diff = step(u_scanWidth, abs(czm_height - iTime));// 添加渐变色,czm_height就是渐变因子material.diffuse=mix(vec3(0.1,1.0,0.2),vec3(1.,1.,1.),czm_height);material.diffuse += (material.diffuse * (1.0 - czm_diff)*3.0);
}
这段GLSL代码是用于Cesium引擎的片段着色器,主要实现了 动态高度渐变颜色 和 扫描光带效果,适用于3D模型的视觉增强(如建筑白模的动态高亮扫描)。以下是详细解析:
1. 核心功能
(1) 高度渐变底色
-
实现逻辑:
-
通过模型坐标的Z值
positionMC.z
计算归一化高度czm_height
,公式为:glsl
复制
czm_height = clamp((positionMC.z - groundHeight) / maxHeight, 0.0, 1.0);
将模型高度映射到
[0, 1]
范围,groundHeight
为地面基准高度,maxHeight
为最大高度。 -
颜色插值:使用
mix
函数将颜色从深绿色(0.1, 1.0, 0.2)
渐变到白色(1.0, 1.0, 1.0)
,渐变因子为czm_height
:glsl
复制
material.diffuse = mix(vec3(0.1,1.0,0.2), vec3(1.,1.,1.), czm_height);
-
效果:模型底部显示深绿色,顶部逐渐变为白色,模拟高度相关的颜色过渡(如海拔渐变)。
-
(2) 动态扫描光带
-
光带运动:
-
通过时间变量
iTime
控制光带位置:glsl
复制
float iTime = czm_frameNumber / 120.0; // 时间流逝(120帧为周期) iTime = abs(fract(iTime) * 2.0 - 1.0); // 生成三角波,使光带在0-1高度区间来回扫描
此处
iTime
被转换为一个在[0, 1]
之间来回振荡的值,形成光带上下扫描的效果。 -
光带区域判断:
glsl
复制
float czm_diff = step(u_scanWidth, abs(czm_height - iTime));
-
czm_height - iTime
计算当前高度与光带位置的差值。 -
abs(...)
获取差值的绝对值,step(u_scanWidth, ...)
判断差值是否超过光带宽度u_scanWidth
:-
若差值 小于 光带宽度,
czm_diff = 0
(光带区域)。 -
若差值 大于等于 光带宽度,
czm_diff = 1
(非光带区域)。
-
-
-
-
光带亮度增强:
glsl
复制
material.diffuse += (material.diffuse * (1.0 - czm_diff) * 3.0);
-
在光带区域(
czm_diff = 0
),将底色亮度提升3倍,形成高亮光带。 -
在非光带区域(
czm_diff = 1
),不叠加额外亮度。
-
2. 代码作用
-
视觉表现:
-
模型表面呈现 从深绿到白色的渐变底色,体现高度差异。
-
一条 动态扫描的白色光带 在模型表面上下移动,光带宽度由
u_scanWidth
控制,增强动态视觉效果。
-
-
应用场景:
-
建筑白模的动态扫描(如展示楼体检测、重点区域高亮)。
-
地形或管道的流动效果模拟(如液体流动、能量传输)。
-
3. 关键参数与优化建议
(1) 参数说明
参数 | 作用 |
---|---|
groundHeight | 模型地面基准高度(Z轴起点) |
maxHeight | 模型最大高度(Z轴范围) |
u_scanWidth | 光带宽度(值越小光带越细) |
czm_frameNumber | 引擎帧计数器,用于驱动时间动画 |
(2) 优化方向
-
平滑过渡:将
step
替换为smoothstep
,使光带边缘过渡更自然:glsl
复制
float czm_diff = smoothstep(u_scanWidth - 0.02, u_scanWidth + 0.02, abs(czm_height - iTime));
-
颜色控制:避免直接叠加亮度导致过曝,可改用加法混合或限制颜色范围:
glsl
复制
material.diffuse = min(material.diffuse + (vec3(1.0) * (1.0 - czm_diff)), 1.0);
-
性能优化:若需高频更新光带,可减少
czm_frameNumber
的除数(如/ 60.0
加快扫描速度)。
4. 效果示意图
复制
模型高度 ^ | ░▒▓ 白色光带(动态移动) | ▒░ | ▒░ ▓▒░ | ▒░ ▓▒░ ▒░ | ▒░ ▓▒░ ▒░ |▓▒░ ▒░ |-------------------> 颜色渐变(深绿 → 白)
这段代码通过高度渐变和动态光带,显著提升了模型的视觉吸引力,适用于需要动态高亮或扫描效果的3D场景(如智慧城市、工业仿真)。
白膜特效.js
import * as Cesium from 'cesium'
import * as dat from 'dat.gui'
import { TencentImageryProvider } from '@cesium-china/cesium-map'
import nightFs from '../shader/39.白膜特效/nightFs.glsl'
import scanFs from '../shader/39.白膜特效/scanFs.glsl'
import reflectFs from '../shader/39.白膜特效/reflect.glsl'const gui = new dat.GUI()
// Cesium Ion token
Cesium.Ion.defaultAccessToken ='mytoken'
// viewer是整个三维场景的入口
const viewer = new Cesium.Viewer('cesiumContainer', {// 隐藏默认显示的控件// 时间轴控件timeline: false,// 动画控件animation: false,// 设置底图切换控件baseLayerPicker: false,// 复位按钮的控件homeButton: false,// 全屏按钮的控件fullscreenButton: false,// 导航功能的控件geocoder: false,// 隐藏二三维模式的切换控件sceneModePicker: false,scene3DOnly: true,// 隐藏默认的导航按钮navigationHelpButton: false,// 时间是否流动shouldAnimate: true,imageryProvider: new Cesium.GridImageryProvider({cells: 1,glowWidth: 0,color: Cesium.Color.WHITE.withAlpha(0.1),backgroundColor: Cesium.Color.GRAY,}),
})const options = {style: 4, //style: img、1:经典crs: 'WGS84', // 使用84坐标系,默认为:GCJ02,
}
viewer.scene.imageryLayers.addImageryProvider(new TencentImageryProvider(options)
)const tileset = new Cesium.Cesium3DTileset({url: 'http://localhost:666/model/3dtiles/tileset.json',
})viewer.scene.primitives.add(tileset)viewer.scene.postProcessStages.bloom.enabled = true
viewer.scene.postProcessStages.bloom.uniforms.contrast = 119
viewer.scene.postProcessStages.bloom.uniforms.brightness = -0.4
viewer.scene.postProcessStages.bloom.uniforms.glowOnly = false
viewer.scene.postProcessStages.bloom.uniforms.delta = 0.9
viewer.scene.postProcessStages.bloom.uniforms.sigma = 3.78
viewer.scene.postProcessStages.bloom.uniforms.stepSize = 5const addNightTexture = () => {const customShader = new Cesium.CustomShader({uniforms: {u_texture: {type: Cesium.UniformType.SAMPLER_2D,value: new Cesium.TextureUniform({url: '/src/assets/wall.png',}),},u_pictureSize: {type: Cesium.UniformType.FLOAT,value: 100.0,},},varyings: {v_normalMC: Cesium.VaryingType.VEC3,},vertexShaderText: /*glsl*/ `void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {// normalMC可以在顶点中,通过vsInput获取v_normalMC=vsInput.attributes.normalMC;}`,fragmentShaderText: nightFs,})tileset.customShader = customShader
}// 白膜的上下扫光功能
const addScanCircle = () => {const customShader = new Cesium.CustomShader({uniforms: {// 地上的最高高度maxHeight: {type: Cesium.UniformType.FLOAT,value: 320.0,},//经过debug法线,在模型的地下,还有一截高度,这个高度,我测试出来是380m左右groundHeight: {type: Cesium.UniformType.FLOAT,value: 380.0,},u_scanWidth: {type: Cesium.UniformType.FLOAT,value: 0.005,},},varyings: {v_normalMC: Cesium.VaryingType.VEC3,},vertexShaderText: /*glsl*/ `void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {// normalMC可以在顶点中,通过vsInput获取v_normalMC=vsInput.attributes.normalMC;}`,fragmentShaderText: scanFs,})tileset.customShader = customShader
}const addPointLight = () => {const customShader = new Cesium.CustomShader({uniforms: {// [121.44835554037566, 31.2328027614941]u_lightPosition: {type: Cesium.UniformType.VEC3,value: Cesium.Cartesian3.fromDegrees(121.44835554037566,31.2328027614941,1),},u_lightColor: {type: Cesium.UniformType.VEC3,value: Cesium.Color.fromCssColorString('#6900ff'),},u_lightRadius: {type: Cesium.UniformType.FLOAT,value: 2000,},},varyings: {v_normalMC: Cesium.VaryingType.VEC3,},vertexShaderText: /*glsl*/ `void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {// normalMC可以在顶点中,通过vsInput获取v_normalMC=vsInput.attributes.normalMC;}`,fragmentShaderText: /*glsl*/ `vec3 createPointLight(vec3 positionWC){// pow(clamp(1.-lightDistance/u_lightRadius,0. ,1.),2. );// lightDistance就是当前片元和点光源中心点的距离// length可以计算向量模,这里用当前的世界坐标-点光源的世界坐标float lightDistance=length(positionWC-u_lightPosition);float intensity=pow(clamp(1.-lightDistance/u_lightRadius,0. ,1.),2.);return u_lightColor*intensity;}void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material){vec3 positionWC=fsInput.attributes.positionWC;vec3 lightColor=createPointLight(positionWC);vec3 positionMC=fsInput.attributes.positionMC;float czm_height=clamp((positionMC.z-380.)/320.,0.0,1.0);// 给白膜添加渐变material.diffuse*=czm_height;// 添加点光源material.diffuse+=lightColor;}`,})tileset.customShader = customShader
}const addReflectTexture = () => {const customShader = new Cesium.CustomShader({uniforms: {// cesium在customShader不支持textureCubeu_envTexture: {type: Cesium.UniformType.SAMPLER_2D,value: new Cesium.TextureUniform({url: '/src/assets/pic.jpg',}),},// [121.44835554037566, 31.2328027614941]u_lightPosition: {type: Cesium.UniformType.VEC3,value: Cesium.Cartesian3.fromDegrees(121.44835554037566,31.2328027614941,1),},u_lightColor: {type: Cesium.UniformType.VEC3,value: Cesium.Color.fromCssColorString('#6900ff'),},u_lightRadius: {type: Cesium.UniformType.FLOAT,value: 2000,},},varyings: {v_normalMC: Cesium.VaryingType.VEC3,},vertexShaderText: /*glsl*/ `void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {// normalMC可以在顶点中,通过vsInput获取v_normalMC=vsInput.attributes.normalMC;}`,fragmentShaderText: reflectFs,})tileset.customShader = customShader
}tileset.readyPromise.then((res) => {viewer.zoomTo(tileset)console.log(tileset.properties)// 使用DebugModelMatrixPrimitive将世界坐标可视化出来viewer.scene.primitives.add(new Cesium.DebugModelMatrixPrimitive({modelMatrix: tileset._root.transform,length: 50000.0,width: 3.0,}))addReflectTexture()
})
这段代码是用于 Cesium 3D地理可视化引擎 的复杂场景构建脚本,主要实现以下核心功能:
1. 场景初始化与基础配置
-
引擎配置:
-
隐藏默认控件(时间轴、动画、底图选择器等),保持界面简洁。
-
设置白色半透明网格底图(
GridImageryProvider
),用于调试时辅助观察模型位置。 -
添加腾讯地图影像图层(
TencentImageryProvider
),支持WGS84
坐标系。
-
-
模型加载:
-
通过
Cesium3DTileset
加载本地3D瓦片模型(http://localhost:666/model/3dtiles/tileset.json
),为建筑白模或城市模型。
-
-
后处理特效:
-
启用 Bloom辉光效果,调整参数(对比度、亮度、模糊半径)增强光带、光源的视觉冲击力。
-
2. 自定义着色器效果
通过 Cesium.CustomShader
实现四种动态材质效果,支持按需切换:
(1) 夜间纹理贴图 (addNightTexture
)
-
功能:为模型表面添加动态纹理(如墙面材质)。
-
关键参数:
-
u_texture
: 2D纹理贴图(wall.png
),控制墙面细节。 -
u_pictureSize
: 贴图平铺尺寸,影响纹理密度。
-
-
实现:通过顶点法线
normalMC
计算UV坐标,区分墙面与楼顶,楼顶固定颜色,墙面动态贴图。
(2) 扫描光带效果 (addScanCircle
)
-
功能:在模型表面生成 上下移动的白色光带,模拟扫描检测效果。
-
关键参数:
-
maxHeight
: 模型最大高度(320米)。 -
groundHeight
: 地面基准高度(380米)。 -
u_scanWidth
: 光带宽度(0.005)。
-
-
实现:
-
通过模型高度
positionMC.z
计算归一化高度czm_height
。 -
使用时间变量
iTime
生成三角波,驱动光带上下扫描。 -
通过
mix
函数实现底部到顶部的颜色渐变(深绿→白),叠加光带亮度。
-
(3) 点光源照明 (addPointLight
)
-
功能:模拟点光源(如路灯)对模型的局部照明。
-
关键参数:
-
u_lightPosition
: 光源世界坐标(经度121.44835554037566
, 纬度31.2328027614941
)。 -
u_lightColor
: 光源颜色(紫色#6900ff
)。 -
u_lightRadius
: 光照半径(2000米)。
-
-
实现:
-
计算片元与光源的距离
lightDistance
,通过衰减公式pow(clamp(...), 2)
控制光强。 -
叠加光源颜色到模型基础色,形成局部亮斑。
-
(4) 环境反射贴图 (addReflectTexture
)
-
功能:模拟表面反射环境贴图(如玻璃幕墙反射天空)。
-
关键参数:
-
u_envTexture
: 2D环境贴图(pic.jpg
),替代立方体贴图(Cesium限制)。
-
-
实现:
-
计算视线方向
eyeToSurfaceDir
与法线normalEC
的反射向量。 -
使用反射向量的X/Z分量采样环境贴图,生成反射颜色。
-
3. 调试与可视化工具
-
坐标轴可视化:
-
通过
DebugModelMatrixPrimitive
显示模型的世界坐标轴(长度5万米),辅助定位。
-
-
状态栏:
-
PositionStatusBar
实时显示相机经纬度、高度等信息。
-
4. 代码作用总结
-
核心目标:在Cesium中渲染3D建筑模型,并叠加 动态材质效果,提升视觉表现力。
-
应用场景:
-
智慧城市:建筑白模的夜间灯光、扫描检测、环境反射。
-
工业仿真:设备表面动态光效、局部照明。
-
游戏开发:复杂材质效果(反射、辉光)的快速实现。
-
5. 参数调整示例
// 示例:通过GUI调整光带宽度
gui.add(options, 'u_scanWidth', 0.001, 0.1).onChange((val) => {tileset.customShader.uniforms.u_scanWidth.value = val;
});// 示例:切换效果
const effects = { '反射': addReflectTexture, '光带': addScanCircle };
gui.add(effects, '效果').onChange((fn) => fn());
该代码通过模块化设计支持快速扩展,是Cesium高级材质开发的典型实践。
相关文章:
Cesium 三维场景中通过自定义着色器实现多种特效(纹理、光带、点光源、反射)
整体功能概述 构建一个基于 Cesium 的三维场景,加载三维瓦片集模型,同时提供多种特效,像夜景纹理、上下扫光、点光源以及反射纹理等,利用 dat.gui 库创建交互界面。 代码详解 白膜特效 nightFs.glsl void fragmentMain(Fragm…...
Java学习--HashMap
HaspMap是Java集合框架中最重要、最常用的数据结构之一。其基于哈希表实现了Map接口,在Java1.8的版本中,其采用了“数组链表红黑树”的混合结构,底层代码如下: transient Node<K,V>[] table; // 哈希桶数组 static class N…...
Monorepo、Lerna、Yarn Workspaces、pnpm Workspaces 用法
Monorepo 介绍 Monorepo是一种方案,而非具体的工具。 Monorepo指的是将多个相关的项目或模块放在同一个代码仓库中进行管理的方式。这种方案有以下优点: 方便代码共享:不同项目或模块之间可以方便地共享代码、组件、工具函数等,…...
JVM指令手册:深入理解字节码执行机制
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 引言 Java虚拟机(JVM)作为Java生态的核心执行引擎,其指令系统是理解程序底层运行机制的关键。本手册将系统解析JVM指令集…...
springboot logback 默认加载配置文件顺序
在 Spring Boot 应用中,Logback 默认加载配置文件的顺序遵循特定的规则。以下是详细的加载顺序和优先级说明: 1. 默认配置文件加载顺序 Logback 在 Spring Boot 中会按以下顺序查找并加载配置文件(优先级从高到低): l…...
用 Nodemon 解决 npm run serve 频繁重启服务
Nodemon 是一个基于 Node.js 构建的开发工具,专为帮助开发者自动监控项目文件的更改而设计。每当文件发生变更时,Nodemon 会自动重启 Node.js 服务器,无需手动停止并重启。这对于提升开发速度、减少人工操作非常有帮助,尤其适用于…...
WEB安全--社会工程--SET钓鱼网站
1、选择要钓鱼的网站 2、打开kali中的set 3、启动后依次选择: 4、输入钓鱼主机的地址(kali)和要伪装的网站域名: 5、投放钓鱼网页(服务器域名:80) 6、获取账号密码...
系统架构师---基于规则的系统架构
引言 在业务规则高度动态且需快速响应的系统中,基于规则的系统架构风格(Rule-Based System Architecture Style)提供了一种将业务逻辑与代码解耦的标准化范式。从保险理赔的自动化审核到金融风控的实时拦截,规则引擎已成为企…...
嵌入式软件--stm32 DAY 4 中断系统
1.课后练习 学了这么长时间,现在让我们第一次做练习。 1.1往返流水灯 1.1.1 LED1-LED2-LED3-LED2-LED1循环 (1)工程准备 复制上一个寄存器实现的工程文档,删减修改我们正要实现的工程。为了区别练习和学习工程,我们…...
android开发制作aosp系统签名文件给普通apk签名使用
platform.pk8和platform.x509.pem复制出来放在同一目录下 将AOSP源码路径下build\target\product\security\platform.pk8和platform.x509.pem复制出来放在同一目录下 新开一个ternimal窗口执行下面命令,生成platform.pem文件 openssl pkcs8 -in platform.pk8 -info…...
AVL树的介绍与学习
目录 1.前言 2.AVL树 3.AVL树的插入 平衡因子的更新 更新停止的条件 旋转 1.前言 在学习了二叉搜索树,set和map之后,我们接下来趁热打铁,继续学习AVL树。 2.AVL树 1.AVL树具有二叉搜索树的性质,但是它的左右子树的高度差不…...
docker部署Mysql8一直密码错误记录
正常流程是这样得: 第一步 #拉镜像 docker pull mysql:8.0 第二步 #运行名为 mysql8 得容器 ,MYSQL_ROOT_PASSWORD123456 设置密码 docker run -p 3307:3306 \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD123456 \ -v /docker/mysql8/data:/var/lib/m…...
智慧水库与AI深度融合的实现方案及典型应用场景
以下是智慧水库与AI深度融合的实现方案及典型应用场景,结合行业前沿案例与技术架构展开: 一、智慧水库AI实现方案 1. 技术架构与核心工具 感知层: 多模态传感器网络:部署毫米波雷达水位计(精度3mm)、光纤光栅渗压计(分辨率0.01%FS)、高清智能球机(支持800万像素+AI分…...
大语言模型架构基础与挑战
大语言模型(Large Language Model, LLM)在近几年引领了自然语言处理领域的革命性进展。这类模型通常拥有极其庞大的参数规模(往往达到数十亿乃至数千亿级别),通过对海量文本数据进行自监督训练,展现出卓越的语言理解和生成能力。自2018年前后第一批大语言模型问世以来,基…...
KAG:通过知识增强生成提升专业领域的大型语言模型(二)
目录 摘要 Abstract 1 实验 1.1 实验设置 1.2 总体结果 1.3 消融研究 1.3.1 知识图谱索引消融 1.3.2 推理与检索消融 1.3.3 实验结果与讨论 2 KAG服务部署 2.1 安装Docker 2.2 安装Doker Compose 2.3 启动服务 2.4 查看状态 2.5 产品访问 3 KAG 0.6使用&#x…...
【Luogu】动态规划六
P1586 四方定理 - 洛谷 思路: 这题其实就是完全背包问题,但是有限制,最多数量只能是 4 所以我们可以定义 dp[i][j] 为 i 用 j 个数拼凑的总方案数 那么转移方程也很明显了,dp[i][j] dp[i - k*k][j - 1] 具体的,我…...
Postman接口测试: postman设置接口关联,实现参数化
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 postman设置接口关联 在实际的接口测试中,后一个接口经常需要用到前一个接口返回的结果, 从而让后一个接口能正常执行,这个…...
docker打开滚动日志
在 Docker 中启用滚动日志(log rotation)可以帮助你管理容器日志的大小,避免日志文件占用过多磁盘空间。以下是具体的操作步骤: 1. 修改 Docker 守护进程配置 Docker 的日志配置是通过 daemon.json 文件管理的。你需要修改此文件…...
单片机-89C51部分:5、点亮LED
飞书文档https://x509p6c8to.feishu.cn/wiki/SlB5wYD1QiPRzWkfijEcIvv8nyc 一、应用场景 二、点灯原理 插件led灯珠长引脚为正极,短引脚为负极。 LED(发光二极管)两端存在电压差,有一定的电流流过时会亮起。电流可以理解为水流,…...
Lua 第10部分 模式匹配
10.1 模式匹配的相关函数 字符串标准库提供了基于模式的 4 个函数。 我们已经初步了解过函数 find 和 gsub,其余两个函数分别是 match 和 gmatch (Global Match 的缩写)。 函数 string.find 用于在指定的目标字符串中搜索指定的模式。最简单的模式就是一…...
Maven 4.0.0 模式-pom.xml配置详解
Maven 4.0.0 模式-pom.xml配置详解 此 pom.xml 文件涵盖了 Maven 4.0.0 模式支持的所有主要标签,包括项目元数据、依赖管理、构建配置、发布管理等。每个标签都配有详细注释,说明其作用、常见用法和可能的值。 此文件旨在展示标签的完整性&#…...
IDEA 连接 Oracle 数据库
IDEA 连接 Oracle 数据库...
机器人快速启动
机器人快速启动 ES机器人开机操作流程 方法一(一体化底座启动) 接通48V电源点击底座“Power”按钮观察电源指示灯亮起,蜂鸣器发出“嘀”声,代表底座启动完成 方法二(控制手柄启动) 长按手柄开关机键2秒后松…...
使用 MediaPipe 和 OpenCV 快速生成人脸掩膜(Face Mask)
在实际项目中,尤其是涉及人脸识别、换脸、图像修复等任务时,我们经常需要生成人脸区域的掩膜(mask)。这篇文章分享一个简单易用的小工具,利用 MediaPipe 和 OpenCV,快速提取人脸轮廓并生成二值掩膜图像。 …...
《全球反空间能力》报告翻译——部分1
全球反空间能力 已进行过破坏性反卫星测试的国家 美国 美国目前拥有世界上最先进的军事太空能力,尽管与中国的相对差距正在缩小。在冷战期间,美国开创了许多现今使用的国家安全太空应用,并在几乎所有类别中保持技术领先地位。美国军方在将…...
云原生课程-Docker
一次镜像,到处运行。 1. Docker详解: 1.1 Docker简介: Docker是一个开源的容器化平台,可以帮助开发者将应用程序和其依赖的环境打包成一个可移植的,可部署的容器。 docker daemon:是一个运行在宿主机(DO…...
组件的基本知识
组件 组件的基本知识 组件概念组成步骤好处全局注册生命周期scoped原理 父子通信步骤子传父 概念 就是将要复用的标签,抽离放在一个独立的vue文件中,以供主vue文件使用 组成 三部分构成 template:HTML 结构 script: JS 逻辑 style: CSS 样…...
空间矩阵的思考
今天又看了些线性代数,引发了许多思考。 矩阵是以长和宽存储数据,那有没有一种新型的矩阵,以长宽高的形式存储数据呢?我不知道有没有,所以暂且称其为空间矩阵。 它肯定是存在的,可以这样抽象&#…...
【数据挖掘】时间序列预测-常用序列预测模型
常用序列预测模型 (1)AR(自回归)模型(2)ARIMA模型(3)Prophet模型(4)LSTM模型(5)Transformer模型(6)模型评估6.…...
将你的本地项目发布到 GitHub (新手指南)
目录 第 1 步:在 GitHub 上创建新的仓库 (Repository)第 2 步:将本地仓库连接到 GitHub 远程仓库第 3 步:(可能需要) 重命名你的默认分支第 4 步:将本地代码推送到 GitHub第 5 步:在 GitHub 上检查结果后续工作流程 你…...
[论文梳理] 足式机器人规划控制流程 - 接触碰撞的控制 - 模型误差 - 自动驾驶车的安全合规(4个课堂讨论问题)
目录 问题 1:足式机器人运动规划 & 控制的典型流程 (pipline) 1.1 问题 1.2 目标 1.3 典型流程(Pipeline) 1.3.1 环境感知(Perception) 1.3.2 高层规划(High-Level Planning) 1.3.3 …...
初中级前端面试全攻略:自我介绍模板、项目讲解套路与常见问答
为了给面试官留下专业而亲切的第一印象,自我介绍要突出与岗位相关的技能和项目经验,同时以自己擅长的领域开放式结尾。通常可以按照以下思路组织自我介绍内容:首先简单介绍个人信息和工作年限,然后列出精通的前端技术栈…...
Android开发中svg转xml工具使用
要使用 svg2vector-cli 工具通过命令行将 SVG 文件转换为 Android 可用的 XML 矢量图标文件,可以单个文件转换或者整个文件夹批量转换,以下是详细的步骤和说明: 1. 准备工作 1.1 下载工具 首先需要下载 svg2vector-cli-1.0.0.jar 或更高版本…...
爬虫技术入门:基本原理、数据抓取与动态页面处理
引言 在当今数据驱动的时代,网络爬虫技术已成为获取和分析互联网数据的重要手段。无论是搜索引擎的网页收录、竞品数据分析,还是学术研究的语料收集,爬虫技术都发挥着关键作用。本文将深入浅出地讲解爬虫的基本原理,分析它能获取…...
AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年4月27日第65弹
从今天开始,咱们还是暂时基于旧的模型进行预测,好了,废话不多说,按照老办法,重点8-9码定位,配合三胆下1或下2,杀1-2个和尾,再杀6-8个和值,可以做到100-300注左右。 (1)定…...
服务器数据备份,服务器怎么备份数据呢?
企业数据量呈指数级增长,服务器数据备份已成为保障业务连续性、抵御勒索攻击与合规审查的核心技术环节。当前,服务器数据备份方案需兼顾数据完整性、恢复时效性、存储经济性三大核心诉求,其实现路径可根据技术架构、数据规模及容灾等级划分为…...
语音识别质量的跟踪
背景 这个项目是用来生成结构化的电子病历的。数据的来源是医生的录音。中间有一大堆的处理,语音识别,关键字匹配,结构化处理,病历编辑......。最多的时候给上百家医院服务。 语音识别质量的跟踪 一、0225医院的训练后的情况分…...
【数据挖掘】时间序列预测-时间序列的平稳性
时间序列的平稳性 (1)平稳性定义(2)平稳性处理方法2.1 差分法2.2 季节调整(Seasonal Adjustment)2.3 趋势移除(Detrending)2.4 对数转换(Logarithmic Transformation&…...
成都蒲江石象湖旅游攻略之石象湖郁金香最佳观赏时间
石象湖坐落于成都蒲江,拥有绝美的郁金香花海,吸引了很多的游客。如果大家想要观赏比较诱惑人的郁金香,那自然就应该知道正确的观赏时间。 心想郁金香合适的时间是每年的3月份到3月底。石象湖会还会举办盛大的郁金香节,在花园内有数…...
大模型、知识图谱和强化学习三者的结合,可以形成哪些研究方向?
大模型(Large Language Models, LLMs)、知识图谱(Knowledge Graph, KG)与强化学习(Reinforcement Learning, RL)作为人工智能领域的三大核心技术,其融合正推动着认知智能迈向新高度。本文结合2023-2025年的最新研究成果,系统梳理三者结合的七大科研方向及其技术路径。 …...
Linux文件操作
在C语言中,我们已经学习了文件相关的知识,那么在Linux中我们为什么还要再来学习文件呢?这是因为C语言中和Linux中,"文件"是2个不同的概念。所以我们要来学习Linux中对文件的操作。 在学习之前,我们先来回顾一…...
PostSwigger Web 安全学习:CSRF漏洞3
CSRF 漏洞学习网站:What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy CSRF Token 基本原理 CSRF Token 是服务端生成的唯一、随机且不可预测的字符串,用于验证客户端合法校验。 作用:防止攻击…...
【Node.js 】在Windows 下搭建适配 DPlayer 的轻量(简陋)级弹幕后端服务
一、引言 DPlayer官网:DPlayer 官方弹幕后端服务:DPlayer-node MoePlayer/DPlayer-node:使用 Docker for DPlayer Node.js 后端(https://github.com/DIYgod/DPlayer) 本来想直接使用官网提供的DPlayer-node直接搭建…...
淘宝tb.cn短链接生成
淘宝短链接简介 1. 一键在线生成淘宝短链接tb.cn,m.tb.cn等 2. 支持淘宝优惠券短链接等淘宝系的所有网址 3. 生成的淘宝短链接是官方的,安全稳定有保证 4.适合多种场景下使用,如:网站推广,短信推广 量大提供api接口࿰…...
在web应用后端接入内容审核——以腾讯云音频审核为例(Go语言示例)
腾讯云对象存储数据万象(Cloud Infinite,CI)为用户提供图片、视频、语音、文本等文件的内容安全智能审核服务,帮助用户有效识别涉黄、违法违规和广告审核,规避运营风险。本文以音频审核为例给出go语言示例代码与相应结…...
优化无头浏览器流量:使用Puppeteer进行高效数据抓取的成本降低策略
概述 使用 Puppeteer 进行数据抓取时,流量消耗是一个重要考虑因素。特别是在使用代理服务时,流量成本可能显著增加。为了优化流量使用,我们可以采用以下策略: 资源拦截:通过拦截不必要的资源请求来减少流量消耗。请求…...
【C语言】fprintf与perror对比,两种报错提示的方法
它们的主要区别在于 信息来源 和 自动包含的系统错误详情。 1. fprintf(stderr, "自定义错误信息\n"); 功能: 这是标准库中的一个通用格式化输出函数。你可以用它向任何文件流(包括 stdout 标准输出, stderr 标准错误, 或任何用 fopen 打开的文件&#x…...
C语言复习笔记--内存函数
在复习完字符函数和字符串函数之后,今天让我们复习一下内存函数吧.这一块的东西不太多,并且与之前的字符串函数有一些地方很相似,所以这里应该会比较轻松. memcpy使用和模拟实现 老规矩,先看函数原型 void * memcpy ( void * destination, const void * source, size_t num );…...
前端面试高频算法
前端面试高频算法 1 排序算法;1.1 如何分析一个排序算法1.1.1 执行效率3.1.2 内存消耗1.1.3 稳定性 1.2 冒泡排序(Bubble Sort)1.3 插入排序(Insertion Sort)1.4 选择排序(Selection Sort)1.5 归…...
云原生--核心组件-容器篇-4-认识Dockerfile文件(镜像创建的基础文件和指令介绍)
1、Dockerfile的定义与作用 定义: Dockerfile是一个文本文件,包含一系列Docker指令,用于自动化构建Docker镜像。Docker 在构建镜像时会按照Dockerfile中的指令逐步执行,每一行指令都会生成一个新的镜像层(layer&#x…...