cesium比较区别 opengl_Cesium原理篇:6 Render模块(6: Instance实例化)

最近研究Cesium的实例化,尽管该技术需要在WebGL2.0,也就是OpenGL ES3.0才支持。调试源码的时候眼前一亮,发现VAO和glDrawBuffers都不是WebGL1.0的标准函数,都是扩展功能,看来WebGL2.0标准的推广势在必行啊。同时发现,通过ANGLE_instanced_arrays的扩展,也可以在WebGL1.0下实现实例化,创建实例化方法的代码如下:

varglDrawElementsInstanced;varglDrawArraysInstanced;varglVertexAttribDivisor;varinstancedArrays;//WebGL2.0标准直接提供了实例化接口

if(webgl2) {

glDrawElementsInstanced= function(mode, count, type, offset, instanceCount) {

gl.drawElementsInstanced(mode, count, type, offset, instanceCount);

};

glDrawArraysInstanced= function(mode, first, count, instanceCount) {

gl.drawArraysInstanced(mode, first, count, instanceCount);

};

glVertexAttribDivisor= function(index, divisor) {

gl.vertexAttribDivisor(index, divisor);

};

}else{//WebGL1.0下

//扩展ANGLE_instanced_arrays

instancedArrays = getExtension(gl, ['ANGLE_instanced_arrays']);if(defined(instancedArrays)) {

glDrawElementsInstanced= function(mode, count, type, offset, instanceCount) {

instancedArrays.drawElementsInstancedANGLE(mode, count, type, offset, instanceCount);

};

glDrawArraysInstanced= function(mode, first, count, instanceCount) {

instancedArrays.drawArraysInstancedANGLE(mode, first, count, instanceCount);

};

glVertexAttribDivisor= function(index, divisor) {

instancedArrays.vertexAttribDivisorANGLE(index, divisor);

};

}

}//涉及到实例化的三个方法

this.glDrawElementsInstanced =glDrawElementsInstanced;this.glDrawArraysInstanced =glDrawArraysInstanced;this.glVertexAttribDivisor =glVertexAttribDivisor;this._instancedArrays = !!instancedArrays;

通过这样的封装,Cesium.Context提供了标准的实例化方法,不需要用户过多的关心WebGL标准的差异。而实例化的渲染也非常简单,核心代码如下:

functioncontinueDraw(context, drawCommand) {//……

var instanceCount =drawCommand.instanceCount;if(defined(indexBuffer)) {

offset= offset *indexBuffer.bytesPerIndex;//offset in vertices to offset in bytes

count =defaultValue(count, indexBuffer.numberOfIndices);if (instanceCount === 0) {

context._gl.drawElements(primitiveType, count, indexBuffer.indexDatatype, offset);

}else{

context.glDrawElementsInstanced(primitiveType, count, indexBuffer.indexDatatype, offset, instanceCount);

}

}else{

count=defaultValue(count, va.numberOfVertices);if (instanceCount === 0) {

context._gl.drawArrays(primitiveType, offset, count);

}else{

context.glDrawArraysInstanced(primitiveType, offset, count, instanceCount);

}

}//……

是否实例化渲染,取决于你所构造的DrawCommand是否有实例化的信息,对应代码中的drawCommand.instanceCount,如果你的实例化数目不为零,则进行实例化的渲染。因此,Context中对实例化进行了封装,内部的渲染机制中,实例化和非实例化的渲染机制差别并不大。从应用的角度来看,我们并不需要关心Context的实现,而是通过构造DrawCommand来决定是否想要实例化渲染。

之前我们较详细的介绍过Renderer.DrawCommand模块,如果不清楚的回去再翻翻看,在VertexArray中实现了VAO中创建attr.vertexAttrib,这里有一个instanceDivisor属性,这就是用来表示该attribute是否是实例化的divisor:

attr.vertexAttrib = function(gl) {var index = this.index;

gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexBuffer._getBuffer());

gl.vertexAttribPointer(index,this.componentsPerAttribute, this.componentDatatype, this.normalize,this.strideInBytes, this.offsetInBytes);

gl.enableVertexAttribArray(index);if (this.instanceDivisor > 0) {

context.glVertexAttribDivisor(index,this.instanceD

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值