cocos2d-x中的batchNode的方式可以提高相同的纹理的渲染效率,但是它使用的绘制方式还是glDrawElements的方式,它只是把相同的纹理的绘制命令只提交一次,剩下的重复绘制都调用glDrawElements即可,当绘制中的一些参数变化时,使用glMapBuffer获得数据的指针,然后修改数据,代码如下:
glBufferData(GL_ARRAY_BUFFER,sizeof(_quads[0]) * _capacity,nullptr,GL_DYNAMIC_DRAW); void *buf = glMapBuffer(GL_ARRAY_BUFFER,GL_WRITE_ONLY); memcpy(buf,_quads,sizeof(_quads[0])* _totalQuads); glUnmapBuffer(GL_ARRAY_BUFFER);把数据传进缓冲的这个方式是向内存请求一个指针,调用glMapBuffer函数openGL会返回当前绑定的内存地址,然后需要调用glUnmapBuffer函数可以告诉openGL已经用完指针了,这是一个解映射的操作。
另外一个被注释掉的方式就是调用glBufferSubData:
glBufferSubData(GL_ARRAY_BUFFER,sizeof(_quads[0])*start,sizeof(_quads[0]) * n,&_quads[start] );glBufferSubData填充特定区域的缓冲而不是填充整个缓冲,第二个参数就是要被填充的缓冲的其实偏移值。
openGL其实提供了一种更高效的方式,就是实例化的方式。实例化也称多实例渲染,是一种连续执行多条相同的渲染命令的方法,并且每个渲染命令所产生的结果都会有轻微的差异,这是一种非常有效的,使用少量API调用大量几何体的方法。openGL已经提供了一些常用的绘制函数的多变量形式来优化命令的多次执行。
实例化是一种只调用一次渲染函数却能绘制出很多物体的技术,它节省了渲染一个物体是cpu到gpu的通讯时间,对应glDrawArrays和glDrawElements,有两个实例化绘制函数glDrawArraysInstanced和glDrawElementsInstanced,这两个函数需要多传一个实例化数量的参数,它设置我们打算渲染实力的数量,这样我们只需要把所需要的数据发给gpu一次,然后告诉gpu该如何使用这个参数绘制这些实例。
对应的在着色器中,我们可以拿到一个内置变量-gl_Instance来知道当前绘制到第几个了
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES,6,100);
glBindVertexArray(0);cocos2d-x中的batchNode部分其实可以用实例化的方式重构一下,提高效率。
能力不足,水平有限,如有错误,欢迎指出。