大家好,我是日拱一卒的攻城师不浪,致力于前沿科技探索,摸索小而美工作室。这是2025年输出的第9/100篇文章。
效果预览
【在线预览地址】:jiawanlong.github.io/Cesium-Exam...
前言
曾经有很多朋友问我:如何在Cesium中做视频投射
,能不能讲一讲实现思路?今天它来啦!源码文末自取!
可能有的小伙伴还不了解:视频投射是什么东东?我们先来了解一下,这个东东它的应用场景都有啥?
视频投射应用场景
-
虚拟现实与增强现实
通过将视频投射到
3D模型
或地理
场景中,可以为用户提供身临其境的沉浸式体验
。例如,将实时视频投射到指定道路路口
,工作人员可以在虚拟环境中直观感受实时交通情况的变化,并针对突发状况做出及时响应。
-
数字孪生与城市建模
在城市建模中,将实时视频投射到数字孪生模型中,可以展示现实世界中的动态场景。例如,在建筑物或街道模型上叠加实时视频流,用于
监控
、广告
或旅游
展示。 -
灾难管理与应急响应
通过在Cesium场景中投射实时视频,配合
地理信息系
(GIS),可以帮助应急响应团队实时监控灾难现场
,提供更准确的决策支持。比如,地震后的视频数据投射可以帮助救援队伍迅速评估受灾区域。
-
文化遗产保护与虚拟博物馆
视频投射可用于展示历史遗址或文化遗产的
数字化复原
,用户可以通过Cesium虚拟漫游查看遗址的实时视频或复原视频,增进对历史文化的理解。
其外,视频投射系统还适用于AR导航
等地理空间可视化场景等。
原理解析
在做一个功能之前,我们需要先分析其功能,解析出原理,才能对整体做把控。
那么在Cesium中实现视频投射的核心原理主要是通过视锥体几何 和动态材质绑定技术:
-
视锥体建模 :基于摄像机参数(
位置
、视角
、方向
)构建一个3D视锥体
几何,定义视频投射的空间范围; -
视频材质映射 :将
HTML5视频元素
作为纹理贴图
,通过GLSL着色器实时渲染
到视锥体表面; -
动态坐标转换 :利用Cesium的坐标系(
WGS84/Cartesian3
)实现地理空间定位,保证视频投射与地球表面的精确对齐。
关键代码解析
视锥体创建
javascript
createLightCamera() {
this.lightCamera = new Cesium.Camera(this.viewer.scene);
this.lightCamera.frustum.near = this.viewDistance * 0.0001;
this.lightCamera.frustum.far = this.viewDistance;
// 计算宽高比和视场角
const aspectRatio =
(this.viewDistance * Math.tan(hr / 2) * 2) /
(this.viewDistance * Math.tan(vr / 2) * 2);
this.lightCamera.setView({
orientation: {
heading: Cesium.Math.toRadians(this.viewHeading),
pitch: Cesium.Math.toRadians(this.viewPitch)
}
});
}
-
摄像机参数 :通过
near/far
控制视锥体深度范围; -
方向控制 :
heading/pitch
确定视锥体朝向; -
宽高比计算 :基于
水平/垂直
视角动态计算投影比例;
通过Cesium.FrustumGeometry
生成几何体,使用Cesium.FrustumOutlineGeometry
绘制边框。
视频材质绑定
js
createAppearance() {
let source = `czm_material czm_getMaterial(...) {
vec4 colorImage = texture(image, st);
material.alpha = colorImage.a * color.a * maskImage.r;
material.diffuse = colorImage.rgb * color.rgb;
}`;
let material = new Cesium.Material({
fabric: {
uniforms: {
image: video_dom, // 绑定视频元素
tmask: "data:image/jpg;base64,..." // 透明遮罩
}
}
});
return new Cesium.EllipsoidSurfaceAppearance({ material });
}
-
动态着色器 :通过自定义
GLSL
实现视频与遮罩的混合; -
实时更新 :将
<video>
元素作为纹理输入; -
透明处理 :通过
alpha
通道控制视频透明度;
创建包含视频元素的Material
实例,通过PerInstanceColorAppearance
实现实例化渲染。
地理坐标交互
js
getCurrentMousePosition(scene, position) {
// 通过射线与地球表面求交
if(scene.mode === Cesium.SceneMode.SCENE3D) {
const pickRay = scene.camera.getPickRay(position);
return scene.globe.pick(pickRay, scene);
}
return scene.camera.pickEllipsoid(position);
}
-
三维拾取:在3D模式下通过射线与地球求交;
-
坐标系转换 :将屏幕坐标转换为
WGS84
地理坐标; -
高程适配 :通过
globe.pick
自动处理地形高度;
动态更新
监听视频播放事件更新材质,通过requestAnimationFrame
实现帧同步。
关键技术点
技术点 | 实现方式 | 作用 |
---|---|---|
视锥体参数化 | 动态计算宽高比/视场角 | 适配不同视频比例 |
坐标系转换 | Cesium.Transforms.eastNorthUpToFixedFrame |
地理空间准确定位 |
性能优化 | 使用Primitive替代Entity | 提升渲染效率 |
透明通道处理 | GLSL混合视频与遮罩纹理 | 实现边缘融合效果 |
如何使用
javascript
// 初始化参数
const options = {
horizontalViewAngle: 60, // 水平视场角
verticalViewAngle: 40, // 垂直视场角
video: "video_dom", // 视频DOM ID
viewPosition: Cartesian3.fromDegrees(85.788705, 45.161394, 900), // 锥体原点
viewPositionEnd: Cartesian3.fromDegrees(85.788705, 45.167394, 500) // 锥体远点
};
// 创建视频投射实例
const videoProjector = new CesiumVideo(viewer, options);
videoProjector.drawVideo();
// 控制视频播放
document.getElementById('video_dom').play();
最后
【源码地址 】:github.com/jiawanlong/...
不浪的【Cesium案例集合源码 】:github.com/tingyuxuan2...
如果开源对您有帮助,也欢迎帮我们点一个免费的star
,以鼓励和支持我们开源更多案例!
不会Cesium的基础,也很难做出更高级的效果,所以可以了解下不浪的教程
《Cesium从入门到实战》
,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市
的完整项目,课程也在不断更新迭代中,想了解+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群
可以加我:brown_7778(备注来意)。