void OpenGLSPropRenderer::render(const Math::Vector3d position, float direction) { if (_faceVBO == -1) { // Update the OpenGL Buffer Objects if required clearVertices(); uploadVertices(); } _gfx->set3DMode(); Math::Matrix4 model = getModelMatrix(position, direction); Math::Matrix4 view = StarkScene->getViewMatrix(); Math::Matrix4 projection = StarkScene->getProjectionMatrix(); Math::Matrix4 mvp = projection * view * model; mvp.transpose(); _shader->use(true); _shader->setUniform("mvp", mvp); const Common::Array<Formats::BiffMesh::Face> &faces = _model->getFaces(); const Common::Array<Formats::BiffMesh::Material> &materials = _model->getMaterials(); for (Common::Array<Formats::BiffMesh::Face>::const_iterator face = faces.begin(); face != faces.end(); ++face) { const Formats::BiffMesh::Material &material = materials[face->materialId]; // For each face draw its vertices from the VBO, indexed by the EBO const Gfx::Texture *tex = _texture->getTexture(material.texture); if (tex) { tex->bind(); } else { glBindTexture(GL_TEXTURE_2D, 0); } GLuint ebo = _faceEBO[face]; _shader->enableVertexAttribute("position", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); _shader->enableVertexAttribute("normal", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 12); _shader->enableVertexAttribute("texcoord", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 24); _shader->use(true); _shader->setUniform("textured", tex != nullptr); _shader->setUniform("color", Math::Vector3d(material.r, material.g, material.b)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glDrawElements(GL_TRIANGLES, face->vertexIndices.size(), GL_UNSIGNED_INT, 0); glUseProgram(0); } }
void Geometry::upload(std::set<Buffers> dynamicAccess) { std::set<Buffers> dyn(dynamicAccess); if (m_hasDataVertices) { uploadVertices((dyn.find(VERTICES) == dyn.end()) ? STATIC_ACCESS : DYNAMIC_ACCESS); } if (m_hasDataNormals) { uploadNormals((dyn.find(NORMALS) == dyn.end()) ? STATIC_ACCESS : DYNAMIC_ACCESS); } if (m_hasDataColors) { uploadColors((dyn.find(COLORS) == dyn.end()) ? STATIC_ACCESS : DYNAMIC_ACCESS); } if (m_hasDataIndices) { uploadIndices((dyn.find(INDICES) == dyn.end()) ? STATIC_ACCESS : DYNAMIC_ACCESS); } if (m_hasTexCoords) { uploadTexCoords((dyn.find(TEXCOORDS) == dyn.end()) ? STATIC_ACCESS : DYNAMIC_ACCESS); } }
void Renderer::flush() { int numOfRenderables = renderingQueue.size(); if (numOfRenderables > 0) { // Build the vertex-buffer std::vector<float> vertexBuffer; vertexBuffer.reserve(numOfRenderables * VERTEX_PER_RENDERABLE); for (auto renderable : renderingQueue) { std::shared_ptr<SpriteComponent> sprite = renderable->getComponent<SpriteComponent>(SpriteComponent::componentName); std::vector<float> vertices = sprite->getVertices(); vertexBuffer.insert(vertexBuffer.end(), vertices.begin(), vertices.end()); } // Upload data to the GPU uploadVertices(vertexBuffer); // Render the uploaded data renderBuffers(numOfRenderables * INDEX_PER_RENDERABLE); // Clear the rendering queue renderingQueue.clear(); } }
void uploadVertices(const std::vector<T>& data) { uploadVertices(static_cast<GLsizei>(data.size()), data.size() * sizeof(T), data.data()); // Assume T has a static method for attributes; attributes = T::vertex_attributes(); }
GeometryBuffer(const std::vector<T>& data) { uploadVertices(data); }
GeometryBuffer(const std::vector<T>& data) : vbo(0), num(0) { uploadVertices(data); }
void Text::addTextData(const TextData &t) { std::vector<Font::GlyphVertex> vertices; std::vector<Font::DrawCommand> new_commands; Font::TextInfo text_info; Colorf constantcolor = Colorf(1.0f, 1.0f, 1.0f, 1.0f); // We only have formatted text if the align mode is valid. if (t.align == Font::ALIGN_MAX_ENUM) new_commands = font->generateVertices(t.codepoints, constantcolor, vertices, 0.0f, Vector2(0.0f, 0.0f), &text_info); else new_commands = font->generateVerticesFormatted(t.codepoints, constantcolor, t.wrap, t.align, vertices, &text_info); if (vertices.empty()) return; if (t.use_matrix) t.matrix.transformXY(&vertices[0], &vertices[0], (int) vertices.size()); size_t voffset = vert_offset; if (!t.append_vertices) { voffset = 0; draw_commands.clear(); text_data.clear(); } uploadVertices(vertices, voffset); if (!new_commands.empty()) { // The start vertex should be adjusted to account for the vertex offset. for (Font::DrawCommand &cmd : new_commands) cmd.startvertex += (int) voffset; auto firstcmd = new_commands.begin(); // If the first draw command in the new list has the same texture as the // last one in the existing list we're building and its vertices are // in-order, we can combine them (saving a draw call.) if (!draw_commands.empty()) { auto prevcmd = draw_commands.back(); if (prevcmd.texture == firstcmd->texture && (prevcmd.startvertex + prevcmd.vertexcount) == firstcmd->startvertex) { draw_commands.back().vertexcount += firstcmd->vertexcount; ++firstcmd; } } // Append the new draw commands to the list we're building. draw_commands.insert(draw_commands.end(), firstcmd, new_commands.end()); } vert_offset = voffset + vertices.size(); text_data.push_back(t); text_data.back().text_info = text_info; // Font::generateVertices can invalidate the font's texture cache. if (font->getTextureCacheID() != texture_cache_id) regenerateVertices(); }