You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:17:40