我用它来渲染QGLWidget中的文本
QGLWidget::renderText(x, y, z, text, font)
字符串的渲染深度为~0.5(通过glReadPixel()获得)。
然而,在我的情况下它应该更接近~0.9。 当我将x,y,z coords转换为与当前矩阵的屏幕坐标时,我也发现〜0.9的结果。
为什么会出现这样的差异?它使文本始终显示在前面。
我在visual studio中创建了一个简单的QT项目来重现这个问题。 它绘制了一个绿色方块,正方形前后有文字。两个文字都看在广场前面。并且可以通过悬停鼠标来读取像素的深度。
我使用为64位平台构建的Qt 5.5版。
MyGLWidget.h
#include <QGLWidget>
#include <QMouseEvent>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
private:
float _depth;
public:
MyGLWidget(QWidget * parent = 0);
virtual ~MyGLWidget();
virtual void initializeGL();
virtual void paintGL();
void mouseMoveEvent(QMouseEvent * event);
signals:
void depthRead(float);
};
MyGLWidget.cpp
#include "MyGLWidget.h"
#include <gl/GLU.h>
#include <Qfont>
MyGLWidget::MyGLWidget(QWidget * parent) : QGLWidget(parent)
{
}
MyGLWidget::~MyGLWidget()
{
}
void MyGLWidget::initializeGL()
{
}
void MyGLWidget::paintGL()
{
// set up projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float width = this->width();
float height = this->height();
glViewport(0, 0, width, height);
gluPerspective(45, width / height, 1, 100);
// set up model view
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,5, // eye
0,0,0, // look at
0,1,0); // up
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
// draw a green square
glColor4f(0,1,0,1);
glBegin(GL_QUADS);
glVertex3f(-1,-1,0);
glVertex3f(1,-1,0);
glVertex3f(1,1,0);
glVertex3f(-1,1,0);
glEnd();
// render some blue text behind the square
QFont font;
font.setPointSize(20);
glColor4f(0,0,1,1);
renderText(-2,-0.5,-1, "BEHIND_BEHIND_BEHIND_BEHIND", font);
// render some red text in front of the square
glColor4f(1,0,0,1);
renderText(-2,0.5,+1, "IN_FRONT_IN_FRONT_IN_FRONT_I", font);
}
void MyGLWidget::mouseMoveEvent(QMouseEvent * event)
{
int x = event->x();
// flip y for QT origin is top left while OpenGL origin is bottom left
int y = this->height() - event->y();
// read pixel depth
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &_depth);
// update ui
emit depthRead(_depth);
}
rendertexttest.h
#ifndef RENDERTEXTTEST_H
#define RENDERTEXTTEST_H
#include <QtWidgets/QMainWindow>
#include "ui_rendertexttest.h"
#include "MyGLWidget.h"
class RenderTextTest : public QMainWindow
{
Q_OBJECT
public:
RenderTextTest(QWidget *parent = 0);
~RenderTextTest();
public slots:
void onDepthRead(float depth);
private:
Ui::RenderTextTestClass ui;
MyGLWidget * _glwidget;
};
#endif // RENDERTEXTTEST_H
rendertexttest.cpp
#include "rendertexttest.h"
RenderTextTest::RenderTextTest(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
_glwidget = new MyGLWidget(this);
_glwidget->setMouseTracking(true);
QObject::connect(_glwidget, SIGNAL(depthRead(float)),
this, SLOT(onDepthRead(float)));
ui._mainLayout->addWidget(_glwidget);
}
RenderTextTest::~RenderTextTest()
{
}
void RenderTextTest::onDepthRead(float depth)
{
ui._lblDepth->setText(QString::number(depth));
}
ui_rendertexttest.h
/********************************************************************************
** Form generated from reading UI file 'rendertexttest.ui'
**
** Created by: Qt User Interface Compiler version 5.3.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_RENDERTEXTTEST_H
#define UI_RENDERTEXTTEST_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_RenderTextTestClass
{
public:
QWidget *centralWidget;
QWidget *verticalLayoutWidget;
QVBoxLayout *_mainLayout;
QLabel *_lblDepth;
void setupUi(QMainWindow *RenderTextTestClass)
{
if (RenderTextTestClass->objectName().isEmpty())
RenderTextTestClass->setObjectName(QStringLiteral("RenderTextTestClass"));
RenderTextTestClass->resize(600, 438);
centralWidget = new QWidget(RenderTextTestClass);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
verticalLayoutWidget = new QWidget(centralWidget);
verticalLayoutWidget->setObjectName(QStringLiteral("verticalLayoutWidget"));
verticalLayoutWidget->setGeometry(QRect(9, 9, 581, 381));
_mainLayout = new QVBoxLayout(verticalLayoutWidget);
_mainLayout->setSpacing(6);
_mainLayout->setContentsMargins(11, 11, 11, 11);
_mainLayout->setObjectName(QStringLiteral("_mainLayout"));
_mainLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
_mainLayout->setContentsMargins(0, 0, 0, 0);
_lblDepth = new QLabel(centralWidget);
_lblDepth->setObjectName(QStringLiteral("_lblDepth"));
_lblDepth->setGeometry(QRect(10, 410, 581, 16));
RenderTextTestClass->setCentralWidget(centralWidget);
retranslateUi(RenderTextTestClass);
QMetaObject::connectSlotsByName(RenderTextTestClass);
} // setupUi
void retranslateUi(QMainWindow *RenderTextTestClass)
{
RenderTextTestClass->setWindowTitle(QApplication::translate("RenderTextTestClass", "RenderTextTest", 0));
_lblDepth->setText(QApplication::translate("RenderTextTestClass", "Depth:", 0));
} // retranslateUi
};
namespace Ui {
class RenderTextTestClass: public Ui_RenderTextTestClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_RENDERTEXTTEST_H
答案 0 :(得分:0)
可能有3个问题
1-目标深度在QGLWidget :: renderText()中正确计算,并通过setTranslateZ()传递给paintEngine。但是,顶点着色器不会直接在顶点剪切坐标中设置此值。相反,它会转换为此值。
2- translateZ的标志似乎不正确。这可以解释为什么当文本靠近时文本像素的深度会增加。
3-似乎剪切的坐标[0,1]被映射到范围[0.5,1]但是我没有在Qt的源中看到对glDepthRange()的任何调用。
如果我们使用以下内容更改qglengineshadersource_p.h中的qglslComplexGeometryPositionOnlyVertexShader的代码,则可以解决问题。
static const char* const qglslComplexGeometryPositionOnlyVertexShader = "\n\
uniform highp mat3 matrix; \n\
uniform highp float translateZ; \n\
attribute highp vec2 vertexCoordsArray; \n\
void setPosition(void) \n\
{ \n\
vec3 v = matrix * vec3(vertexCoordsArray, 1.0); \n\
v.z = (-translateZ - 0.5f) * 2.0f; \n\
gl_Position = vec4(v.xyz, 1.0);\n\
} \n";
答案 1 :(得分:0)
我发现一个很好的解决方法是将文本渲染为纹理。然后在场景中显示该纹理。
如果文本在纯色背景上呈现,则效果很好。 QGLWidget似乎没有写入alpha通道。