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
饮水思源,不忘初心。
要面包,也要有诗和远方。