Как визуализировать некоторые вершины в буфере как точки, а остальные, используя линии в qopenglwidget?
У меня есть набор вершин и нормалей, хранящихся в буфере. Я хочу отобразить большинство вершин в виде точек, но я хочу нарисовать линии для оставшихся нескольких вершин. Все они хранятся внутри одного вектора с частью точек спереди, и я знаю местоположение буфера, пока они не будут отображены с использованием точек. Я также знаю количество элементов для каждой задачи рисования. Для этой задачи я использую только один объект vao и один буфер.
Я инициализирую GLWidget с помощью следующего кода:
void GLWidget::initializeGL()
{
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);
initializeOpenGLFunctions();
glClearColor(0, 0, 0, m_transparent ? 0 : 1);
m_program = new QOpenGLShaderProgram;
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_core ? fragmentShaderSourceCore : fragmentShaderSource);
m_program->bindAttributeLocation("vertex", 0);
m_program->bindAttributeLocation("normal", 1);
m_program->link();
m_program->bind();
m_projMatrixLoc = m_program->uniformLocation("projMatrix");
m_mvMatrixLoc = m_program->uniformLocation("mvMatrix");
m_normalMatrixLoc = m_program->uniformLocation("normalMatrix");
m_lightPosLoc = m_program->uniformLocation("lightPos");
m_vao.create();
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
m_obj.create();
setupBuffer();
setupVertexAttribs();
m_camera.setToIdentity();
QVector3D camPos = QVector3D(0.0, 0.0, 15.0);
m_camera.translate(-camPos);
QVector3D camTarget = QVector3D(0.0, 0.0, 0.0);
QVector3D camDirection = QVector3D(camPos - camTarget).normalized();
QVector3D worldUp = QVector3D(0.0, 1.0, 0.0);
QVector3D camRight = QVector3D::crossProduct(worldUp, camDirection).normalized();
QVector3D camUp = QVector3D::crossProduct(camDirection, camRight);
m_camera.lookAt(camPos, camTarget, camUp);
// Light position is fixed.
m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 200));
m_program->release();
}
Где функции setupBuffer() setupVertexAtrribs() выполняют те же задачи, что и их имена. Вершины располагаются в буфере с позициями xyz вершины, за которыми следует xyz соответствующей нормали. Они реализованы следующим образом
void GLWidget::setupBuffer()
{
m_obj.bind();
m_obj.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
}
void GLWidget::setupVertexAttribs()
{
m_obj.bind();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(0));
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
m_obj.release();
}
Теперь вершины QVector - это буфер, который передается в opengl. Последние несколько записей в этом векторе - это вершины, которые нужно нарисовать с помощью GL_LINES.
Моя функция paintGL() выглядит примерно так:
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_POINT_SIZE);
glEnable(GL_LINE_WIDTH);
glPointSize(2);
glLineWidth(10);
m_world.setToIdentity();
m_world.rotate(180.0f - (m_xRot / 16.0f), 1, 0, 0);
m_world.rotate(m_yRot / 16.0f, 0, 1, 0);
m_world.rotate(m_zRot / 16.0f, 0, 0, 1);
m_world.scale(m_dispScale);
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
m_program->bind();
m_program->setUniformValue(m_projMatrixLoc, m_proj);
m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world);
QMatrix3x3 normalMatrix = m_world.normalMatrix();
m_program->setUniformValue(m_normalMatrixLoc, normalMatrix);
glDrawArrays(GL_POINTS, 0, vertices.size() - camVertices.size());
// Draw camera frustums
glDrawArrays(GL_LINES, vertices.size() - camVertices.size(), camVertices.size());
//glDrawElements(GL_POINTS, vecIndices.size(), GL_UNSIGNED_INT, 0);
m_program->release();
}
QVector camVertices - это еще один вектор, содержащий точки, которые необходимо нарисовать с использованием линий. Данные в camVertices добавляются в конец вектора "Вершины" перед рендерингом. Как видно из приведенного выше кода, я вызываю функцию glDrawArrays дважды - во-первых, начиная с 0 индекса буфера, во-вторых, начиная с того места, где завершился предыдущий вызов, чтобы отобразить оставшиеся точки.
Проблема в том, что точки отображаются нормально. Однако второй вызов отображает только точки, но не рисует никаких линий.
Вот ссылка на снимок экрана с отображаемым выводом - https://drive.google.com/open?id=1i7CjO1qkBALw78KKYGvBteydhfAWh3wh
На рисунке показан пример отображения, где ярко-зеленые точки, видимые на верхних участках от остальных (прямоугольник с множеством точек), - это те, которые должны быть нарисованы линиями. Однако я вижу только точки, но не линии.
1 ответ
Я сделал простой тест, и я могу рисовать точки и линии, используя следующий код:
glDrawArrays(GL_POINTS, 0, verticesCount() - 10); glDrawArrays(GL_LINES, 10, 10);
Который не сильно отличается от вашего, за исключением переменных. Я также использую 1 ВАО. Так что, безусловно, можно рисовать линии после точек, как мы и ожидали.
Не могли бы вы попробовать то же самое (используя целое число вместо ваших переменных)
Можете ли вы показать отладочную информацию на ваших вершинах?
Можете ли вы загрузить минимальный компилируемый пример?