2015-04-12 353 views
2

我想在QOpenGLWidget上繪製文本標籤。我試圖用QPainter來完成這項任務,但沒有成功 - 文本看起來很醜並且沒有反鋸齒。在Qt OpenGL/2dpainting示例中,它看起來也很醜陋。然而,在也使用OpenGL後端的QML控件中,文本渲染效果更好。這裏http://blog.qt.io/blog/2011/07/15/text-rendering-in-the-qml-scene-graph/我發現了一種在QML中使用的技術。有沒有辦法使用這種技術在QOpenGLWidget中繪製文本?Qt:QOpenGLWidget中的文本渲染

PS:可能正確的方法是將我所有的場景嵌入到QQuickWidget的QSGSceneGraph中?

回答

2

確保您創建QGL/QopenGLWidget與表面格式,支持多重採樣抗鋸齒:

QSurfaceFormat format = QSurfaceFormat::defaultFormat(); 
format.setSamples(4); 
QOpenGLWidget * glWidget = new QOpenGLWidget; 
glWidget->setFormat(format); 

然後,使用對窗口部件的QPainter時,一定要開啓抗鋸齒:

QPainter painter(paintDevice); 
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); 

然後畫你的文字。

1

重新實現舊的QOGLWidget的renderText()以方便文本渲染。 這種方式文本將隨場景一起移動。如果你想要一個靜態版本,你可以簡化它。

從QOpenGLWidget繼承一個類(在本例中是GLBox)以下方法:

renderText:

void GLBox::renderText(D3DVECTOR &textPosWorld, QString text) 
{ 
    int width = this->width(); 
    int height = this->height(); 

    GLdouble model[4][4], proj[4][4]; 
    GLint view[4]; 
    glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]); 
    glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]); 
    glGetIntegerv(GL_VIEWPORT, &view[0]); 
    GLdouble textPosX = 0, textPosY = 0, textPosZ = 0; 

    project(textPosWorld.x, textPosWorld.y, textPosWorld.z, 
       &model[0][0], &proj[0][0], &view[0], 
       &textPosX, &textPosY, &textPosZ); 

    textPosY = height - textPosY; // y is inverted 

    QPainter painter(this); 
    painter.setPen(Qt::yellow); 
    painter.setFont(QFont("Helvetica", 8)); 
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); 
    painter.drawText(textPosX, textPosY, text); // z = pointT4.z + distOverOp/4 
    painter.end(); 
} 

項目:

inline GLint GLBox::project(GLdouble objx, GLdouble objy, GLdouble objz, 
    const GLdouble model[16], const GLdouble proj[16], 
    const GLint viewport[4], 
    GLdouble * winx, GLdouble * winy, GLdouble * winz) 
{ 
    GLdouble in[4], out[4]; 

    in[0] = objx; 
    in[1] = objy; 
    in[2] = objz; 
    in[3] = 1.0; 
    transformPoint(out, model, in); 
    transformPoint(in, proj, out); 

    if (in[3] == 0.0) 
     return GL_FALSE; 

    in[0] /= in[3]; 
    in[1] /= in[3]; 
    in[2] /= in[3]; 

    *winx = viewport[0] + (1 + in[0]) * viewport[2]/2; 
    *winy = viewport[1] + (1 + in[1]) * viewport[3]/2; 

    *winz = (1 + in[2])/2; 
    return GL_TRUE; 
} 

終於transformPoint:

inline void GLBox::transformPoint(GLdouble out[4], const GLdouble m[16], const GLdouble in[4]) 
{ 
#define M(row,col) m[col*4+row] 
    out[0] = 
     M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3]; 
    out[1] = 
     M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3]; 
    out[2] = 
     M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3]; 
    out[3] = 
     M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3]; 
#undef M 
}