OpenGL+GLUT水平滚动文本动画失效问题求助
问题分析与解决方案
你的代码里文本消失的核心问题在于矩阵变换没有正确管理,加上颜色值的错误设置,导致文本要么位置偏移出屏幕,要么颜色不对(比如全白或透明)。下面是具体的问题点和修复方案:
1. 修复矩阵变换的累积问题
在draw()函数中,你每次调用glTranslatef都会修改当前的模型视图矩阵,但没有在函数结束时恢复原来的矩阵状态。这意味着每次重绘时,平移操作会被叠加,文本的位置会越来越偏,最终超出屏幕范围。
解决方法:使用glPushMatrix()和glPopMatrix()来保存和恢复矩阵状态,确保每次draw的变换都是独立的。
2. 修正颜色值范围
OpenGL的glColor4f()函数要求颜色分量是0.0到1.0之间的浮点数,你原来写的255.0f会被自动截断为1.0,导致颜色和预期不符,甚至可能因为某些驱动的问题导致文本不可见。需要把RGB值归一化(除以255)。
3. 调整文本位置的计算逻辑
把glTranslatef的操作去掉,直接在glRasterPos2f里计算位置,避免矩阵变换干扰文本的光栅位置。
修正后的完整代码
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #ifdef WIN32 #include <windows.h> #endif #include <GL/gl.h> #include <GL/glut.h> using namespace std; static int font_index = 0; int state = 1; float x_pos = -200; float y_pos = 70; void print_bitmap_string(const char* s) { while (*s) { glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *s); s++; } } void my_reshape(int w, int h) { GLdouble size; GLdouble aspect; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); size = (GLdouble)((w >= h)? w : h) / 2.0; if (w <= h) { aspect = (GLdouble)h / (GLdouble)w; glOrtho(-size, size, -size * aspect, size * aspect, -100000.0, 100000.0); } else { aspect = (GLdouble)w / (GLdouble)h; glOrtho(-size * aspect, size * aspect, -size, size, -100000.0, 100000.0); } glScaled(aspect, aspect, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void draw() { const char* text = "Hello train"; // 保存当前矩阵状态 glPushMatrix(); // 修正颜色值:归一化到0-1范围 glColor4f(0.0f, 1.0f, 140.0f/255.0f, 1.0f); // 直接设置文本的光栅位置,不需要额外translate glRasterPos2f(x_pos, y_pos); print_bitmap_string(text); // 恢复之前的矩阵状态 glPopMatrix(); } void display(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); // 确保每次display都从初始矩阵开始 draw(); // 绘制测试用的多边形 glColor3f(0.0, 1.0, 0.0); glBegin(GL_POLYGON); glVertex2f(x_pos + 0.5f, 0.0f); glVertex2f(x_pos+1.0f, 0.5f); glVertex2f(x_pos+0.5f, 0.5f); glEnd(); glutSwapBuffers(); } void timer(int) { glutPostRedisplay(); glutTimerFunc(16, timer, 0); // 改成16ms左右,动画更流畅(约60帧) switch (state) { case 1: if (x_pos > -295) { x_pos -= 1; } else { state = -1; } break; case -1: x_pos = 180; state = 1; break; } cout << x_pos << endl; } int main(int argc, char** argv) { glutInitWindowSize(500, 150); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Train Display"); glutDisplayFunc(display); glutReshapeFunc(my_reshape); glutTimerFunc(0, timer, 0); // 立即启动定时器 glutMainLoop(); return 0; }
额外优化点
- 把定时器的间隔从1000ms改成16ms,这样动画会更流畅(接近60帧每秒)。
- 在
display()函数开头加上glLoadIdentity(),确保每次重绘的模型视图矩阵都是初始状态。 - 简化了
draw()函数里的变量,让逻辑更清晰。
现在运行代码,文本应该会和多边形一起正常滚动,不会消失了。
内容的提问来源于stack exchange,提问作者Gillian De Buyser
相关产品推荐
相关产品推荐

