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的可以试试。

你可能感兴趣的:(js,shader)