本文參考了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