VertexAttributeBinding.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. // Search for an existing vertex attribute binding that can be used.
  33. VertexAttributeBinding* b;
  34. for (unsigned int i = 0, count = __vertexAttributeBindingCache.size(); i < count; ++i)
  35. {
  36. b = __vertexAttributeBindingCache[i];
  37. if (b->_mesh == mesh && b->_effect == effect)
  38. {
  39. // Found a match!
  40. b->addRef();
  41. return b;
  42. }
  43. }
  44. b = create(mesh, mesh->getVertexFormat(), 0, effect);
  45. // Add the new vertex attribute binding to the cache.
  46. if (b)
  47. {
  48. __vertexAttributeBindingCache.push_back(b);
  49. }
  50. return b;
  51. }
  52. VertexAttributeBinding* VertexAttributeBinding::create(const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
  53. {
  54. return create(NULL, vertexFormat, vertexPointer, effect);
  55. }
  56. VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexFormat& vertexFormat, void* vertexPointer, Effect* effect)
  57. {
  58. // One-time initialization.
  59. if (__maxVertexAttribs == 0)
  60. {
  61. GLint temp;
  62. GL_ASSERT( glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &temp) );
  63. __maxVertexAttribs = temp;
  64. assert(__maxVertexAttribs > 0);
  65. if (__maxVertexAttribs <= 0)
  66. {
  67. return NULL;
  68. }
  69. }
  70. // Create a new VertexAttributeBinding.
  71. VertexAttributeBinding* b = new VertexAttributeBinding();
  72. #ifdef USE_GL_VAOS
  73. if (mesh && glGenVertexArrays)
  74. {
  75. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
  76. GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) );
  77. // Use hardware VAOs.
  78. GL_ASSERT( glGenVertexArrays(1, &b->_handle) );
  79. if (b->_handle == 0)
  80. {
  81. SAFE_DELETE(b);
  82. return NULL;
  83. }
  84. // Bind the new VAO.
  85. GL_ASSERT( glBindVertexArray(b->_handle) );
  86. // Bind the Mesh VBO so our glVertexAttribPointer calls use it.
  87. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()) );
  88. }
  89. else
  90. #endif
  91. {
  92. // Construct a software representation of a VAO.
  93. VertexAttribute* attribs = new VertexAttribute[__maxVertexAttribs];
  94. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  95. {
  96. // Set GL defaults
  97. attribs[i].enabled = GL_FALSE;
  98. attribs[i].size = 4;
  99. attribs[i].stride = 0;
  100. attribs[i].type = GL_FLOAT;
  101. attribs[i].normalized = GL_FALSE;
  102. attribs[i].pointer = 0;
  103. }
  104. b->_attributes = attribs;
  105. }
  106. if (mesh)
  107. {
  108. b->_mesh = mesh;
  109. mesh->addRef();
  110. }
  111. b->_effect = effect;
  112. effect->addRef();
  113. // Call setVertexAttribPointer for each vertex element.
  114. std::string name;
  115. unsigned int offset = 0;
  116. for (unsigned int i = 0, count = vertexFormat.getElementCount(); i < count; ++i)
  117. {
  118. const VertexFormat::Element& e = vertexFormat.getElement(i);
  119. gameplay::VertexAttribute attrib;
  120. // Constructor vertex attribute name expected in shader.
  121. switch (e.usage)
  122. {
  123. case VertexFormat::POSITION:
  124. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_POSITION_NAME);
  125. break;
  126. case VertexFormat::NORMAL:
  127. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_NORMAL_NAME);
  128. break;
  129. case VertexFormat::COLOR:
  130. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_COLOR_NAME);
  131. break;
  132. case VertexFormat::TANGENT:
  133. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TANGENT_NAME);
  134. break;
  135. case VertexFormat::BINORMAL:
  136. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BINORMAL_NAME);
  137. break;
  138. case VertexFormat::BLENDWEIGHTS:
  139. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDWEIGHTS_NAME);
  140. break;
  141. case VertexFormat::BLENDINDICES:
  142. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
  143. break;
  144. case VertexFormat::TEXCOORD0:
  145. attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX);
  146. // Try adding a "0" after the texcoord attrib name (flexible name for this case).
  147. if (attrib == -1)
  148. {
  149. name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
  150. name += "0";
  151. attrib = effect->getVertexAttribute(name.c_str());
  152. }
  153. break;
  154. case VertexFormat::TEXCOORD1:
  155. case VertexFormat::TEXCOORD2:
  156. case VertexFormat::TEXCOORD3:
  157. case VertexFormat::TEXCOORD4:
  158. case VertexFormat::TEXCOORD5:
  159. case VertexFormat::TEXCOORD6:
  160. case VertexFormat::TEXCOORD7:
  161. name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
  162. name += (e.usage - VertexFormat::TEXCOORD0);
  163. attrib = effect->getVertexAttribute(name.c_str());
  164. break;
  165. default:
  166. attrib = -1;
  167. break;
  168. }
  169. if (attrib == -1)
  170. {
  171. WARN_VARG("Warning: Vertex attribute not found for usage %d", (int)e.usage);
  172. }
  173. else
  174. {
  175. void* pointer = vertexPointer ? (void*)(((unsigned char*)vertexPointer) + offset) : (void*)offset;
  176. b->setVertexAttribPointer(attrib, (GLint)e.size, GL_FLOAT, GL_FALSE, (GLsizei)vertexFormat.getVertexSize(), pointer);
  177. }
  178. offset += e.size * sizeof(float);
  179. }
  180. if (b->_handle)
  181. {
  182. GL_ASSERT( glBindVertexArray(0) );
  183. }
  184. return b;
  185. }
  186. void VertexAttributeBinding::setVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalize, GLsizei stride, void* pointer)
  187. {
  188. assert(indx < (GLuint)__maxVertexAttribs);
  189. if (_handle)
  190. {
  191. // Hardware mode
  192. GL_ASSERT( glEnableVertexAttribArray(indx) );
  193. GL_ASSERT( glVertexAttribPointer(indx, size, type, normalize, stride, pointer) );
  194. }
  195. else
  196. {
  197. // Software mode
  198. _attributes[indx].enabled = true;
  199. _attributes[indx].size = size;
  200. _attributes[indx].type = type;
  201. _attributes[indx].normalized = normalize;
  202. _attributes[indx].stride = stride;
  203. _attributes[indx].pointer = pointer;
  204. }
  205. }
  206. void VertexAttributeBinding::bind()
  207. {
  208. if (_handle)
  209. {
  210. // Hardware mode
  211. GL_ASSERT( glBindVertexArray(_handle) );
  212. }
  213. else
  214. {
  215. // Software mode
  216. if (_mesh)
  217. {
  218. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, _mesh->getVertexBuffer()) );
  219. }
  220. else
  221. {
  222. GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
  223. }
  224. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  225. {
  226. VertexAttribute& a = _attributes[i];
  227. if (a.enabled)
  228. {
  229. GL_ASSERT( glEnableVertexAttribArray(i) );
  230. GL_ASSERT( glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, a.pointer) );
  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. for (unsigned int i = 0; i < __maxVertexAttribs; ++i)
  250. {
  251. if (_attributes[i].enabled)
  252. {
  253. GL_ASSERT( glDisableVertexAttribArray(i) );
  254. }
  255. }
  256. }
  257. }
  258. }