framework2
1115 строк · 32.0 Кб
1//TODO:
2//GL Error checking
3// handle idling of arrays: possibly let gl create memory and use map buffers for streaming
4// index updating/deleting?
5// setVertexData with float* should know about ofVec3f vs ofVec2f?
6
7
8#include "ofUtils.h"9#include "ofVbo.h"10#include "ofShader.h"11#include "ofGLUtils.h"12#include "ofMesh.h"13#include "ofGLBaseTypes.h"14
15#ifdef TARGET_ANDROID16#include "ofAppAndroidWindow.h"17#endif18
19using std::unordered_map;20
21bool ofVbo::vaoSupported=true;22bool ofVbo::vaoChecked=false;23
24#ifdef TARGET_OPENGLES25#include <dlfcn.h>26typedef void (* glGenVertexArraysType) (GLsizei n, GLuint *arrays);27glGenVertexArraysType glGenVertexArraysFunc = nullptr;28#define glGenVertexArrays glGenVertexArraysFunc29
30typedef void (* glDeleteVertexArraysType) (GLsizei n, GLuint *arrays);31glDeleteVertexArraysType glDeleteVertexArraysFunc = nullptr;32#define glDeleteVertexArrays glDeleteVertexArraysFunc33
34typedef void (* glBindVertexArrayType) (GLuint array);35glBindVertexArrayType glBindVertexArrayFunc = nullptr;36#define glBindVertexArray glBindVertexArrayFunc37#endif38
39static unordered_map<GLuint,int> & getVAOIds(){40static unordered_map<GLuint,int> * ids = new unordered_map<GLuint,int>;41return *ids;42}
43
44//--------------------------------------------------------------
45static void retainVAO(GLuint id){46if(id==0) return;47if(getVAOIds().find(id)!=getVAOIds().end()){48getVAOIds()[id]++;49}else{50getVAOIds()[id]=1;51}52}
53
54//--------------------------------------------------------------
55static void releaseVAO(GLuint id){56if(getVAOIds().find(id)!=getVAOIds().end()){57getVAOIds()[id]--;58if(getVAOIds()[id]==0){59#ifdef TARGET_ANDROID60if (!ofAppAndroidWindow::isSurfaceDestroyed())61#endif62glDeleteVertexArrays(1, &id);63getVAOIds().erase(id);64}65}else{66ofLogWarning("ofVbo") << "releaseVAO(): something's wrong here, releasing unknown vertex array object id " << id;67
68#ifdef TARGET_ANDROID69if (!ofAppAndroidWindow::isSurfaceDestroyed())70#endif71glDeleteVertexArrays(1, &id);72}73}
74
75//--------------------------------------------------------------
76ofVbo::VertexAttribute::VertexAttribute()77:stride(0)78,offset(0)79,numCoords(0)80,location(0)81,normalize(false)82,divisor(0){83
84}
85
86//--------------------------------------------------------------
87bool ofVbo::VertexAttribute::isAllocated() const{88return buffer.isAllocated();89}
90
91
92//--------------------------------------------------------------
93void ofVbo::VertexAttribute::allocate(){94buffer.allocate();95}
96
97//--------------------------------------------------------------
98void ofVbo::VertexAttribute::bind() const{99buffer.bind(GL_ARRAY_BUFFER);100}
101
102//--------------------------------------------------------------
103void ofVbo::VertexAttribute::setData(GLsizeiptr bytes, const void * data, GLenum usage){104buffer.setData(bytes,data,usage);105}
106
107//--------------------------------------------------------------
108void ofVbo::VertexAttribute::unbind() const{109buffer.unbind(GL_ARRAY_BUFFER);110}
111
112//--------------------------------------------------------------
113GLuint ofVbo::VertexAttribute::getId() const{114return buffer.getId();115}
116
117//--------------------------------------------------------------
118void ofVbo::VertexAttribute::updateData(GLintptr offset, GLsizeiptr bytes, const void * data){119buffer.updateData(offset,bytes,data);120}
121
122
123//--------------------------------------------------------------
124void ofVbo::VertexAttribute::setData(const float * attrib0x, int numCoords, int total, int usage, int stride, bool normalize){125if (!isAllocated()) {126allocate();127}128GLsizeiptr size = (stride == 0) ? numCoords * sizeof(float) : stride;129this->stride = size;130this->numCoords = numCoords;131this->offset = 0;132this->normalize = normalize;133setData(total * size, attrib0x, usage);134};135
136//--------------------------------------------------------------
137void ofVbo::VertexAttribute::setBuffer(ofBufferObject & buffer, int numCoords, int stride, int offset){138this->buffer = buffer;139this->offset = offset;140this->numCoords = numCoords;141GLsizeiptr size = (stride == 0) ? numCoords * sizeof(float) : stride;142this->stride = size;143
144};145
146//--------------------------------------------------------------
147void ofVbo::VertexAttribute::enable() const{148bind();149glEnableVertexAttribArray(location);150glVertexAttribPointer(location, numCoords, GL_FLOAT, normalize?GL_TRUE:GL_FALSE, stride, (void*)offset);151#ifndef TARGET_OPENGLES152glVertexAttribDivisor(location, divisor);153#endif154unbind();155}
156
157//--------------------------------------------------------------
158void ofVbo::VertexAttribute::disable() const{159glDisableVertexAttribArray(location);160}
161
162//--------------------------------------------------------------
163ofVbo::IndexAttribute::IndexAttribute()164{
165
166}
167
168//--------------------------------------------------------------
169bool ofVbo::IndexAttribute::isAllocated() const{170return buffer.isAllocated();171}
172
173//--------------------------------------------------------------
174void ofVbo::IndexAttribute::allocate(){175buffer.allocate();176}
177
178//--------------------------------------------------------------
179void ofVbo::IndexAttribute::bind() const{180buffer.bind(GL_ELEMENT_ARRAY_BUFFER);181}
182
183//--------------------------------------------------------------
184void ofVbo::IndexAttribute::setData(GLsizeiptr bytes, const void * data, GLenum usage){185buffer.bind(GL_ELEMENT_ARRAY_BUFFER);186buffer.setData(bytes,data,usage);187buffer.unbind(GL_ELEMENT_ARRAY_BUFFER);188}
189
190//--------------------------------------------------------------
191void ofVbo::IndexAttribute::unbind() const{192buffer.unbind(GL_ELEMENT_ARRAY_BUFFER);193}
194
195//--------------------------------------------------------------
196void ofVbo::IndexAttribute::updateData(GLintptr offset, GLsizeiptr bytes, const void * data){197buffer.updateData(offset,bytes,data);198}
199
200//--------------------------------------------------------------
201GLuint ofVbo::IndexAttribute::getId() const{202return buffer.getId();203}
204
205
206//--------------------------------------------------------------
207ofVbo::ofVbo(){208bUsingVerts = false;209bUsingTexCoords = false;210bUsingColors = false;211bUsingNormals = false;212bUsingIndices = false;213
214totalVerts = 0;215totalIndices = 0;216
217vaoChanged = false;218vaoID = 0;219
220positionAttribute.location = ofShader::POSITION_ATTRIBUTE;221colorAttribute.location = ofShader::COLOR_ATTRIBUTE;222texCoordAttribute.location = ofShader::TEXCOORD_ATTRIBUTE;223normalAttribute.location = ofShader::NORMAL_ATTRIBUTE;224}
225
226ofVbo::ofVbo(const ofVbo & mom){227bUsingVerts = mom.bUsingVerts;228bUsingTexCoords = mom.bUsingTexCoords;229bUsingColors = mom.bUsingColors;230bUsingNormals = mom.bUsingNormals;231bUsingIndices = mom.bUsingIndices;232
233positionAttribute = mom.positionAttribute;234colorAttribute = mom.colorAttribute;235texCoordAttribute = mom.texCoordAttribute;236normalAttribute = mom.normalAttribute;237
238customAttributes = mom.customAttributes;239
240totalVerts = mom.totalVerts;241totalIndices = mom.totalIndices;242indexAttribute = mom.indexAttribute;243
244vaoChanged = mom.vaoChanged;245vaoID = mom.vaoID;246
247if(ofIsGLProgrammableRenderer()){248retainVAO(vaoID);249}250}
251
252ofVbo & ofVbo::operator=(const ofVbo& mom){253if(&mom==this) return *this;254clear();255bUsingVerts = mom.bUsingVerts;256bUsingTexCoords = mom.bUsingTexCoords;257bUsingColors = mom.bUsingColors;258bUsingNormals = mom.bUsingNormals;259bUsingIndices = mom.bUsingIndices;260
261positionAttribute = mom.positionAttribute;262colorAttribute = mom.colorAttribute;263texCoordAttribute = mom.texCoordAttribute;264normalAttribute = mom.normalAttribute;265
266customAttributes = mom.customAttributes;267
268totalVerts = mom.totalVerts;269totalIndices = mom.totalIndices;270indexAttribute = mom.indexAttribute;271
272vaoChanged = mom.vaoChanged;273vaoID = mom.vaoID;274
275if(ofIsGLProgrammableRenderer()){276retainVAO(vaoID);277}278return *this;279}
280
281//--------------------------------------------------------------
282ofVbo::~ofVbo(){283clear();284}
285
286//--------------------------------------------------------------
287void ofVbo::setMesh(const ofMesh & mesh, int usage){288setMesh(mesh,usage,mesh.hasColors(),mesh.hasTexCoords(),mesh.hasNormals());289}
290
291//--------------------------------------------------------------
292void ofVbo::setMesh(const ofMesh & mesh, int usage, bool useColors, bool useTextures, bool useNormals){293if(mesh.getVertices().empty()){294ofLogWarning("ofVbo") << "setMesh(): ignoring mesh with no vertices";295return;296}297setVertexData(mesh.getVerticesPointer(),mesh.getNumVertices(),usage);298if(mesh.hasColors() && useColors){299setColorData(mesh.getColorsPointer(),mesh.getNumColors(),usage);300enableColors();301}else{302disableColors();303}304if(mesh.hasNormals() && useNormals){305setNormalData(mesh.getNormalsPointer(),mesh.getNumNormals(),usage);306enableNormals();307}else{308disableNormals();309}310if(mesh.hasTexCoords() && useTextures){311setTexCoordData(mesh.getTexCoordsPointer(),mesh.getNumTexCoords(),usage);312enableTexCoords();313}else{314disableTexCoords();315}316if(mesh.hasIndices()){317setIndexData(mesh.getIndexPointer(), mesh.getNumIndices(), usage);318enableIndices();319}else{320disableIndices();321}322}
323
324//--------------------------------------------------------------
325void ofVbo::setVertexData(const glm::vec3 * verts, int total, int usage) {326setVertexData(&verts[0].x,3,total,usage,sizeof(glm::vec3));327}
328
329//--------------------------------------------------------------
330void ofVbo::setVertexData(const ofVec3f * verts, int total, int usage) {331setVertexData(&verts[0].x,3,total,usage,sizeof(glm::vec3));332}
333
334//--------------------------------------------------------------
335void ofVbo::setVertexData(const glm::vec2 * verts, int total, int usage) {336setVertexData(&verts[0].x,2,total,usage,sizeof(glm::vec2));337}
338
339//--------------------------------------------------------------
340void ofVbo::setVertexData(const ofVec2f * verts, int total, int usage) {341setVertexData(&verts[0].x,2,total,usage,sizeof(glm::vec2));342}
343
344//--------------------------------------------------------------
345void ofVbo::setVertexData(const float * vert0x, int numCoords, int total, int usage, int stride) {346positionAttribute.setData(vert0x, numCoords, total, usage, stride);347bUsingVerts = true;348totalVerts = total;349}
350
351//--------------------------------------------------------------
352void ofVbo::setColorData(const ofFloatColor * colors, int total, int usage) {353setColorData(&colors[0].r,total,usage,sizeof(ofFloatColor));354}
355
356//--------------------------------------------------------------
357void ofVbo::setColorData(const float * color0r, int total, int usage, int stride) {358colorAttribute.setData(color0r, 4, total, usage, stride);359enableColors();360}
361
362//--------------------------------------------------------------
363void ofVbo::setNormalData(const glm::vec3 * normals, int total, int usage) {364setNormalData(&normals[0].x,total,usage,sizeof(glm::vec3));365}
366
367//--------------------------------------------------------------
368void ofVbo::setNormalData(const ofVec3f * normals, int total, int usage) {369setNormalData(&normals[0].x,total,usage,sizeof(glm::vec3));370}
371
372//--------------------------------------------------------------
373void ofVbo::setNormalData(const float * normal0x, int total, int usage, int stride) {374normalAttribute.setData(normal0x, 3, total, usage, stride);375enableNormals();376}
377
378//--------------------------------------------------------------
379void ofVbo::setTexCoordData(const glm::vec2 * texCoords, int total, int usage) {380setTexCoordData(&texCoords[0].x,total, usage, sizeof(glm::vec2));381}
382
383//--------------------------------------------------------------
384void ofVbo::setTexCoordData(const ofVec2f * texCoords, int total, int usage) {385setTexCoordData(&texCoords[0].x,total, usage, sizeof(glm::vec2));386}
387
388//--------------------------------------------------------------
389void ofVbo::setTexCoordData(const float * texCoord0x, int total, int usage, int stride) {390texCoordAttribute.setData(texCoord0x, 2, total, usage, stride);391enableTexCoords();392}
393
394
395//--------------------------------------------------------------
396void ofVbo::setIndexData(const ofIndexType * indices, int total, int usage){397if(!indexAttribute.isAllocated()){398indexAttribute.allocate();399enableIndices();400}401totalIndices = total;402indexAttribute.setData(sizeof(ofIndexType) * total, &indices[0], usage);403}
404
405//--------------------------------------------------------------
406ofVbo::VertexAttribute & ofVbo::getOrCreateAttr(int location){407VertexAttribute * attr = nullptr;408if (ofIsGLProgrammableRenderer()) {409switch (location){410case ofShader::POSITION_ATTRIBUTE:411attr = &positionAttribute;412break;413case ofShader::COLOR_ATTRIBUTE:414attr = &colorAttribute;415break;416case ofShader::NORMAL_ATTRIBUTE:417attr = &normalAttribute;418break;419case ofShader::TEXCOORD_ATTRIBUTE:420attr = &texCoordAttribute;421break;422default:423customAttributes[location].location = location;424attr = &customAttributes[location];425vaoChanged = true;426break;427}428}else{429customAttributes[location].location = location;430attr = &customAttributes[location];431vaoChanged = true;432}433return *attr;434}
435
436//--------------------------------------------------------------
437void ofVbo::setAttributeData(int location, const float * attrib0x, int numCoords, int total, int usage, int stride){438if(ofIsGLProgrammableRenderer() && location==ofShader::POSITION_ATTRIBUTE){439totalVerts = total;440}441
442bool normalize = false;443if(ofIsGLProgrammableRenderer() && !hasAttribute(location)){444vaoChanged = true;445bUsingVerts |= (location == ofShader::POSITION_ATTRIBUTE);446bUsingColors |= (location == ofShader::COLOR_ATTRIBUTE);447bUsingNormals |= (location == ofShader::NORMAL_ATTRIBUTE);448bUsingTexCoords |= (location == ofShader::TEXCOORD_ATTRIBUTE);449}450
451getOrCreateAttr(location).setData(attrib0x,numCoords,total,usage,stride,normalize);452}
453
454#ifndef TARGET_OPENGLES455//--------------------------------------------------------------
456void ofVbo::setAttributeDivisor(int location, int divisor){457getOrCreateAttr(location).divisor = divisor;458}
459#endif460
461//--------------------------------------------------------------
462void ofVbo::updateMesh(const ofMesh & mesh){463updateVertexData(mesh.getVerticesPointer(),mesh.getNumVertices());464updateColorData(mesh.getColorsPointer(),mesh.getNumColors());465updateNormalData(mesh.getNormalsPointer(),mesh.getNumNormals());466updateTexCoordData(mesh.getTexCoordsPointer(),mesh.getNumTexCoords());467}
468
469//--------------------------------------------------------------
470void ofVbo::updateVertexData(const glm::vec3 * verts, int total) {471updateVertexData(&verts[0].x,total);472}
473
474//--------------------------------------------------------------
475void ofVbo::updateVertexData(const ofVec3f * verts, int total) {476updateVertexData(&verts[0].x,total);477}
478
479//--------------------------------------------------------------
480void ofVbo::updateVertexData(const glm::vec2 * verts, int total) {481updateVertexData(&verts[0].x,total);482}
483
484//--------------------------------------------------------------
485void ofVbo::updateVertexData(const ofVec2f * verts, int total) {486updateVertexData(&verts[0].x,total);487}
488
489//--------------------------------------------------------------
490void ofVbo::updateVertexData(const float * vert0x, int total) {491positionAttribute.updateData(0, total * positionAttribute.stride, vert0x);492}
493
494//--------------------------------------------------------------
495void ofVbo::updateColorData(const ofFloatColor * colors, int total) {496updateColorData(&colors[0].r,total);497}
498
499//--------------------------------------------------------------
500void ofVbo::updateColorData(const float * color0r, int total) {501colorAttribute.updateData(0, total * colorAttribute.stride, color0r);502}
503
504//--------------------------------------------------------------
505void ofVbo::updateNormalData(const glm::vec3 * normals, int total) {506updateNormalData(&normals[0].x,total);507}
508
509//--------------------------------------------------------------
510void ofVbo::updateNormalData(const ofVec3f * normals, int total) {511updateNormalData(&normals[0].x,total);512}
513
514//--------------------------------------------------------------
515void ofVbo::updateNormalData(const float * normal0x, int total) {516normalAttribute.updateData(0, total * normalAttribute.stride, normal0x);517}
518
519//--------------------------------------------------------------
520void ofVbo::updateTexCoordData(const glm::vec2 * texCoords, int total) {521updateTexCoordData(&texCoords[0].x,total);522}
523
524//--------------------------------------------------------------
525void ofVbo::updateTexCoordData(const ofVec2f * texCoords, int total) {526updateTexCoordData(&texCoords[0].x,total);527}
528
529//--------------------------------------------------------------
530void ofVbo::updateTexCoordData(const float * texCoord0x, int total) {531texCoordAttribute.updateData(0, total * texCoordAttribute.stride, texCoord0x);532}
533
534//--------------------------------------------------------------
535void ofVbo::updateIndexData(const ofIndexType * indices, int total) {536if(indexAttribute.isAllocated()) {537indexAttribute.updateData(0, total*sizeof(ofIndexType), indices);538}539}
540
541void ofVbo::updateAttributeData(int location, const float * attr0x, int total){542VertexAttribute * attr = nullptr;543if (ofIsGLProgrammableRenderer()) {544switch (location){545case ofShader::POSITION_ATTRIBUTE:546attr = &positionAttribute;547break;548case ofShader::COLOR_ATTRIBUTE:549attr = &colorAttribute;550break;551case ofShader::NORMAL_ATTRIBUTE:552attr = &normalAttribute;553break;554case ofShader::TEXCOORD_ATTRIBUTE:555attr = &texCoordAttribute;556break;557default:558if(customAttributes.find(location)!=customAttributes.end()) {559attr = &customAttributes[location];560}561break;562}563} else {564if(customAttributes.find(location)!=customAttributes.end()) {565attr = &customAttributes[location];566}567}568if (attr !=nullptr && attr->isAllocated()) {569attr->updateData(0, total*attr->stride, attr0x);570}571}
572
573void ofVbo::enableColors() {574if (!bUsingColors && colorAttribute.isAllocated()) {575bUsingColors=true;576vaoChanged = true;577}578}
579
580void ofVbo::enableNormals(){581if (!bUsingNormals && normalAttribute.isAllocated()) {582bUsingNormals=true;583vaoChanged = true;584}585}
586
587void ofVbo::enableTexCoords(){588if (!bUsingTexCoords && texCoordAttribute.isAllocated()){589bUsingTexCoords = true;590vaoChanged = true;591}592}
593
594void ofVbo::enableIndices(){595if(indexAttribute.isAllocated() && !bUsingIndices){596bUsingIndices=true;597vaoChanged = true;598}599}
600
601void ofVbo::disableColors(){602if(bUsingColors){603bUsingColors=false;604vaoChanged = true;605}606}
607
608void ofVbo::disableNormals(){609if(bUsingNormals){610bUsingNormals=false;611vaoChanged = true;612}613}
614
615void ofVbo::disableTexCoords(){616if(bUsingTexCoords){617bUsingTexCoords=false;618vaoChanged = true;619}620}
621
622void ofVbo::disableIndices(){623if(bUsingIndices){624bUsingIndices=false;625vaoChanged = true;626}627}
628
629//--------------------------------------------------------------
630bool ofVbo::getIsAllocated() const {631return positionAttribute.isAllocated();632}
633
634//--------------------------------------------------------------
635bool ofVbo::getUsingVerts() const {636return bUsingVerts;637}
638
639//--------------------------------------------------------------
640bool ofVbo::getUsingColors() const {641return bUsingColors;642}
643
644//--------------------------------------------------------------
645bool ofVbo::getUsingNormals() const {646return bUsingNormals;647}
648
649//--------------------------------------------------------------
650bool ofVbo::getUsingTexCoords() const {651return bUsingTexCoords;652}
653
654//--------------------------------------------------------------
655bool ofVbo::getUsingIndices() const {656return bUsingIndices;657}
658
659//--------------------------------------------------------------
660GLuint ofVbo::getVaoId() const{661return vaoID;662}
663
664//--------------------------------------------------------------
665GLuint ofVbo::getVertId() const {666return positionAttribute.getId();667}
668
669//--------------------------------------------------------------
670GLuint ofVbo::getColorId() const{671return colorAttribute.getId();672}
673
674//--------------------------------------------------------------
675GLuint ofVbo::getNormalId() const {676return normalAttribute.getId();677}
678
679//--------------------------------------------------------------
680GLuint ofVbo::getTexCoordId() const {681return texCoordAttribute.getId();682}
683
684//--------------------------------------------------------------
685GLuint ofVbo::getIndexId() const {686return indexAttribute.getId();687}
688
689//--------------------------------------------------------------
690GLuint ofVbo::getAttributeId(int location) const {691if (!hasAttribute(location)) {692ofLogWarning() << "No attribute id found for attribute pos: " << location;693return 0;694}695return const_cast<ofVbo*>(this)->getOrCreateAttr(location).getId();696}
697
698//--------------------------------------------------------------
699void ofVbo::setVertexBuffer(ofBufferObject & buffer, int numCoords, int stride, int offset){700positionAttribute.setBuffer(buffer, numCoords, stride, offset);701bUsingVerts = true;702vaoChanged = true;703// Calculate the total number of vertices based on what we know:704int tmpStride = stride;705if (tmpStride == 0) {706// if stride is not given through argument, we need to calculate it based on707// on the data size and the number of coordinates.708tmpStride = (numCoords * sizeof(float));709if (tmpStride == 0) {710ofLogWarning() << "Setting buffer with 0 vertices.";711totalVerts = 0;712return;713}714}715totalVerts = buffer.size() / tmpStride;716}
717
718//--------------------------------------------------------------
719void ofVbo::setColorBuffer(ofBufferObject & buffer, int stride, int offset){720colorAttribute.setBuffer(buffer, 4, stride, offset);721enableColors();722}
723
724//--------------------------------------------------------------
725void ofVbo::setNormalBuffer(ofBufferObject & buffer, int stride, int offset){726normalAttribute.setBuffer(buffer, 3, stride, offset);727enableNormals();728}
729
730//--------------------------------------------------------------
731void ofVbo::setTexCoordBuffer(ofBufferObject & buffer, int stride, int offset){732texCoordAttribute.setBuffer(buffer, 2, stride, offset);733enableTexCoords();734}
735
736//--------------------------------------------------------------
737void ofVbo::setIndexBuffer(ofBufferObject & buffer){738indexAttribute.buffer = buffer;739vaoChanged = true;740enableIndices();741}
742
743//--------------------------------------------------------------
744void ofVbo::setAttributeBuffer(int location, ofBufferObject & buffer, int numCoords, int stride, int offset){745if(ofIsGLProgrammableRenderer() && !hasAttribute(location)){746vaoChanged = true;747bUsingVerts |= (location == ofShader::POSITION_ATTRIBUTE);748bUsingColors |= (location == ofShader::COLOR_ATTRIBUTE);749bUsingNormals |= (location == ofShader::NORMAL_ATTRIBUTE);750bUsingTexCoords |= (location == ofShader::TEXCOORD_ATTRIBUTE);751}752
753getOrCreateAttr(location).setBuffer(buffer, numCoords, stride, offset);754}
755
756//--------------------------------------------------------------
757ofBufferObject & ofVbo::getVertexBuffer(){758return positionAttribute.buffer;759}
760
761//--------------------------------------------------------------
762ofBufferObject & ofVbo::getColorBuffer(){763return colorAttribute.buffer;764}
765
766//--------------------------------------------------------------
767ofBufferObject & ofVbo::getNormalBuffer(){768return normalAttribute.buffer;769}
770
771//--------------------------------------------------------------
772ofBufferObject & ofVbo::getTexCoordBuffer(){773return texCoordAttribute.buffer;774}
775
776//--------------------------------------------------------------
777ofBufferObject & ofVbo::getIndexBuffer(){778return indexAttribute.buffer;779}
780
781//--------------------------------------------------------------
782ofBufferObject & ofVbo::getAttributeBuffer(int attributePos_) {783
784if( attributePos_ == ofShader::POSITION_ATTRIBUTE ) {785return getVertexBuffer();786} else if( attributePos_ == ofShader::COLOR_ATTRIBUTE ) {787return getColorBuffer();788} else if( attributePos_ == ofShader::NORMAL_ATTRIBUTE ) {789return getNormalBuffer();790} else if( attributePos_ == ofShader::TEXCOORD_ATTRIBUTE ) {791return getTexCoordBuffer();792}793
794return customAttributes.at(attributePos_).buffer;795}
796
797//--------------------------------------------------------------
798const ofBufferObject & ofVbo::getVertexBuffer() const{799return positionAttribute.buffer;800}
801
802//--------------------------------------------------------------
803const ofBufferObject & ofVbo::getColorBuffer() const{804return colorAttribute.buffer;805}
806
807//--------------------------------------------------------------
808const ofBufferObject & ofVbo::getNormalBuffer() const{809return normalAttribute.buffer;810}
811
812//--------------------------------------------------------------
813const ofBufferObject & ofVbo::getTexCoordBuffer() const{814return texCoordAttribute.buffer;815}
816
817//--------------------------------------------------------------
818const ofBufferObject & ofVbo::getAttributeBuffer(int attributePos_) const{819if( attributePos_ == ofShader::POSITION_ATTRIBUTE ) {820return getVertexBuffer();821} else if( attributePos_ == ofShader::COLOR_ATTRIBUTE ) {822return getColorBuffer();823} else if( attributePos_ == ofShader::NORMAL_ATTRIBUTE ) {824return getNormalBuffer();825} else if( attributePos_ == ofShader::TEXCOORD_ATTRIBUTE ) {826return getTexCoordBuffer();827}828
829return customAttributes.at(attributePos_).buffer;830}
831
832
833//--------------------------------------------------------------
834const ofBufferObject & ofVbo::getIndexBuffer() const{835return indexAttribute.buffer;836}
837
838//--------------------------------------------------------------
839void ofVbo::bind() const{840bool programmable = ofIsGLProgrammableRenderer();841if(programmable && (vaoSupported || !vaoChecked)){842if(vaoID==0){843#if defined(TARGET_OPENGLES) && !defined(TARGET_EMSCRIPTEN)844if(glGenVertexArrays==0 && !vaoChecked){845glGenVertexArrays = (glGenVertexArraysType)dlsym(RTLD_DEFAULT, "glGenVertexArrays");846glDeleteVertexArrays = (glDeleteVertexArraysType)dlsym(RTLD_DEFAULT, "glDeleteVertexArrays");847glBindVertexArray = (glBindVertexArrayType)dlsym(RTLD_DEFAULT, "glBindVertexArray");848vaoChecked = true;849vaoSupported = glGenVertexArrays;850}851#elif defined(TARGET_EMSCRIPTEN)852vaoChecked = true;853vaoSupported = false;854#else855vaoChecked = true;856vaoSupported = true;857#endif858if(vaoSupported) glGenVertexArrays(1, &const_cast<ofVbo*>(this)->vaoID);859if(vaoID!=0){860retainVAO(vaoID);861vaoChanged = true;862}863}864if(vaoSupported) glBindVertexArray(vaoID);865}else{866vaoSupported = false;867}868
869if(vaoChanged || !vaoSupported){870if(bUsingVerts){871if(!programmable){872positionAttribute.bind();873#ifndef TARGET_PROGRAMMABLE_GL874glEnableClientState(GL_VERTEX_ARRAY);875glVertexPointer(positionAttribute.numCoords, GL_FLOAT,876positionAttribute.stride,877(void*)positionAttribute.offset);878#endif879}else{880positionAttribute.enable();881}882}else if(programmable){883positionAttribute.disable();884}885
886if(bUsingColors) {887if(!programmable){888colorAttribute.bind();889#ifndef TARGET_PROGRAMMABLE_GL890glEnableClientState(GL_COLOR_ARRAY);891glColorPointer(colorAttribute.numCoords, GL_FLOAT,892colorAttribute.stride,893(void*)colorAttribute.offset);894#endif895}else{896colorAttribute.enable();897}898}else if(programmable){899colorAttribute.disable();900}901
902if(bUsingNormals) {903if(!programmable){904normalAttribute.bind();905#ifndef TARGET_PROGRAMMABLE_GL906glEnableClientState(GL_NORMAL_ARRAY);907glNormalPointer(GL_FLOAT, normalAttribute.stride,908(void*)normalAttribute.offset);909#endif910}else{911normalAttribute.enable();912}913}else if(programmable){914normalAttribute.disable();915}916
917if(bUsingTexCoords) {918if(!programmable){919texCoordAttribute.bind();920#ifndef TARGET_PROGRAMMABLE_GL921glEnableClientState(GL_TEXTURE_COORD_ARRAY);922glTexCoordPointer(texCoordAttribute.numCoords,923GL_FLOAT, texCoordAttribute.stride,924(void*)texCoordAttribute.offset);925#endif926}else{927texCoordAttribute.enable();928}929}else if(programmable){930texCoordAttribute.disable();931}932
933if (bUsingIndices) {934indexAttribute.bind();935}936
937unordered_map<int,VertexAttribute>::const_iterator it;938for(it = customAttributes.begin();it!=customAttributes.end();it++){939it->second.enable();940}941
942vaoChanged=false;943}944}
945
946//--------------------------------------------------------------
947void ofVbo::unbind() const{948if(vaoSupported){949glBindVertexArray(0);950}951glBindBuffer(GL_ARRAY_BUFFER, 0);952glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);953if(!ofIsGLProgrammableRenderer()){954#ifndef TARGET_PROGRAMMABLE_GL955if(bUsingColors){956glDisableClientState(GL_COLOR_ARRAY);957}958if(bUsingNormals){959glDisableClientState(GL_NORMAL_ARRAY);960}961if(bUsingTexCoords){962glDisableClientState(GL_TEXTURE_COORD_ARRAY);963}964#endif965}966}
967
968//--------------------------------------------------------------
969void ofVbo::draw(int drawMode, int first, int total) const{970ofGetGLRenderer()->draw(*this,drawMode,first,total);971}
972
973//--------------------------------------------------------------
974void ofVbo::drawElements(int drawMode, int amt, int offsetelements) const{975ofGetGLRenderer()->drawElements(*this,drawMode,amt,offsetelements);976}
977
978//--------------------------------------------------------------
979void ofVbo::drawInstanced(int drawMode, int first, int total, int primCount) const{980ofGetGLRenderer()->drawInstanced(*this,drawMode,first,total,primCount);981}
982
983//--------------------------------------------------------------
984void ofVbo::drawElementsInstanced(int drawMode, int amt, int primCount) const{985ofGetGLRenderer()->drawElementsInstanced(*this,drawMode,amt,primCount);986}
987
988//--------------------------------------------------------------
989void ofVbo::clear(){990
991// clear all fixed function attributes992
993clearVertices();994clearColors();995clearNormals();996clearTexCoords();997
998// we're not using any of these.999bUsingVerts = false;1000bUsingColors = false;1001bUsingNormals = false;1002bUsingTexCoords = false;1003
1004// clear all custom attributes.1005customAttributes.clear();1006
1007clearIndices();1008if(vaoID!=0){1009releaseVAO(vaoID);1010vaoID=0;1011}1012}
1013
1014
1015//--------------------------------------------------------------
1016void ofVbo::clearVertices(){1017positionAttribute = VertexAttribute();1018positionAttribute.location = ofShader::POSITION_ATTRIBUTE;1019bUsingVerts = false;1020totalVerts = 0;1021}
1022
1023//--------------------------------------------------------------
1024void ofVbo::clearNormals(){1025normalAttribute = VertexAttribute();1026normalAttribute.location = ofShader::NORMAL_ATTRIBUTE;1027bUsingNormals = false;1028}
1029
1030//--------------------------------------------------------------
1031void ofVbo::clearColors(){1032colorAttribute = VertexAttribute();1033colorAttribute.location = ofShader::COLOR_ATTRIBUTE;1034bUsingColors = false;1035
1036}
1037
1038//--------------------------------------------------------------
1039void ofVbo::clearTexCoords(){1040texCoordAttribute = VertexAttribute();1041texCoordAttribute.location = ofShader::TEXCOORD_ATTRIBUTE;1042bUsingTexCoords = false;1043}
1044
1045//--------------------------------------------------------------
1046void ofVbo::clearIndices(){1047if(indexAttribute.isAllocated()){1048indexAttribute = IndexAttribute();1049bUsingIndices = false;1050totalIndices = 0;1051}1052}
1053
1054//--------------------------------------------------------------
1055
1056void ofVbo::clearAttribute(int attributePos_){1057
1058if (!hasAttribute(attributePos_)) return;1059
1060if (ofIsGLProgrammableRenderer()) {1061if(attributePos_>3){1062customAttributes.erase(attributePos_);1063}else{1064switch (attributePos_){1065case ofShader::POSITION_ATTRIBUTE:1066clearVertices();1067break;1068case ofShader::COLOR_ATTRIBUTE:1069clearColors();1070break;1071case ofShader::NORMAL_ATTRIBUTE:1072clearNormals();1073break;1074case ofShader::TEXCOORD_ATTRIBUTE:1075clearTexCoords();1076break;1077default:1078break;1079}1080}1081}else{1082customAttributes.erase(attributePos_);1083}1084}
1085
1086//--------------------------------------------------------------
1087int ofVbo::getNumIndices() const {1088if (bUsingIndices) {1089return totalIndices;1090} else {1091return 0;1092}1093}
1094
1095//--------------------------------------------------------------
1096int ofVbo::getNumVertices() const {1097return totalVerts;1098}
1099
1100//--------------------------------------------------------------
1101bool ofVbo::hasAttribute(int attributePos) const {1102if(ofIsGLProgrammableRenderer()){1103switch(attributePos){1104case ofShader::POSITION_ATTRIBUTE:1105return positionAttribute.isAllocated();1106case ofShader::COLOR_ATTRIBUTE:1107return colorAttribute.isAllocated();1108case ofShader::NORMAL_ATTRIBUTE:1109return normalAttribute.isAllocated();1110case ofShader::TEXCOORD_ATTRIBUTE:1111return texCoordAttribute.isAllocated();1112}1113}1114return (customAttributes.find(attributePos) != customAttributes.end());1115}
1116
1117