Qt 的 OpenGL 故障(而不是 GLUT)

Posted

技术标签:

【中文标题】Qt 的 OpenGL 故障(而不是 GLUT)【英文标题】:OpenGL glitch with Qt (and not with GLUT) 【发布时间】:2013-06-26 15:23:57 【问题描述】:

我正在尝试来自 website 的一些简单(和旧)opengl 教程。在 gcc 中编译它们效果很好。现在我试着把它们放在我真正需要的地方:在 QGLWidget 内的 Qt 应用程序中。而且..我有一些小故障(彩色像素,图像应该全是黑白的)。不知道为什么。

查看附件图片:

我使用的是带有 QtCreator 的 Mac OS/X 10.8、Qt 4.8,并且正在编译基本的 GLUT 教程:

gcc -o test -Wall -W test.c -framework GLUT -framework OpenGL

程序大致相同,部分是替换一些GLUT vs Qt..无论如何,这是cpp文件:

#include "glwidget.h"

#include <QTimer>
#include <iostream>

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)

    QTimer *t = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(update()));
    t->start(1000.0f/30.0f); // 30 FPS


void GLWidget::initializeGL()

    glShadeModel(GL_SMOOTH);

    glClearColor(1, 1, 1, 0);

    glClearDepth(1);
    glEnable(GL_DEPTH_TEST);

    glMatrixMode(GL_MODELVIEW);

    //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    //glEnable(GL_LINE_SMOOTH);
    //glEnable(GL_POINT_SMOOTH);

    glLoadIdentity();

    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &texture_id);
    glBindTexture(GL_TEXTURE_2D, texture_id);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB,
                 GL_UNSIGNED_BYTE, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);



void GLWidget::resizeGL(int w, int h)

    h = h ? h : 1;

    glViewport(0, 0, w,h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 0.1, 8000.0f);
    glMatrixMode(GL_MODELVIEW);


float rotation=20;
void GLWidget::paintGL()

    makeCurrent();

    //glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    //glLoadIdentity();

    glLoadIdentity();
    glTranslatef(0, 0, -10);
    glRotatef(rotation, 1, 0, 0);
    glRotatef(20   , 0, 1, 0);

    /* Define a view-port adapted to the texture */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(20, 1, 5, 15);
    glViewport(0, 0, SIZE, SIZE);
    glMatrixMode(GL_MODELVIEW);

    /* Render to buffer */
    glClearColor(1, 1, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    Cube();
    glFlush();

    /* Copy buffer to texture */
    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE - 10, SIZE - 10);

    /* Render to screen */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(20, width() / (float) height(), 5, 15);
    glViewport(0, 0, width(), height());
    glMatrixMode(GL_MODELVIEW);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    Cube();

    /* End */
    glFlush();

    /* Update again and again */
    rotation += 0.1;


void GLWidget::Cube()

    glBegin(GL_QUADS);

    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, -1,  1);
    glTexCoord2i(1, 1); glVertex3f(-1,  1,  1);
    glTexCoord2i(1, 0); glVertex3f(-1,  1, -1);

    glTexCoord2i(0, 0); glVertex3f( 1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f( 1, -1,  1);
    glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
    glTexCoord2i(1, 0); glVertex3f( 1,  1, -1);

    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, -1,  1);
    glTexCoord2i(1, 1); glVertex3f( 1, -1,  1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);

    glTexCoord2i(0, 0); glVertex3f(-1,  1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1,  1,  1);
    glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
    glTexCoord2i(1, 0); glVertex3f( 1,  1, -1);

    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1,  1, -1);
    glTexCoord2i(1, 1); glVertex3f( 1,  1, -1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);

    glTexCoord2i(0, 0); glVertex3f(-1, -1,  1);
    glTexCoord2i(0, 1); glVertex3f(-1,  1,  1);
    glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1,  1);

    glEnd();

ps。 Ubuntu 12.04下同样的Qt程序没问题

【问题讨论】:

【参考方案1】:

我确实在您在其他问题中发布的代码中看到了这一点:

glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE - 10, SIZE - 10);
                                                       ^^^^       ^^^^

两边都有一个未定义的 10 像素边框。在那个演示中,它为纹理添加了一些边框,但从技术上讲,它会使纹理中已经存在的任何内容保持不变。

现在,由于您可能会使用一些未定义的数组数据初始化纹理(我没有看到 texture 作为数据参数传递给正在初始化的 glTexImage2D),这将产生一些垃圾。顺便说一句:您可以通过将空指针传递给 glTexImage2D 的数据参数来安全地初始化纹理。

【讨论】:

@datenwold:谢谢。所以..我试过:1)我试图设置*texture = 0glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);之前传递一个空指针..没有任何改变2)for(int i=0; i&lt;3 * SIZE * SIZE -1; i++) texture[i] = 0; 提供一些初始化的数组数据和..程序崩溃不好内存访问 (??) @nkint:传递 0 指针会使纹理未初始化,这也可能导致垃圾。关于后者:如何定义和初始化*texture?它必须是静态分配的,使用new,是std::vectorQVector 我忘记用 new 初始化它。以前是unsigned int texture[3 * SIZE * SIZE];,现在是unsigned int *texture; .... texture = new unsigned int[3 * SIZE * SIZE];

以上是关于Qt 的 OpenGL 故障(而不是 GLUT)的主要内容,如果未能解决你的问题,请参考以下文章

Qt 4.6 OpenGL GLSL

QT一个最简单的openGL例子

将 Qt GUI 拆分为多个线程用于 GUI、模拟和 OpenGL 是不是可行?

如何通过openGL或Glut检查窗口是不是打开

Qt下使用glut库

VS2010下用OpenGL“缺少glut32.dll”