// generate vertex array object void Mesh::generateVAO(Material::ShaderType key) { #if _GVRF_USE_GLES3_ GLuint tmpID; if (vao_dirty_) { deleteVaos(); } if (vaoID_map_.find(key) != vaoID_map_.end()) { // already initialized return; } if (vertices_.size() == 0 && normals_.size() == 0 && tex_coords_.size() == 0) { std::string error = "no vertex data yet, shouldn't call here. "; throw error; return; } if (vertexLoc_ == -1 && normalLoc_ == -1 && texCoordLoc_ == -1) { std::string error = "no attrib loc setup yet, please compile shader and set attribLoc first. "; throw error; return; } GLuint vaoID_ = 0; GLuint triangle_vboID_, vert_vboID_, norm_vboID_, tex_vboID_; glGenVertexArrays(1, &vaoID_); glBindVertexArray(vaoID_); glGenBuffers(1, &triangle_vboID_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangle_vboID_); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * triangles_.size(), &triangles_[0], GL_STATIC_DRAW); numTriangles_ = triangles_.size() / 3; if (vertices_.size()) { glGenBuffers(1, &vert_vboID_); glBindBuffer(GL_ARRAY_BUFFER, vert_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices_.size(), &vertices_[0], GL_STATIC_DRAW); glEnableVertexAttribArray(getVertexLoc()); glVertexAttribPointer(getVertexLoc(), 3, GL_FLOAT, 0, 0, 0); } if (normals_.size()) { glGenBuffers(1, &norm_vboID_); glBindBuffer(GL_ARRAY_BUFFER, norm_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * normals_.size(), &normals_[0], GL_STATIC_DRAW); glEnableVertexAttribArray(getNormalLoc()); glVertexAttribPointer(getNormalLoc(), 3, GL_FLOAT, 0, 0, 0); } if (tex_coords_.size()) { glGenBuffers(1, &tex_vboID_); glBindBuffer(GL_ARRAY_BUFFER, tex_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * tex_coords_.size(), &tex_coords_[0], GL_STATIC_DRAW); glEnableVertexAttribArray(getTexCoordLoc()); glVertexAttribPointer(getTexCoordLoc(), 2, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_float_keys_.begin(); it != attribute_float_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * getFloatVector(it->second).size(), getFloatVector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 1, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec2_keys_.begin(); it != attribute_vec2_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * getVec2Vector(it->second).size(), getVec2Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 2, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec3_keys_.begin(); it != attribute_vec3_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * getVec3Vector(it->second).size(), getVec3Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 3, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec4_keys_.begin(); it != attribute_vec4_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * getVec4Vector(it->second).size(), getVec4Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 4, GL_FLOAT, 0, 0, 0); } vaoID_map_[key] = vaoID_; triangle_vboID_map_[key] = triangle_vboID_; vert_vboID_map_[key] = vert_vboID_; norm_vboID_map_[key] = norm_vboID_; tex_vboID_map_[key] = tex_vboID_; // done generation glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); vao_dirty_ = false; #endif }
// generate vertex array object void Mesh::generateVAO() { #if _GVRF_USE_GLES3_ GLuint tmpID; if (!vao_dirty_) { return; } deleteVaos(); if (vertices_.size() == 0 && normals_.size() == 0 && tex_coords_.size() == 0) { std::string error = "no vertex data yet, shouldn't call here. "; throw error; return; } glGenVertexArrays(1, &vaoID_); glBindVertexArray(vaoID_); glGenBuffers(1, &triangle_vboID_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangle_vboID_); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * indices_.size(), &indices_[0], GL_STATIC_DRAW); numTriangles_ = indices_.size() / 3; if (vertices_.size()) { glGenBuffers(1, &vert_vboID_); glBindBuffer(GL_ARRAY_BUFFER, vert_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices_.size(), &vertices_[0], GL_STATIC_DRAW); GLuint vertexLoc = GLProgram::POSITION_ATTRIBUTE_LOCATION; glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); } if (normals_.size()) { glGenBuffers(1, &norm_vboID_); glBindBuffer(GL_ARRAY_BUFFER, norm_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * normals_.size(), &normals_[0], GL_STATIC_DRAW); GLuint normalLoc = GLProgram::NORMAL_ATTRIBUTE_LOCATION; glEnableVertexAttribArray(normalLoc); glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0); } if (tex_coords_.size()) { glGenBuffers(1, &tex_vboID_); glBindBuffer(GL_ARRAY_BUFFER, tex_vboID_); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * tex_coords_.size(), &tex_coords_[0], GL_STATIC_DRAW); GLuint texCoordLoc = GLProgram::TEXCOORD_ATTRIBUT_LOCATION; glEnableVertexAttribArray(texCoordLoc); glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_float_keys_.begin(); it != attribute_float_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * getFloatVector(it->second).size(), getFloatVector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 1, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec2_keys_.begin(); it != attribute_vec2_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * getVec2Vector(it->second).size(), getVec2Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 2, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec3_keys_.begin(); it != attribute_vec3_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * getVec3Vector(it->second).size(), getVec3Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 3, GL_FLOAT, 0, 0, 0); } for (auto it = attribute_vec4_keys_.begin(); it != attribute_vec4_keys_.end(); ++it) { glGenBuffers(1, &tmpID); glBindBuffer(GL_ARRAY_BUFFER, tmpID); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * getVec4Vector(it->second).size(), getVec4Vector(it->second).data(), GL_STATIC_DRAW); glEnableVertexAttribArray(it->first); glVertexAttribPointer(it->first, 4, GL_FLOAT, 0, 0, 0); } // done generation glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); vao_dirty_ = false; #endif }
void Mesh::createAttributeMapping(int programId, int& totalStride, int& attrLen) { totalStride = attrLen = 0; if (programId == -1) { // If program id has not been set, return. return; } GLint numActiveAtributes; glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTES, &numActiveAtributes); GLchar attrName[512]; GLAttributeMapping attrData; for (int i = 0; i < numActiveAtributes; i++) { GLsizei length; GLint size; GLenum type; glGetActiveAttrib(programId, i, 512, &length, &size, &type, attrName); if (std::find(dynamicAttribute_Names_.begin(), dynamicAttribute_Names_.end(), attrName) != dynamicAttribute_Names_.end()) { // Skip dynamic attributes. Currently only bones are dynamic attributes which changes each frame. // They are handled seperately. } else { attrData.type = GL_FLOAT; int loc = glGetAttribLocation(programId, attrName); attrData.index = loc; attrData.data = NULL; attrData.offset = totalStride; bool addData = true; int len = 0; // Two things to note -- // 1. The 3 builtin buffers are still seperate from the maps used for the other attributes // 2. The attribute index *has* to be 0, 1 and 2 for position, tex_coords and normal. The // index from querying via glGetActiveAttrib cannot be used. Needs analysis. if (strcmp(attrName, "a_position") == 0) { attrData.size = 3; len = vertices_.size(); attrData.data = vertices_.data(); //attrData.index = 0; } else if (strcmp(attrName, "a_normal") == 0) { attrData.size = 3; len = normals_.size(); attrData.data = normals_.data(); //attrData.index = 1; } else if (strcmp(attrName, "a_texcoord") == 0) { attrData.size = 2; len = tex_coords_.size(); attrData.data = tex_coords_.data(); //attrData.index = 2; } else if (strcmp(attrName, "a_tex_coord") == 0) { attrData.size = 2; len = tex_coords_.size(); attrData.data = tex_coords_.data(); //attrData.index = 2; } else { switch (type) { case GL_FLOAT: attrData.size = 1; { const std::vector<float>& curr = getFloatVector(attrName); len = curr.size(); attrData.data = curr.data(); } break; case GL_FLOAT_VEC2: attrData.size = 2; { const std::vector<glm::vec2>& curr = getVec2Vector(attrName); len = curr.size(); attrData.data = curr.data(); } break; case GL_FLOAT_VEC3: attrData.size = 3; { const std::vector<glm::vec3>& curr = getVec3Vector(attrName); len = curr.size(); attrData.data = curr.data(); } break; case GL_FLOAT_VEC4: attrData.size = 4; { const std::vector<glm::vec4>& curr = getVec4Vector(attrName); len = curr.size(); attrData.data = curr.data(); } break; default: addData = false; LOGE("Looking up %s failed ", attrName); break; } } if (addData) { totalStride += attrData.size; attrMapping.push_back(attrData); if (attrLen == 0) attrLen = len; else { if (len != attrLen) LOGE(" $$$$*** Attib length does not match %d vs %d", len, attrLen); } } } } }