OpenGL闪屏

Posted

技术标签:

【中文标题】OpenGL闪屏【英文标题】:OpenGL flickering screen 【发布时间】:2015-05-08 17:19:55 【问题描述】:

我编写了一个在我的 ubuntu 笔记本电脑上运行的简单 opengl。它是一个包括太阳和地球的小太阳系,地球围绕太阳旋转。我的程序的问题是每次我尝试运行它时屏幕都会不停地闪烁。

#include <GL/glut.h>
#define SUN_RADIUS 0.4
#define EARTH_RADIUS 0.06
#define MOON_RADIUS 0.016

GLfloat EARTH_ORBIT_RADIUS = 0.9;
GLfloat year = 0.0;

void init() 
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();



void renderScene() 
    gluLookAt(
        0.0, 0.0, -4.0,
        0.0, 0.0, 0.0,
        0.0, 1.0, 0.0
    );
    glColor3f(1.0, 1.0, 0.7);
    glutWireSphere(SUN_RADIUS, 50, 50);
    glPushMatrix();

    glRotatef(year, 0.0, 1.0, 0.0);
    glTranslatef(EARTH_ORBIT_RADIUS, 0.0, 0.0);

    glColor3f(0.0, 0.7, 1.0);
    glutWireSphere(EARTH_RADIUS, 10, 10);

    glPopMatrix();


void display() 
    glClear(GL_COLOR_BUFFER_BIT);
    renderScene();
    glFlush();
    glutSwapBuffers();


void idle() 
    year += 0.2;
    display();


int main(int argc, char** argv) 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(600, 600);
    glutCreateWindow("Solar System");

    init();
    glutDisplayFunc(display);
    glutIdleFunc(idle);

    glutMainLoop();

【问题讨论】:

您没有清除深度缓冲区。会不会是这个问题? 我将 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 添加到我的代码中,但问题仍然存在 【参考方案1】: gluLookAt() 乘以当前矩阵,它不会加载新矩阵。多个gluLookAt()s 相乘并没有多大意义。 每帧重新加载 proj/modelview 矩阵,有助于防止矩阵异常。 让 GLUT 完成它的工作,不要从 idle() 调用 display(),而是使用 glutPostRedisplay()。这样 GLUT 就知道下次通过事件循环调用 display()

大家一起:

#include <GL/glut.h>

#define SUN_RADIUS 0.4
#define EARTH_RADIUS 0.06
#define MOON_RADIUS 0.016

GLfloat EARTH_ORBIT_RADIUS = 0.9;
GLfloat year = 0.0;

void renderScene()

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho( -1, 1, -1, 1, -100, 100 );

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt
        (
        0.0, 0.0, -4.0,
        0.0, 0.0, 0.0,
        0.0, 1.0, 0.0
        );

    glColor3f(1.0, 1.0, 0.7);
    glutWireSphere(SUN_RADIUS, 50, 50);

    glPushMatrix();
    glRotatef(year, 0.0, 1.0, 0.0);
    glTranslatef(EARTH_ORBIT_RADIUS, 0.0, 0.0);
    glColor3f(0.0, 0.7, 1.0);
    glutWireSphere(EARTH_RADIUS, 10, 10);
    glPopMatrix();


void display()

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(10.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    renderScene();
    glutSwapBuffers();


void idle()

    year += 0.2;
    glutPostRedisplay();


int main(int argc, char** argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(600, 600);
    glutCreateWindow("Solar System");

    glutDisplayFunc(display);
    glutIdleFunc( idle );

    glutMainLoop();

【讨论】:

谢谢,这解决了我的问题。那么,乘以许多 gluLookAt 矩阵是否会导致闪烁问题?【参考方案2】:

如果您没有进行任何类型的垂直同步(看起来不像您的代码),这可能是由于撕裂造成的。尝试在您的显示方法中添加睡眠时间(例如 sleep(500))。这不是解决此问题的正确方法,但这将允许您验证问题是否存在。如果是,请考虑将垂直同步添加到您的应用程序中。

【讨论】:

我在 ubuntu 上出现撕裂问题,这是由合成管理器引起的。 好像sleep()是windows的函数,Ubuntu Linux下有没有类似的函数? 它应该在那里。我认为您需要包含 unistd.h 并从那里调用它。 pthread.h 也可能有它(实际上取决于包含哪些库)。我看到的一个解决方案是在这个线程的底部以及自定义睡眠功能:ubuntuforums.org/showthread.php?t=296142 我已经按照你的建议添加了 sleep() 函数。但是,程序不绘制任何东西并在运行时卡住。 尝试使用 50 的值。如果您添加了该方法,请确保它有效,因为我不确定该方法是否正确。基本上,您想减慢显示方法的运行速度。这种睡眠方法可能永远不会结束,或者需要太长时间。

以上是关于OpenGL闪屏的主要内容,如果未能解决你的问题,请参考以下文章

移除或更换启动时的 kivy 闪屏

Blender源码分析之上下文的索引结构

Blender源码分析之上下文的索引结构

[OpenGL红宝书]第一章 OpenGL概述

OpenGL版本与OpenGL扩展机制

glfw 包含了opengl吗