Cesium使用视频创建自定义纹理【转】

本文参考了cesium的自定义texture实现,在此基础上做了修改,引入html5的视频进行渲染,实测比使用视频作为材质效率略有优化,且更具灵活性,利于对视频进行二次处理,废话不多说,代码如下:

var PrimitiveTexture= (
    function () {
        var vertexShader;
        var fragmentShader;
        var materialShader;
        var video;
        function _(options) {
 
            vertexShader = getVS();
            fragmentShader = getFS();
            materialShader = getMS();
            video = options.video;
 
            var postionsTemp = [];
            //纹理坐标,调整纹理坐标顺序即可完成贴图的旋转
            var stsTemp = [0,0,0,1,1,1,1,0];
            //索引数组
            var indicesTesm = [0,1,2,0,2,3];
 
            for (var i = 0; i < options.Cartesians.length; i++) {
                postionsTemp.push(options.Cartesians[i].x);
                postionsTemp.push(options.Cartesians[i].y);
                postionsTemp.push(options.Cartesians[i].z);
            }
            console.log("pos:"+postionsTemp)
            this.positionArr = new Float32Array(postionsTemp);
            this.sts = new Uint8Array(stsTemp);
            this.indiceArr = new Uint16Array(indicesTesm);
            //通过坐标数组,索引数组,纹理坐标数组创建多边形
            this.geometry = CreateGeometry(this.positionArr, this.sts, this.indiceArr);
            this.appearance = CreateAppearence(fragmentShader, vertexShader,materialShader,video);
            this.primitive = viewer.scene.primitives.add(new Cesium.Primitive({
                geometryInstances: new Cesium.GeometryInstance({
                    geometry: this.geometry,
                }),
                appearance: this.appearance,
                asynchronous: false
            }));
        }
        
        function CreateGeometry(positions, sts, indices) {
            let sess= new Cesium.GeometryAttribute({
            componentDatatype: Cesium.ComponentDatatype.FLOAT,
            componentsPerAttribute: 2,
            values: sts
        })
        return new Cesium.Geometry({
            attributes: {
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: positions
                }),
                st:sess
            },
            indices: indices,
            primitiveType: Cesium.PrimitiveType.TRIANGLES,
            boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
        });
    }
    
    
    function CreateAppearence(fs, vs,ms,video) {
        function NewMaterial(){
            var material = new Cesium.Material({
                fabric: {
                    type : 'myImage',
                    uniforms:{
                        image : ""
                    },
                    source: ms
                }
            });
            material.uniforms.image = video;
            return material;
        }
    
        return new Cesium.Appearance({
            material: NewMaterial(),
            aboveGround: true,
            faceForward: true,
            flat: true,
            translucent: false,
            renderState: {
                blending: Cesium.BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
                depthTest: { enabled: true },
                depthMask: true,
            },
            fragmentShaderSource: fs,
            vertexShaderSource: vs
        });
    }
    
    function getVS() {
        return "attribute vec3 position3DHigh;\
            attribute vec3 position3DLow;\
            attribute vec2 st;\
            attribute float batchId;\
            varying vec2 v_st;\
            void main()\
            {\
                vec4 p = czm_computePosition();\
                v_st=st;\
                p = czm_modelViewProjectionRelativeToEye * p;\
                gl_Position = p;\
            }\
            ";
    }
    function getFS() {
        return "varying vec2 v_st;\
            void main()\
            {\
                czm_materialInput materialInput;\
                czm_material material=czm_getMaterial(materialInput,v_st);\
                vec4 color=vec4(material.diffuse + material.emission,material.alpha);\
                if(color.x == 1.0&&color.y == 1.0&&color.z == 1.0&&color.w == 1.0) color=vec4(vec3(0.0,0.0,0.0),0.0);\
                gl_FragColor =color;\
            }\
            ";
    }
    function getMS() {
      return "czm_material czm_getMaterial(czm_materialInput materialInput,vec2 v_st)\
            {\
                vec4 color = texture2D(image, v_st);\
                czm_material material = czm_getDefaultMaterial(materialInput);\
                material.diffuse = color.rgb;\
                material.alpha = 0;\
                return material;\
            }\
            ";
    }
    return _;
  })()

对比自定义texture中的代码,最主要的一步在这里:

var material = new Cesium.Material({
    fabric: {
            type : 'myImage',
            uniforms:{
                image : ""
            },
            source: ms
    }
});
material.uniforms.image = video;
return material;

uinform中的image不能直接使用video,必须创建完后赋值过去,似乎老版本的Cesium是可以直接在uniforms中直接将video定义给image,没有验证,有老版本cesium的可以试试。


原文链接:https://blog.csdn.net/garefield/article/details/105549916

posted on 2022-03-11 17:26  3D入魔  阅读(1237)  评论(0编辑  收藏  举报