| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- #include "Base.h"
- #include "VertexAttributeBinding.h"
- #include "Mesh.h"
- #include "Effect.h"
- namespace gameplay
- {
- static GLuint __maxVertexAttribs = 0;
- static std::vector<VertexAttributeBinding*> __vertexAttributeBindingCache;
- VertexAttributeBinding::VertexAttributeBinding() :
- _handle(0), _attributes(NULL), _mesh(NULL), _effect(NULL)
- {
- }
- VertexAttributeBinding::~VertexAttributeBinding()
- {
- // Delete from the vertex attribute binding cache.
- std::vector<VertexAttributeBinding*>::iterator itr = std::find(__vertexAttributeBindingCache.begin(), __vertexAttributeBindingCache.end(), this);
- if (itr != __vertexAttributeBindingCache.end())
- {
- __vertexAttributeBindingCache.erase(itr);
- }
- SAFE_RELEASE(_mesh);
- SAFE_RELEASE(_effect);
- SAFE_DELETE_ARRAY(_attributes);
- if (_handle)
- {
- GL_ASSERT( glDeleteVertexArrays(1, &_handle) );
- _handle = 0;
- }
- }
- VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, Effect* effect)
- {
- // Search for an existing vertex attribute binding that can be used.
- VertexAttributeBinding* b;
- for (unsigned int i = 0, count = __vertexAttributeBindingCache.size(); i < count; ++i)
- {
- b = __vertexAttributeBindingCache[i];
- if (b->_mesh == mesh && b->_effect == effect)
- {
- // Found a match!
- b->addRef();
- return b;
- }
- }
- b = create(mesh, mesh->getVertexFormat(), 0, effect);
- // Add the new vertex attribute binding to the cache.
- if (b)
- {
- __vertexAttributeBindingCache.push_back(b);
- }
- return b;
- }
- VertexAttributeBinding* VertexAttributeBinding::create(const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
- {
- return create(NULL, vertexFormat, vertexPointer, effect);
- }
- VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
- {
- // One-time initialization.
- if (__maxVertexAttribs == 0)
- {
- GLint temp;
- GL_ASSERT( glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &temp) );
- __maxVertexAttribs = temp;
- assert(__maxVertexAttribs > 0);
- if (__maxVertexAttribs <= 0)
- {
- return NULL;
- }
- }
- // Create a new VertexAttributeBinding.
- VertexAttributeBinding* b = new VertexAttributeBinding();
- #ifdef USE_GL_VAOS
- if (mesh && glGenVertexArrays)
- {
- GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
- GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) );
- // Use hardware VAOs.
- GL_ASSERT( glGenVertexArrays(1, &b->_handle) );
- if (b->_handle == 0)
- {
- SAFE_DELETE(b);
- return NULL;
- }
- // Bind the new VAO.
- GL_ASSERT( glBindVertexArray(b->_handle) );
- // Bind the Mesh VBO so our glVertexAttribPointer calls use it.
- GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()) );
- }
- else
- #endif
- {
- // Construct a software representation of a VAO.
- VertexAttribute* attribs = new VertexAttribute[__maxVertexAttribs];
- for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
- {
- // Set GL defaults
- attribs[i].enabled = GL_FALSE;
- attribs[i].size = 4;
- attribs[i].stride = 0;
- attribs[i].type = GL_FLOAT;
- attribs[i].normalized = GL_FALSE;
- attribs[i].pointer = 0;
- }
- b->_attributes = attribs;
- }
- if (mesh)
- {
- b->_mesh = mesh;
- mesh->addRef();
- }
-
- b->_effect = effect;
- effect->addRef();
- // Call setVertexAttribPointer for each vertex element.
- std::string name;
- unsigned int offset = 0;
- for (unsigned int i = 0, count = vertexFormat.getElementCount(); i < count; ++i)
- {
- const VertexFormat::Element& e = vertexFormat.getElement(i);
- gameplay::VertexAttribute attrib;
- // Constructor vertex attribute name expected in shader.
- switch (e.usage)
- {
- case VertexFormat::POSITION:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_POSITION_NAME);
- break;
- case VertexFormat::NORMAL:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_NORMAL_NAME);
- break;
- case VertexFormat::COLOR:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_COLOR_NAME);
- break;
- case VertexFormat::TANGENT:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TANGENT_NAME);
- break;
- case VertexFormat::BINORMAL:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BINORMAL_NAME);
- break;
- case VertexFormat::BLENDWEIGHTS:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDWEIGHTS_NAME);
- break;
- case VertexFormat::BLENDINDICES:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
- break;
- case VertexFormat::TEXCOORD0:
- attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX);
- // Try adding a "0" after the texcoord attrib name (flexible name for this case).
- if (attrib == -1)
- {
- name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
- name += "0";
- attrib = effect->getVertexAttribute(name.c_str());
- }
- break;
- case VertexFormat::TEXCOORD1:
- case VertexFormat::TEXCOORD2:
- case VertexFormat::TEXCOORD3:
- case VertexFormat::TEXCOORD4:
- case VertexFormat::TEXCOORD5:
- case VertexFormat::TEXCOORD6:
- case VertexFormat::TEXCOORD7:
- name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
- name += (e.usage - VertexFormat::TEXCOORD0);
- attrib = effect->getVertexAttribute(name.c_str());
- break;
- default:
- attrib = -1;
- break;
- }
- if (attrib == -1)
- {
- WARN_VARG("Warning: Vertex attribute not found for usage %d", (int)e.usage);
- }
- else
- {
- void* pointer = vertexPointer ? (void*)(((unsigned char*)vertexPointer) + offset) : (void*)offset;
- b->setVertexAttribPointer(attrib, (GLint)e.size, GL_FLOAT, GL_FALSE, (GLsizei)vertexFormat.getVertexSize(), pointer);
- }
- offset += e.size * sizeof(float);
- }
- if (b->_handle)
- {
- GL_ASSERT( glBindVertexArray(0) );
- }
- return b;
- }
- void VertexAttributeBinding::setVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalize, GLsizei stride, void* pointer)
- {
- assert(indx < (GLuint)__maxVertexAttribs);
- if (_handle)
- {
- // Hardware mode
- GL_ASSERT( glEnableVertexAttribArray(indx) );
- GL_ASSERT( glVertexAttribPointer(indx, size, type, normalize, stride, pointer) );
- }
- else
- {
- // Software mode
- _attributes[indx].enabled = true;
- _attributes[indx].size = size;
- _attributes[indx].type = type;
- _attributes[indx].normalized = normalize;
- _attributes[indx].stride = stride;
- _attributes[indx].pointer = pointer;
- }
- }
- void VertexAttributeBinding::bind()
- {
- if (_handle)
- {
- // Hardware mode
- GL_ASSERT( glBindVertexArray(_handle) );
- }
- else
- {
- // Software mode
- if (_mesh)
- {
- GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, _mesh->getVertexBuffer()) );
- }
- else
- {
- GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
- }
- for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
- {
- VertexAttribute& a = _attributes[i];
- if (a.enabled)
- {
- GL_ASSERT( glEnableVertexAttribArray(i) );
- GL_ASSERT( glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, a.pointer) );
- }
- }
- }
- }
- void VertexAttributeBinding::unbind()
- {
- if (_handle)
- {
- // Hardware mode
- GL_ASSERT( glBindVertexArray(0) );
- }
- else
- {
- // Software mode
- if (_mesh)
- {
- GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
- }
- for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
- {
- if (_attributes[i].enabled)
- {
- GL_ASSERT( glDisableVertexAttribArray(i) );
- }
- }
- }
- }
- }
|