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

OpenGL滚动文本触左边界消失问题求解

OpenGL水平滚动文本横幅修复方案

问题

在OpenGL应用中实现水平滚动文本横幅时,文本从右侧平滑进入屏幕显示正常,但当首个字符触碰窗口左边界时,整个文本会消失。需要实现文本平滑移出边界后从右侧重新开始滚动的效果。

问题根源

  1. 文本宽度未计算:当前用固定值-200判断重置位置,没有考虑文本实际宽度,导致文本未完全移出就触发重置,或因光栅位置超出裁剪区而停止绘制。
  2. 颜色值错误:glColor4f/glColor3f的参数需为0.0-1.0的浮点数,原代码中173.0f、255.0f会被截断为1.0,颜色显示异常。
  3. 矩阵设置不完整:reshape函数未切换回模型视图矩阵并重置,可能导致坐标转换混乱。

修复步骤

  • 新增计算文本宽度的函数,准确获取字符串的像素宽度。
  • 修改滚动终止条件:当文本完全移出左边界(文本右边缘 < 窗口左边界)时,才将文本重置到窗口右侧。
  • 修正颜色值为0.0-1.0的范围。
  • 完善reshape函数的矩阵设置,确保模型视图矩阵正确初始化。

修改后的完整代码

#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;

int state = 1;
float xsize = 800;
float ysize = 300;
const char* scrollText = "Testing train application for windows!!@@";

// 计算文本的像素宽度
float calculateTextWidth(const char* text) {
    float width = 0.0f;
    while (*text) {
        width += glutBitmapWidth(GLUT_BITMAP_TIMES_ROMAN_24, *text);
        text++;
    }
    return width;
}

void print_bitmap_string(const char* s) {
    while (*s) {
        glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *s);
        s++;
    }
}

void 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();
}

float x_pos = xsize/2;
float y_pos = 70;
float textWidth = 0.0f;

void draw() {
    glPushMatrix();
    glTranslatef(0.5, -100, 0);
    // 修正颜色值为0-1范围
    glColor4f(0.0f, 173.0f/255.0f, 115.0f/255.0f, 1.0f);

    glRasterPos2f(x_pos, y_pos);
    print_bitmap_string(scrollText);
    glPopMatrix();
}

void display(void) {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    draw();

    // 修正颜色值
    glColor3f(0.0f, 1.0f, 0.0f);
    glutSwapBuffers();
}

void timer(int) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 90, timer, 0);
    
    switch (state) {
        case 1:
            // 当文本完全移出左边界时重置
            if (x_pos + textWidth > -xsize / 2) {
                x_pos -= 1;
            } else {
                x_pos = xsize / 2;
            }
            break;
    }
}

int main(int argc, char** argv) {
    glutInitWindowSize(xsize, ysize);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutCreateWindow("Train Display");
    
    // 初始化文本宽度
    textWidth = calculateTextWidth(scrollText);
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutTimerFunc(1000 / 90, timer, 0);
    glutMainLoop();

    return 0;
}

说明

  • calculateTextWidth函数遍历字符串,累加每个字符的宽度,得到文本总宽度。
  • 滚动判断条件改为x_pos + textWidth > -xsize/2,确保文本完全移出左边界后才重置到右侧。
  • 颜色值调整为除以255后的浮点数,保证颜色正确显示。
  • 修正了reshape函数的矩阵切换,避免坐标转换错误。
  • 简化了状态机逻辑,去掉不必要的state=-1分支,直接在条件满足时重置位置。

内容的提问来源于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.08.22 23:15:44