DengQN·一个普通程序员;
【Cesium】使用图元加载视频到场景
2024-03-27 10:29 734
#Cesium#视频融合

方案

基本原理就是把Element作为贴图贴到自定义的材质里。这样可以方便使用shader等对材质做进一步处理。直接使用Entity加入局限性比较大。

1、使用video标签播放视频

其中样式不能display: none或者移出窗口外,否则在cesium内只能渲染第一帧。所以直接把透明度设置为全透明 opacity: 0;

<video  crossorigin="anonymous" style="width: 100px; height: 100px; position: fixed; top: 0; opacity: 0;" id="v" loop="" class="video-js" autoplay="autoplay" preload="auto" muted>
    <source src="x">
</video>


// js
let videoElement = document.getElementById('v');

2、创建自定义材质

let m  =new Material({
    fabric: {
        uniforms: {
            image: "",
        },
        source: shaderSource
    }
})
m.uniforms.image = videoElement;

直接使用new的方式初始化材质对象。在初始化完成后我们再通过uniforms 传入视频节点。其中fabric.source 为shader的代码

可以写一个最简单的shader:

let shaderSource = `
czm_material czm_getMaterial(czm_materialInput materialInput) 
{
    czm_material material = czm_getDefaultMaterial(materialInput);
    material.diffuse = texture(image, materialInput.st).rgb;
    return material;
}
`

czm_getMaterial 是内置的入口函数,return的内容是显示的结果。

然后就是创建Primitive并添加到view

await GroundPrimitive.initializeTerrainHeights() 
const primitive = new GroundPrimitive({
    asynchronous: false,
    geometryInstances: new GeometryInstance({
        geometry: new PolygonGeometry({
            polygonHierarchy: new PolygonHierarchy(Cartesian3.fromDegreesArray([
            110.50940051824507, 25.652613985682056,
            110.53054820489356, 25.625936676583187,
            110.5577535658818, 25.641588383493374,
            110.54154406073128, 25.6676382250381,
            ]))
        })
    }),
    appearance: new MaterialAppearance({
        // closed: false,
        material: m,
        renderState: {
            blending: BlendingState.ALPHA_BLEND
        }
        // renderState: {
        // 	blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
        // 	depthTest: { enabled: true },
        // 	depthMask: true,
        // },
    })
})
let p = viewer.scene.primitives.add(primitive)

polygonHierarchy的坐标就是相当于视频的显示位置控制点。

如果 GroundPrimitive 的 sync是false, 那么需要 同步等待初始化完成 await GroundPrimitive.initializeTerrainHeights()

创建一个MaterialAppearance并把我们的材质传进去。

QQ截图20240327103230.png