.COcos2d-X 节点(CCGLBufferedNode)API 从 GL的缓冲区加载数据
class CC_DLL CCGrid3D : public CCGridBase
#ifdef EMSCRIPTEN
, public CCGLBufferedNode
#endif // EMSCRIPTEN
class CC_DLL CCLayerColor : public CCLayerRGBA, public CCBlendProtocol
#ifdef EMSCRIPTEN
, public CCGLBufferedNode
#endif // EMSCRIPTEN
class CC_DLL CCProgressTimer : public CCNodeRGBA
#ifdef EMSCRIPTEN
, public CCGLBufferedNode
#endif // EMSCRIPTEN
class CC_DLL CCSprite : public CCNodeRGBA, public CCTextureProtocol
#ifdef EMSCRIPTEN
, public CCGLBufferedNode
#endif // EMSCRIPTEN
class CC_DLL CCTexture2D : public CCObject
#ifdef EMSCRIPTEN
, public CCGLBufferedNode
#endif // EMSCRIPTEN
#ifndef __CC_GL_BUFFERED_NODE__
#define __CC_GL_BUFFERED_NODE__
#include <CCGL.h>
class CCGLBufferedNode
{
public:
CCGLBufferedNode(void);
CCGLBufferedNode::CCGLBufferedNode(void)
{
for(int i = 0; i < BUFFER_SLOTS; i++)
{
m_bufferObject[i] = 0;
m_bufferSize[i] = 0;
m_indexBufferObject[i] = 0;
m_indexBufferSize[i] = 0;
}
}
/**
* Load the given data into this CCNode's GL Buffer. Needed for WebGL, as it does not support client-side arrays.
*/
void setGLBufferData(void *buf, GLuint bufSize, int slot);
void CCGLBufferedNode::setGLBufferData(void *buf, GLuint bufSize, int slot)
{
// WebGL doesn't support client-side arrays, so generate a buffer and load the data first.
if(m_bufferSize[slot] < bufSize)
{
if(m_bufferObject[slot])
{
glDeleteBuffers(1, &(m_bufferObject[slot]));
}
glGenBuffers(1, &(m_bufferObject[slot]));
m_bufferSize[slot] = bufSize;
glBindBuffer(GL_ARRAY_BUFFER, m_bufferObject[slot]);
glBufferData(GL_ARRAY_BUFFER, bufSize, buf, GL_DYNAMIC_DRAW);
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, m_bufferObject[slot]);
glBufferSubData(GL_ARRAY_BUFFER, 0, bufSize, buf);
}
}
void setGLIndexData(void *buf, GLuint bufSize, int slot);
void CCGLBufferedNode::setGLIndexData(void *buf, GLuint bufSize, int slot)
{
// WebGL doesn't support client-side arrays, so generate a buffer and load the data first.
if(m_indexBufferSize[slot] < bufSize)
{
if(m_indexBufferObject[slot])
{
glDeleteBuffers(1, &(m_indexBufferObject[slot]));
}
glGenBuffers(1, &(m_indexBufferObject[slot]));
m_indexBufferSize[slot] = bufSize;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferObject[slot]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufSize, buf, GL_DYNAMIC_DRAW);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferObject[slot]);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, bufSize, buf);
}
}
// We allocate 4 buffer objs per node, and index into them as slots.
//每个节点分配4个缓存
#define BUFFER_SLOTS 4
GLuint m_bufferObject[BUFFER_SLOTS]; //typedef unsigned int GLuint
GLuint m_bufferSize[BUFFER_SLOTS];
GLuint m_indexBufferObject[BUFFER_SLOTS];
GLuint m_indexBufferSize[BUFFER_SLOTS];
};
#endif // __CC_GL_BUFFERED_NODE__
关于gl
一:为什么要有opengl缓冲区对象
前面的顶点数组使得几何图元的显示方便了很多,但是如果每次都要向OPENGL发送一大块数据,而这数据其实并没有修改过,那么这传输就是冗余的。所以这里添加了缓冲区对象,将顶点数组存储在服务器端的缓冲区对象中。
二:如何创建和使用缓冲区对象
glGenBuffers():OpenGL分配n个当前未使用的名称(非 0),表示缓冲区对象。
原型 : void glGenBuffers(GLsizei n,GLuint *buffers);
GLboolean glIsBuffer(GLuint buffer):判断一个标识符是否是当前使用的缓冲区对象的标识符。
2.激活缓冲区对象
激活缓冲区对象,首先需要对他进行绑定。绑定缓冲区对象表示选择未来的操作将影响到哪个缓冲区 对象。
glBindBuffer(GLenum target ,GLuint buffer): 指定了当前的活动缓冲区对象 。
3.用数据分配和初始化缓冲区对象
一旦绑定了一个缓冲区对象,就需要保留空间以存储数据。
void glBufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage );
功能是分配size个存储单位的OpenGL服务器内存,用于存储顶点数据或索引。以前有与当前缓冲区对象相关联的数据将删除。
glBufferData()首先在OpenGL拂去其中分配内存以存储数据。如果成功分配,data!=NULL,size个单位就会从客户机内存复制到这个对象中。如果data=NULL,为数据保留适当的空间,但不会初始化。
方法一:假设已经在用用程序的一个缓冲区中准备了相同类型的数据,glBufferSubData()将用我们提供的数据替换被绑定的缓冲区对象的一些数据子集。
void glBufferSubData(GLenum target,GLuint offset,GLsizei size,const GLvoid *data); 用data 指向的数据更新 与target 相关联的当前绑定缓冲区对象中从offset开始的size个字节数据。
方法二:允许灵活的选择需要更新的数据。
GLvoid *glMapBuffer(GLenum target,GLuenum access):返回一个指向缓冲区对象的指针,可以在这个缓冲区对象中写入新值及更新之后,再调用GLboolean glUnMapBuffer(GLenum target)表示已经完成了对数据的更新,取消对这个缓冲区的映射。如果只需要更新所需范围内的数据值,也可调用GLvoid *glMapBuffwerRange(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access)
5.在缓冲区对象之间复制数据
void glCopyBufferSubData(readbuffer,writebuffer,resdoffset,writeoffset,size);
把数据从与readbuffer相关联的缓冲区对象复制到绑定到writebuffer的缓冲区对象。
6. 清除缓冲区对象
glDeleteBuffer(GLsizei n,const GLuint *buffers):删除n个缓冲区对象。被删除的当前缓冲区对象的所有绑定都重置为零。如果一个缓冲区对象是在绑定时删除的,这个对象的所有绑定都重置为默认的缓冲区对象。
7.使用缓冲区对象来存储顶点数组数据
需要以下步骤:
(1)生成缓冲区对象标识符;
(2)绑定缓冲区对象,确定是存储顶点数据还是索引;
(3)请求数据的存储空间,并对数据元素进行初始化;
(4)指定相对于缓冲区起始位置的偏移量;
(5)绑定适当的缓冲区对象,用于渲染;
(6)使用适当的顶点数组渲染函数进行渲染,比如glDrawArrays()
如果想初始化多个缓冲区对象,就需要为每个缓冲区对象重复以上。顶点数组数据的所有格式都适用于缓冲区对象。