VertexAttributeBinding.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include "Base.h"
  2. #include "VertexAttributeBinding.h"
  3. #include "Mesh.h"
  4. #include "Effect.h"
  5. namespace gameplay
  6. {
  7. static GLuint __maxVertexAttribs = 0;
  8. static std::vector<VertexAttributeBinding*> __vertexAttributeBindingCache;
  9. VertexAttributeBinding::VertexAttributeBinding() :
  10. _handle(0), _attributes(NULL), _mesh(NULL), _effect(NULL)
  11. {
  12. }
  13. VertexAttributeBinding::~VertexAttributeBinding()
  14. {
  15. // Delete from the vertex attribute binding cache.
  16. std::vector<VertexAttributeBinding*>::iterator itr = std::find(__vertexAttributeBindingCache.begin(), __vertexAttributeBindingCache.end(), this);
  17. if (itr != __vertexAttributeBindingCache.end())
  18. {
  19. __vertexAttributeBindingCache.erase(itr);
  20. }
  21. SAFE_RELEASE(_mesh);
  22. SAFE_RELEASE(_effect);
  23. SAFE_DELETE_ARRAY(_attributes);
  24. if (_handle)
  25. {
  26. GL_ASSERT( glDeleteVertexArrays(1, &_handle) );
  27. _handle = 0;
  28. }
  29. }
  30. VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, Effect* effect)
  31. {
  32. GP_ASSERT(mesh);
  33. // Search for an existing vertex attribute binding that can be used.
  34. VertexAttributeBinding* b;
  35. for (size_t i = 0, count = __vertexAttributeBindingCache.size(); i < count; ++i)
  36. {
  37. b = __vertexAttributeBindingCache[i];
  38. GP_ASSERT(b);
  39. if (b->_mesh == mesh && b->_effect == effect)
  40. {
  41. // Found a match!
  42. b->addRef();
  43. return b;
  44. }
  45. }
  46. b = create(mesh, mesh->getVertexFormat(), 0, effect);
  47. // Add the new vertex attribute binding to the cache.
  48. if (b)
  49. {
  50. __vertexAttributeBindingCache.push_back(b);
  51. }
  52. return b;
  53. }
  54. VertexAttributeBinding* VertexAttributeBinding::create(const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
  55. {
  56. return create(NULL, vertexFormat, vertexPointer, effect);
  57. }
  58. VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
  59. {
  60. GP_ASSERT(effect);
  61. // One-time initialization.
  62. if (__maxVertexAttribs == 0)
  63. {
  64. GLint temp;
  65. GL_ASSERT( glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &temp) );
  66. __maxVertexAttribs = temp;
  67. if (__maxVertexAttribs <= 0)
  68. {
  69. GP_ERROR("The maximum number of vertex attributes supported by OpenGL on the current device is 0 or less.");
  70. return NULL;
  71. }
  72. }
  73. // Create a new VertexAttributeBinding.
  74. VertexAttributeBinding* b = new VertexAttributeBinding();
  75. #ifdef USE_VAO
  76. if (mesh && glGenVertexArrays)
  77. {
  78. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
  79. GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
  80. // Use hardware VAOs.
  81. GL_ASSERT( glGenVertexArrays(1, &b->_handle) );
  82. if (b->_handle == 0)
  83. {
  84. GP_ERROR("Failed to create VAO handle.");
  85. SAFE_DELETE(b);
  86. return NULL;
  87. }
  88. // Bind the new VAO.
  89. GL_ASSERT( glBindVertexArray(b->_handle) );
  90. // Bind the Mesh VBO so our glVertexAttribPointer calls use it.
  91. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()) );
  92. }
  93. else
  94. #endif
  95. {
  96. // Construct a software representation of a VAO.
  97. VertexAttribute* attribs = new VertexAttribute[__maxVertexAttribs];
  98. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  99. {
  100. // Set GL defaults
  101. attribs[i].enabled = GL_FALSE;
  102. attribs[i].size = 4;
  103. attribs[i].stride = 0;
  104. attribs[i].type = GL_FLOAT;
  105. attribs[i].normalized = GL_FALSE;
  106. attribs[i].pointer = 0;
  107. }
  108. b->_attributes = attribs;
  109. }
  110. if (mesh)
  111. {
  112. b->_mesh = mesh;
  113. mesh->addRef();
  114. }
  115. b->_effect = effect;
  116. effect->addRef();
  117. // Call setVertexAttribPointer for each vertex element.
  118. std::string name;
  119. size_t offset = 0;
  120. for (size_t i = 0, count = vertexFormat.getElementCount(); i < count; ++i)
  121. {
  122. const VertexFormat::Element& e = vertexFormat.getElement(i);
  123. gameplay::VertexAttribute attrib;
  124. // Constructor vertex attribute name expected in shader.
  125. switch (e.usage)
  126. {
  127. case VertexFormat::POSITION:
  128. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_POSITION_NAME);
  129. break;
  130. case VertexFormat::NORMAL:
  131. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_NORMAL_NAME);
  132. break;
  133. case VertexFormat::COLOR:
  134. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_COLOR_NAME);
  135. break;
  136. case VertexFormat::TANGENT:
  137. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TANGENT_NAME);
  138. break;
  139. case VertexFormat::BINORMAL:
  140. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BINORMAL_NAME);
  141. break;
  142. case VertexFormat::BLENDWEIGHTS:
  143. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDWEIGHTS_NAME);
  144. break;
  145. case VertexFormat::BLENDINDICES:
  146. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
  147. break;
  148. case VertexFormat::TEXCOORD0:
  149. if ((attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME)) != -1)
  150. break;
  151. case VertexFormat::TEXCOORD1:
  152. case VertexFormat::TEXCOORD2:
  153. case VertexFormat::TEXCOORD3:
  154. case VertexFormat::TEXCOORD4:
  155. case VertexFormat::TEXCOORD5:
  156. case VertexFormat::TEXCOORD6:
  157. case VertexFormat::TEXCOORD7:
  158. name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
  159. name += '0' + (e.usage - VertexFormat::TEXCOORD0);
  160. attrib = effect->getVertexAttribute(name.c_str());
  161. break;
  162. default:
  163. // This happens whenever vertex data contains extra information (not an error).
  164. attrib = -1;
  165. break;
  166. }
  167. if (attrib == -1)
  168. {
  169. //GP_WARN("Warning: Vertex element with usage '%s' in mesh '%s' does not correspond to an attribute in effect '%s'.", VertexFormat::toString(e.usage), mesh->getUrl(), effect->getId());
  170. }
  171. else
  172. {
  173. void* pointer = vertexPointer ? (void*)(((unsigned char*)vertexPointer) + offset) : (void*)offset;
  174. b->setVertexAttribPointer(attrib, (GLint)e.size, GL_FLOAT, GL_FALSE, (GLsizei)vertexFormat.getVertexSize(), pointer);
  175. }
  176. offset += e.size * sizeof(float);
  177. }
  178. if (b->_handle)
  179. {
  180. GL_ASSERT( glBindVertexArray(0) );
  181. }
  182. return b;
  183. }
  184. void VertexAttributeBinding::setVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalize, GLsizei stride, void* pointer)
  185. {
  186. GP_ASSERT(indx < (GLuint)__maxVertexAttribs);
  187. if (_handle)
  188. {
  189. // Hardware mode.
  190. GL_ASSERT( glVertexAttribPointer(indx, size, type, normalize, stride, pointer) );
  191. GL_ASSERT( glEnableVertexAttribArray(indx) );
  192. }
  193. else
  194. {
  195. // Software mode.
  196. GP_ASSERT(_attributes);
  197. _attributes[indx].enabled = true;
  198. _attributes[indx].size = size;
  199. _attributes[indx].type = type;
  200. _attributes[indx].normalized = normalize;
  201. _attributes[indx].stride = stride;
  202. _attributes[indx].pointer = pointer;
  203. }
  204. }
  205. void VertexAttributeBinding::bind()
  206. {
  207. if (_handle)
  208. {
  209. // Hardware mode
  210. GL_ASSERT( glBindVertexArray(_handle) );
  211. }
  212. else
  213. {
  214. // Software mode
  215. if (_mesh)
  216. {
  217. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, _mesh->getVertexBuffer()) );
  218. }
  219. else
  220. {
  221. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
  222. }
  223. GP_ASSERT(_attributes);
  224. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  225. {
  226. VertexAttribute& a = _attributes[i];
  227. if (a.enabled)
  228. {
  229. GL_ASSERT( glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, a.pointer) );
  230. GL_ASSERT( glEnableVertexAttribArray(i) );
  231. }
  232. }
  233. }
  234. }
  235. void VertexAttributeBinding::unbind()
  236. {
  237. if (_handle)
  238. {
  239. // Hardware mode
  240. GL_ASSERT( glBindVertexArray(0) );
  241. }
  242. else
  243. {
  244. // Software mode
  245. if (_mesh)
  246. {
  247. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
  248. }
  249. GP_ASSERT(_attributes);
  250. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  251. {
  252. if (_attributes[i].enabled)
  253. {
  254. GL_ASSERT( glDisableVertexAttribArray(i) );
  255. }
  256. }
  257. }
  258. }
  259. }