0
\$\begingroup\$

How can I speed up the drawing of my points in OpenGL on Windows?

I have an Qt 5.9.1 app that shows real time Lidar data, so at a certain frequency I add points to my buffer (which I've overloaded to act as a circular buffer.)

On linux, everything is great, all my renderers combined (my lidar points, my 3D models, etc) render in a small fraction of a 60 FPS frame. On Windows however, rendering the lidar points takes almost the time of two 60 FPS frames. I measured this put inserting glFlush() and glFinish() after the glDrawArrays() calls.

My buffer size is about ~1/2 a million points. I'm trying to show points that could span several km, but are usually confined to 1 km - I mention this because right now I'm not doing any explicit frustum culling.

My process is:

  • Load new points from a vector into my overloaded circular OpenGL buffer. Each point is 20 bytes (position, intensity, ..)
  • Write all my uniform variables (MVP matrix, etc)
  • Call glDrawArrays
  • Then there's a vertex shader that just passes data through
  • A geometry shader that instances the points for each viewport (3)
  • A fragment shader that colours the points by elevation.

Explicitly:

Initialize:

auto LidarRenderer::initPointShaders() -> void
{
    point_opengl_buffer_.setUsagePattern(QOpenGLBuffer::DynamicDraw);
    initializeOpenGLFunctions();

    // Setup our vertex buffer object.
    point_opengl_buffer_.create();

    render_program_ = make_unique<QOpenGLShaderProgram>();

    // Vertex shader pretty much just passes points through
    render_program_->addShaderFromSourceFile(QOpenGLShader::Vertex,   vertex_shader_);
    render_program_->addShaderFromSourceFile(QOpenGLShader::Geometry, geo_shader_);
    render_program_->addShaderFromSourceFile(QOpenGLShader::Fragment, fragment_shader_);

    render_program_->link();
    render_program_->bind();

    // Store the vertex attribute bindings for the program.
    {
        // Create our QOpenGLVertexArrayObject
        vao_.create();
        QOpenGLVertexArrayObject::Binder vaoBinder(&vao_);

        // Bind out buffer
        point_opengl_buffer_.bind();

        glEnableVertexAttribArray(0);
        // Vertex position data, send to location = 0, 3 floats per position,
        // not normalized, stride of 20 bytes, no offset
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, 0);

        glEnableVertexAttribArray(1);
        // Vertex intensity data, send to location = 1, 1 int, stride of 20
        // bytes, 12 byte offset
        glVertexAttribIPointer(1, 1, GLint, 20, 12);

        // ...

        point_opengl_buffer_.release();
    }

    render_program_->release();
}

Load new points (write to buffer):

auto LidarRenderer::loadNewPoints() -> void
{
    if (!point_opengl_buffer_.bind()) return;

    auto point_count = tmp_buffer_.size();

    // Transform the points into the proper frame
    std::transform(tmp_buffer_.begin(), tmp_buffer_.end(), tmp_buffer_.begin(),
        [&my_nav_offset_vector_](const RegisterPoint& p) { return p - my_nav_offset_vector_; });

    point_opengl_buffer_.write(&tmp_buffer_[0], static_cast<unsigned int>(point_count * sizeof(RegisterPoint)));
    point_opengl_buffer_.release();

    // Clean our vector
    tmp_buffer_.clear();
} 

Paint:

auto LidarRenderer::paintGL() -> void
{
    QOpenGLVertexArrayObject::Binder vaoBinder(&vao_);
    render_program_->bind();

    // Draw all the ground points in the buffer
    glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(point_opengl_buffer_.CountVertices()));

    render_program_->release();
}

Does anything in that code look wrong? Is there a way to possibly speed up the rendering? (I should mention that I'm still an OpenGL beginner.)

\$\endgroup\$
  • 1
    \$\begingroup\$ Don't disable and enable blending every frame, only do it when you start the program \$\endgroup\$ – Bálint Sep 23 '17 at 16:06
  • \$\begingroup\$ Oh, I was actually doing it in each renderer that I needed blending on. Cool, I'll take it out, thanks! Is that something that would take significant time though? (I won't have access to a windows computer to time it on until Monday.) \$\endgroup\$ – Matt Sep 23 '17 at 16:08
  • 2
    \$\begingroup\$ Sometimes, but even if it doesn't, it makes the code a whole lot more readable \$\endgroup\$ – Bálint Sep 23 '17 at 16:31
  • \$\begingroup\$ What hardware have you? Remember, OpenGL is not a software library that depends on the OS. \$\endgroup\$ – Maximus Minimus Sep 23 '17 at 20:50
  • \$\begingroup\$ I'm not 100% sure, I'll check Monday morning. What seems odd is that both my Linux boxes render this without issue, but my Windows 10 Dell Latitude laptop and my Windows Surface both render it very slowly. It could just be a coincidence though. And when I search for help, I find forum messages from the early/mid 2000s where people are rendering millions of elements. \$\endgroup\$ – Matt Sep 24 '17 at 0:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.