/// @overload QGLWidget void paintGL(){ vao.bind(); program.bind(); { ///--- Update modelview #ifdef WITH_QGLVIEWER /// use the trackball to specify the matrices setup_modelview(camera(), program); #else ///--- simple unit cube orthographic view static Eigen::Matrix4f M = Eigen::Matrix4f::Identity(); static Eigen::Matrix4f P = Eigen::ortho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f); static Eigen::Matrix4f V = Eigen::Matrix4f::Identity(); static Eigen::Matrix4f MV = V*M; static Eigen::Matrix4f MVP = P*MV; GLint MVP_id = glGetUniformLocation(program.programId(), "MVP"); glUniformMatrix4fv(MVP_id, 1, GL_FALSE, MVP.data()); GLint MV_id = glGetUniformLocation(program.programId(), "MV"); glUniformMatrix4fv(MV_id, 1, GL_FALSE, MV.data()); #endif ///--- clear & draw glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glDrawElements(GL_TRIANGLES, triangles.size(), GL_UNSIGNED_INT, 0); } vao.release(); program.release(); }
static void drawTree(QGLShaderProgram& prog, const TransformState& transState, const OctreeNode* node) { Imath::Box3f bbox(node->center - Imath::V3f(node->halfWidth), node->center + Imath::V3f(node->halfWidth)); drawBox(transState, bbox, Imath::C3f(1), prog.programId()); drawBox(transState, node->bbox, Imath::C3f(1,0,0), prog.programId()); for (int i = 0; i < 8; ++i) { OctreeNode* n = node->children[i]; if (n) drawTree(prog, transState, n); } }
void Annotation::draw(QGLShaderProgram& annotationShaderProg, const TransformState& transState) const { glBindVertexArray(m_vao); GLint texture0 = glGetUniformLocation(annotationShaderProg.programId(), "texture0"); m_texture->bind(texture0); annotationShaderProg.setUniformValue("annotationSize", m_texture->width(), m_texture->height()); transState.translate(m_position) .setUniforms(annotationShaderProg.programId()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); glBindVertexArray(0); }
void TriMesh::drawFaces(QGLShaderProgram& prog, const TransformState& transState) const { // TODO: The hasTexture uniform shader variable would be unnecessary if we // supported more than one mesh face shader... GLint hasTextureLoc = glGetUniformLocation(prog.programId(), "hasTexture"); if (m_texture) { GLint textureSamplerLoc = glGetUniformLocation(prog.programId(), "texture0"); if (textureSamplerLoc != -1) m_texture->bind(textureSamplerLoc); } if (hasTextureLoc != -1) glUniform1i(hasTextureLoc, m_texture ? 1 : 0); unsigned int vertexShaderId = shaderId("meshface"); unsigned int vertexArray = getVAO("meshface"); transState.translate(offset()).setUniforms(vertexShaderId); glBindVertexArray(vertexArray); glDrawElements(GL_TRIANGLES, (GLsizei)m_triangles.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); }
void TriMesh::drawEdges(QGLShaderProgram& prog, const TransformState& transState) const { transState.translate(offset()).setUniforms(prog.programId()); prog.enableAttributeArray("position"); prog.setAttributeArray("position", GL_FLOAT, &m_verts[0], 3); if (m_colors.size() == m_verts.size()) { prog.enableAttributeArray("color"); prog.setAttributeArray("color", GL_FLOAT, &m_colors[0], 3); } else prog.setAttributeValue("color", GLfloat(1), GLfloat(1), GLfloat(1)); glDrawElements(GL_LINES, (GLsizei)m_edges.size(), GL_UNSIGNED_INT, &m_edges[0]); prog.disableAttributeArray("color"); prog.disableAttributeArray("position"); }
DrawCount PointArray::drawPoints(QGLShaderProgram& prog, const TransformState& transState, double quality, bool incrementalDraw) const { TransformState relativeTrans = transState.translate(offset()); relativeTrans.setUniforms(prog.programId()); //printActiveShaderAttributes(prog.programId()); std::vector<ShaderAttribute> activeAttrs = activeShaderAttributes(prog.programId()); // Figure out shader locations for each point field // TODO: attributeLocation() forces the OpenGL usage here to be // synchronous. Does this matter? (Alternative: bind them ourselves.) std::vector<const ShaderAttribute*> attributes; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField& field = m_fields[i]; if (field.spec.isArray()) { for (int j = 0; j < field.spec.count; ++j) { std::string name = tfm::format("%s[%d]", field.name, j); attributes.push_back(findAttr(name, activeAttrs)); } } else { attributes.push_back(findAttr(field.name, activeAttrs)); } } // Zero out active attributes in case they don't have associated fields GLfloat zeros[16] = {0}; for (size_t i = 0; i < activeAttrs.size(); ++i) { prog.setAttributeValue((int)i, zeros, activeAttrs[i].rows, activeAttrs[i].cols); } // Enable attributes which have associated fields for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.enableAttributeArray(attributes[i]->location); } DrawCount drawCount; ClipBox clipBox(relativeTrans); // Draw points in each bucket, with total number drawn depending on how far // away the bucket is. Since the points are shuffled, this corresponds to // a stochastic simplification of the full point cloud. V3f relCamera = relativeTrans.cameraPos(); std::vector<const OctreeNode*> nodeStack; nodeStack.push_back(m_rootNode.get()); while (!nodeStack.empty()) { const OctreeNode* node = nodeStack.back(); nodeStack.pop_back(); if (clipBox.canCull(node->bbox)) continue; if (!node->isLeaf()) { for (int i = 0; i < 8; ++i) { OctreeNode* n = node->children[i]; if (n) nodeStack.push_back(n); } continue; } size_t idx = node->beginIndex; if (!incrementalDraw) node->nextBeginIndex = node->beginIndex; DrawCount nodeDrawCount = node->drawCount(relCamera, quality, incrementalDraw); drawCount += nodeDrawCount; idx = node->nextBeginIndex; if (nodeDrawCount.numVertices == 0) continue; for (size_t i = 0, k = 0; i < m_fields.size(); k+=m_fields[i].spec.arraySize(), ++i) { const GeomField& field = m_fields[i]; int arraySize = field.spec.arraySize(); int vecSize = field.spec.vectorSize(); for (int j = 0; j < arraySize; ++j) { const ShaderAttribute* attr = attributes[k+j]; if (!attr) continue; char* data = field.data.get() + idx*field.spec.size() + j*field.spec.elsize; if (attr->baseType == TypeSpec::Int || attr->baseType == TypeSpec::Uint) { glVertexAttribIPointer(attr->location, vecSize, glBaseType(field.spec), 0, data); } else { glVertexAttribPointer(attr->location, vecSize, glBaseType(field.spec), field.spec.fixedPoint, 0, data); } } } glDrawArrays(GL_POINTS, 0, (GLsizei)nodeDrawCount.numVertices); node->nextBeginIndex += nodeDrawCount.numVertices; } //tfm::printf("Drew %d of total points %d, quality %f\n", totDraw, m_npoints, quality); // Disable all attribute arrays - leaving these enabled seems to screw with // the OpenGL fixed function pipeline in unusual ways. for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.disableAttributeArray(attributes[i]->location); } return drawCount; }
DrawCount PointArray::drawPoints(QGLShaderProgram& prog, const TransformState& transState, double quality, bool incrementalDraw) const { GLuint vao = getVAO("points"); glBindVertexArray(vao); GLuint vbo = getVBO("point_buffer"); glBindBuffer(GL_ARRAY_BUFFER, vbo); TransformState relativeTrans = transState.translate(offset()); relativeTrans.setUniforms(prog.programId()); //printActiveShaderAttributes(prog.programId()); std::vector<ShaderAttribute> activeAttrs = activeShaderAttributes(prog.programId()); // Figure out shader locations for each point field // TODO: attributeLocation() forces the OpenGL usage here to be // synchronous. Does this matter? (Alternative: bind them ourselves.) std::vector<const ShaderAttribute*> attributes; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField& field = m_fields[i]; if (field.spec.isArray()) { for (int j = 0; j < field.spec.count; ++j) { std::string name = tfm::format("%s[%d]", field.name, j); attributes.push_back(findAttr(name, activeAttrs)); } } else { attributes.push_back(findAttr(field.name, activeAttrs)); } } // Zero out active attributes in case they don't have associated fields GLfloat zeros[16] = {0}; for (size_t i = 0; i < activeAttrs.size(); ++i) { prog.setAttributeValue((int)i, zeros, activeAttrs[i].rows, activeAttrs[i].cols); } // Enable attributes which have associated fields for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.enableAttributeArray(attributes[i]->location); } DrawCount drawCount; ClipBox clipBox(relativeTrans); // Draw points in each bucket, with total number drawn depending on how far // away the bucket is. Since the points are shuffled, this corresponds to // a stochastic simplification of the full point cloud. V3f relCamera = relativeTrans.cameraPos(); std::vector<const OctreeNode*> nodeStack; nodeStack.push_back(m_rootNode.get()); while (!nodeStack.empty()) { const OctreeNode* node = nodeStack.back(); nodeStack.pop_back(); if (clipBox.canCull(node->bbox)) continue; if (!node->isLeaf()) { for (int i = 0; i < 8; ++i) { OctreeNode* n = node->children[i]; if (n) nodeStack.push_back(n); } continue; } size_t idx = node->beginIndex; if (!incrementalDraw) node->nextBeginIndex = node->beginIndex; DrawCount nodeDrawCount = node->drawCount(relCamera, quality, incrementalDraw); drawCount += nodeDrawCount; idx = node->nextBeginIndex; if (nodeDrawCount.numVertices == 0) continue; if (m_fields.size() < 1) continue; long bufferSize = 0; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField &field = m_fields[i]; unsigned int arraySize = field.spec.arraySize(); unsigned int vecSize = field.spec.vectorSize(); // tfm::printfln("FIELD-NAME: %s", field.name); // tfm::printfln("AS: %i, VS: %i, FSS: %i, FSES: %i, GLBTFSS: %i", arraySize, vecSize, field.spec.size(), field.spec.elsize, sizeof(glBaseType(field.spec))); bufferSize += arraySize * vecSize * field.spec.elsize; //sizeof(glBaseType(field.spec)); } bufferSize = bufferSize * (GLsizei)nodeDrawCount.numVertices; // TODO: might be able to do something more efficient here, for example use glBufferSubData to avoid re-allocation of memory by glBufferData // INITIALIZE THE BUFFER TO FULL SIZE // tfm::printfln("INIT BUFFER: %i, BS: %i", vbo, bufferSize); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)bufferSize, NULL, GL_STREAM_DRAW); /// ======================================================================== /// ======================================================================== GLintptr bufferOffset = 0; for (size_t i = 0, k = 0; i < m_fields.size(); k+=m_fields[i].spec.arraySize(), ++i) { const GeomField& field = m_fields[i]; int arraySize = field.spec.arraySize(); int vecSize = field.spec.vectorSize(); // TODO: should use a single data-array that isn't split into vertex / normal / color / etc. sections, but has interleaved data ? // OpenGL has a stride value in glVertexAttribPointer for exactly this purpose, which should be used for better efficiency // here we write only the current attribute data into this the buffer (e.g. all positions, then all colors) bufferSize = arraySize * vecSize * field.spec.elsize * (GLsizei)nodeDrawCount.numVertices; //sizeof(glBaseType(field.spec)) char* bufferData = field.data.get() + idx*field.spec.size(); glBufferSubData(GL_ARRAY_BUFFER, bufferOffset, bufferSize, bufferData); // tfm::printfln("UPDATE BUFFER: %i, BS: %i", vbo, bufferSize); for (int j = 0; j < arraySize; ++j) { const ShaderAttribute* attr = attributes[k+j]; if (!attr) continue; // we have to create an intermediate buffer offsets for glVertexAttribPointer, but we can still upload the whole data array earlier !? GLintptr intermediate_bufferOffset = bufferOffset + j*field.spec.elsize; if (attr->baseType == TypeSpec::Int || attr->baseType == TypeSpec::Uint) { glVertexAttribIPointer(attr->location, vecSize, glBaseType(field.spec), 0, (const GLvoid *)intermediate_bufferOffset); } else { glVertexAttribPointer(attr->location, vecSize, glBaseType(field.spec), field.spec.fixedPoint, 0, (const GLvoid *)intermediate_bufferOffset); } glEnableVertexAttribArray(attr->location); } bufferOffset += bufferSize; } glDrawArrays(GL_POINTS, 0, (GLsizei)nodeDrawCount.numVertices); node->nextBeginIndex += nodeDrawCount.numVertices; } //tfm::printf("Drew %d of total points %d, quality %f\n", totDraw, m_npoints, quality); // Disable all attribute arrays - leaving these enabled seems to screw with // the OpenGL fixed function pipeline in unusual ways. for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.disableAttributeArray(attributes[i]->location); } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); return drawCount; }