Я использую код для рисования текста в виде текстур в OpenGL (Qt4.8.3 + Linux (debian-like)). Код был перенесен из 2D проекта, где он работает хорошо.
2D-проект использовал gluOrtho2D, теперь я использую gluLookAt для 3D.
Проблема заключается в том, что вместо текста я использую цветной прямоугольник. Если я включу GL_DEPTH_TEST, я вижу артефакты вместо текста. Артефакты BTW меняются, если я перемещаю камеру, что довольно странно.
Здесь код:
void GLWidget::paintGL() {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set blending function.
glEnable(GL_BLEND); //Enable blending.
glShadeModel(GL_SMOOTH);
glEnable(GL_MULTISAMPLE);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60.0f, (GLdouble) width() / (GLdouble) height(), 0.001f, 10000.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// Set up current camera
gluLookAt( cameraDistance * sin(cameraTheta * M_PI / 180) * cos(cameraPhi * M_PI / 180),
cameraDistance * sin(cameraTheta * M_PI / 180) * sin(cameraPhi * M_PI / 180),
cameraDistance * cos(cameraTheta * M_PI / 180),
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
glTranslatef(-4.5355, -4.5355, 0.0);
glPushMatrix();
// draw text labels
drawLabel(1, 0, 90, "1");
drawLabel(2, 0, 90, "2");
drawLabel(3, 0, 90, "3");
drawLabel(4, 0, 90, "4");
drawLabel(5, 0, 90, "5");
glPopMatrix();
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glPopMatrix();
}
void GLWidget::drawLabel(float xpos, float ypos, float angle, char *txt) {
float labelHeight = 0.3;
float labelWidth = labelHeight / 2;
float margin = labelWidth / 10;
float len = (float) strlen(txt);
glPushMatrix();
glRotatef(-angle, 0, 0, -1);
glTranslatef(xpos, ypos, 0.0f);
glRotatef(angle, 0, 0, -1);
glScalef(1.0, -1.0, 1.0);
glTranslatef(- len * labelWidth / 2, -labelHeight / 2 + margin, 0.0f);
// background
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-margin, -margin, 0);
glVertex3f(len * labelWidth + margin, -margin, 0);
glVertex3f(len * labelWidth + margin, labelHeight + margin, 0);
glVertex3f(-margin, labelHeight + margin, 0);
glEnd();
// text
glColor3f(0.5f, 0.5f, 0.5f);
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, glFont->getTextureID() );
glFont->drawText(labelWidth, labelHeight, txt);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
void oglFont::drawText(GLfloat cw, GLfloat ch, char *txt)
{
glBegin(GL_QUADS);
//character location and dimensions
GLfloat cx = 0.0f;
GLfloat cy = 0.0f;
//calculate how wide each character is in term of texture coords
GLfloat dtx = float(c_width) / float(m_width);
GLfloat dty = float(c_height) / float(m_height);
for (char * c = txt; *c != 0; c++, cx += cw) {
int index = getCharIndex(c);
int row = index / c_per_row;
int col = index % c_per_row;
if (index < 0) {
//qDebug() << "glFont: Character outside of font! char: " << c;
}
// find the texture coords
GLfloat tx = float(col * c_width) / float(m_width);
GLfloat ty = float(row * c_height) / float(m_height);
glTexCoord2f(0, 0);
glVertex2f(cx, cy);
glTexCoord2f(1, 0);
glVertex2f(cx + cw, cy);
glTexCoord2f(1, 1);
glVertex2f(cx + cw, cy + ch);
glTexCoord2f(0, 1);
glVertex2f(cx, cy + ch);
}
glEnd();
}
Оказывается, поскольку текстура загружалась в конструктор QGLWidget, контекст был либо не создан, либо не установлен.
Я переместил загрузку текстуры в метод initializeGL(), и он отлично работает.
Причиной артефактов является борьба Z.
Эта проблема может быть решена путем увеличения точности буфера глубины ИЛИ путем выделения разных объектов отдельно друг от друга (те, которые отрывны).
Также убедитесь, что ваш сгенерированный текст не отбирается плоской/ближней плоскостью (возможно, вы создаете геометрию очень близко к краям?).