The rendering performance of VTK is lower than that of QOpenGLWidget. How can I improve VTK’s display performance?
Background:
I am using Qt + VTK to display point cloud data, with the final deployment on Linux (but tested on Windows during development).
Testing shows that on both Linux and Windows,
when using the SimpleView example code (which utilizes vtkGenericOpenGLRenderWindow
and QVTKRenderWidget
), loading 10 million points results in lag during rotation.
In contrast, using QOpenGLWidget to load the same 10 million points achieves smooth rotation.
- The data used is in OBJ format, but only contains vertices (no normals/colors).
- The number of points is confirmed identical in both cases.
Questions:
-
How can I make VTK rotate faster?
*mapper->SetVBOShiftScaleMethod(vtkPolyDataMapper::DISABLE_SHIFT_SCALE);
*actor->GetProperty()->SetLighting(false);
I’ve tried both methods mentioned above, but they didn’t improve performance. -
Why is VTK significantly slower than native QOpenGLWidget?
If no solution exists, I may have to downsample the data, though I prefer to avoid downsampling.
Thank you for your help!
QOpenGLWidget
VTK
The main code related to QOpenGLWidget is as follows:
void GenericRender::initsize(QString filename)
{
program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, R"(vsrc.vert)");
program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, R"(fsrc.frag)");
program_.link();
ObjLoader objModelLoader;
objModelLoader.load(filename,vertPoints_);
QVector<float> points;
points << vertPoints_ ;
vbo_.create();
vbo_.bind();
vbo_.allocate(points.data(),points.count() * sizeof(float));
}
void GenericRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix, QVector3D &cameraLocation, QVector3D &lightCation)
{
f->glEnable(GL_DEPTH_TEST);
program_.bind();
vbo_.bind();
program_.setUniformValue("uPMatrix",pMatrix);
program_.setUniformValue("uVMatrix",vMatrix);
program_.setUniformValue("uMMatrix",mMatrix);
program_.setUniformValue("uLightLocation",lightCation);
program_.setUniformValue("uCamera",cameraLocation);
program_.enableAttributeArray(0);
program_.setAttributeBuffer(0,GL_FLOAT,0,3,3*sizeof(GLfloat));
f->glDrawArrays(GL_POINTS,0,vertPoints_.count()/3);
program_.disableAttributeArray(0);
vbo_.release();
program_.release();
f->glDisable(GL_DEPTH_TEST);
}
vsrc.vert
windows: #version 330
linux: #version 320 es
#version 330
uniform mediump mat4 uPMatrix,uVMatrix,uMMatrix;
uniform mediump vec3 uLightLocation,uCamera;
layout (location = 0) in mediump vec3 aPosition;
void pointLight(in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular,in vec4 lightAmbient,in vec4 lightDiffuse,in vec4 lightSpecular,in float shininess){
ambient = lightAmbient;
vec3 normalTarget = aPosition + normal;
vec3 newNormal = normalize((uMMatrix * vec4(normalTarget,1)).xyz - (uMMatrix * vec4(aPosition,1)).xyz);
vec3 eye = normalize(uCamera - (uMMatrix * vec4(aPosition,1)).xyz);
vec3 vp = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);
vec3 halfVector = normalize(eye + vp);
float nDotViewPotision = max(0.0,dot(newNormal,vp));
diffuse = lightDiffuse * nDotViewPotision;
float nDotViewHalfVector = dot(newNormal,halfVector);
float powerFactor = max(0.0,pow(nDotViewHalfVector,shininess));
specular = lightSpecular * powerFactor;
}
void main(void)
{
gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);
}
fsrc.frag
windows: #version 330
linux: #version 320 es
#version 330
out mediump vec4 fragColor;
void main(void)
{
fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
The main code related to VTK is as follows:
vtkSmartPointer<vtkOBJReader> reader = vtkSmartPointer<vtkOBJReader>::New();
reader->SetFileName(R"(data.obj)");
reader->Update();
// Mapper
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(reader->GetOutput());
// Actor in scene
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
// VTK Renderer
vtkNew<vtkRenderer> ren;
// Add Actor to renderer
ren->AddActor(actor);
// VTK/Qt wedded
vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
this->ui->qvtkWidget->setRenderWindow(renderWindow);
this->ui->qvtkWidget->renderWindow()->AddRenderer(ren);