了解WEBGL就可以自己实现一些特效,添加到cesium中。
首先我们从简单的案列开始,比如利用纯WEBGL实现绘制三角形,那么实现的代码如下:
点着色器:
attribute vec4 position; void main() { gl_Position = position; }
片元着色器:
void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }
把上述点着色器和片元着色器放置cesium中,如定义一个扩展类,实现自己的着色器,如下:
1 function getVS() { 2 return 'attribute vec4 position;\ 3 void main() {\ 4 gl_Position = position;\ 5 }'; 6 } 7 8 function getFS() { 9 return "void main()\ 10 {\ 11 gl_FragColor = vec4(1,1,1,1);\ 12 }\ 13 "; 14 } 15 16 function Trangle(viewer) { 17 this._viewer = viewer; 18 } 19 20 Trangle.prototype.getPointCommand = function (context) { 21 var shaderProgram = Cesium.ShaderProgram.fromCache({ 22 context: context, 23 vertexShaderSource: getVS(), 24 fragmentShaderSource: getFS() 25 }); 26 var renderState = Cesium.RenderState.fromCache({ 27 depthTest: { 28 enabled: false 29 }, 30 depthMask: false, 31 blending: Cesium.BlendingState.ALPHA_BLEND 32 }); 33 34 var indexBuffer = Cesium.Buffer.createIndexBuffer({ 35 context: context, 36 typedArray: new Uint32Array([0, 1, 2]), 37 usage: Cesium.BufferUsage.STATIC_DRAW, 38 indexDatatype: Cesium.IndexDatatype.UNSIGNED_INT 39 }); 40 var vertexBuffer = Cesium.Buffer.createVertexBuffer({ 41 context: context, 42 typedArray: Cesium.ComponentDatatype.createTypedArray(Cesium.ComponentDatatype.FLOAT, [0, 0, 0, 0, 100000, 100000, 100000, 100000, 0]), 43 usage: Cesium.BufferUsage.STATIC_DRAW 44 }); 45 var attributes = []; 46 attributes.push({ 47 index: 0, 48 vertexBuffer: vertexBuffer, 49 componentDatatype: Cesium.ComponentDatatype.FLOAT, 50 componentsPerAttribute: 3, 51 normalize: false 52 }); 53 var vertexArray = new Cesium.VertexArray({ 54 context: context, 55 attributes: attributes, 56 indexBuffer: indexBuffer 57 }); 58 59 this.pointCommand = new Cesium.DrawCommand({ 60 boundingVolume: new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(113, 30, 50000), 200000), 61 primitiveType: Cesium.PrimitiveType.TRIANGLES, 62 shaderProgram: shaderProgram, 63 renderState: renderState, 64 vertexArray: vertexArray, 65 pass: Cesium.Pass.OPAQUE, 66 modelMatrix: GWViewer.GWMath.getMatrix(Cesium.Cartesian3.fromDegrees(113, 30, 50000), 0, 0, 0) 67 }); 68 }; 69 70 Trangle.prototype.update = function (frameState) { 71 if (this.pointCommand) { 72 var commandList = frameState.commandList; 73 commandList.push(this.pointCommand); 74 this._viewer.scene.requestRender(); 75 } else { 76 this.getPointCommand(this._viewer.scene._context); 77 } 78 79 };
上面定义了一个三角形类,内部给定了三角形的三个顶点,通过
viewer.scene.primitives.add(new Trangle(viewer));即可把自定义的着色器对象添加到球上,然后运行调试后发现没有报错也没有绘制出三角形。
调试分析查找原因,着色器代码确实运行绘制了,没有显示出来,原因是坐标位置不对,应该调用cesium自带的着色器方法,转换坐标。更改后的代码如下:
点着色器:
attribute vec3 position3DHigh; attribute vec3 position3DLow; void main() { vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow); p = czm_modelViewProjectionRelativeToEye * p; gl_Position = p; }
片元着色器:
void main() { gl_FragColor = vec4(1,1,1,1); }
换掉着色器代码,我们就可以看到球上绘制的三角形了,展示结果如此下图所示: