我正在使用 QGLWidget 子类在 Qt 中关注NeHe OGL 教程。到目前为止我还没有遇到任何问题,并且在第6 次教程中在纹理映射中,他介绍了对旋转框进行纹理化。我让一切正常,然后尝试在立方体的每一侧添加我自己的纹理。我使用 QGLWidget::bindTexture() 函数加载通过 Qt 资源系统存储的 256x256 bmp 文件,并将 GLuint id 保存在私有成员数组中。在paintGL() 中,在为正方形的每个面调用glBegin(GL_QUADS) 和glEnd() 之前,我使用GL_TEXTURE_2D 和GLuint 数组元素之一作为参数调用glBindTexture()。它编译得很好,但是该框要么呈现完全白色(好像它可能找不到纹理),否则我在旋转绘制过程中得到疯狂的黑白伪影,随机线条在整个屏幕上射击。
在搞砸的同时,我设法通过在我的类声明的末尾添加另一个私有数据成员来解决问题,当事情神奇地开始工作时,我决定在类声明中将我的 GLuint 纹理数组的声明移到更高的位置,这似乎有效. 我对内存对齐一无所知,这似乎是正在发生的事情的最明显原因,我很想解释这里发生的事情。
万一这很重要,这是在 Qt 4.6 上,在 GCC 4.4.0 和 MinGW 5.1.6 中的 GNU Make 3.8.1 上编译(我应该升级)。
代码:glwidget.hpp,有问题的声明在底部注释
#ifndef GLWIDGET_HPP
#define GLWIDGET_HPP
#include <QtOpenGL>
class QTimer;
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget( QWidget *parent = 0 );
~GLWidget();
protected:
void initializeGL();
void paintGL();
void resizeGL( int width, int height );
private:
void drawCube();
void loadTextures();
QTimer *m_timer;
GLuint m_textures[6]; // doesn't cause rendering problems here
GLfloat m_xrot, m_yrot, m_zrot;
// GLuint m_textures[6]; // causes rendering problems if declared here
};
#endif
glwidget.cpp
#include "glwidget.hpp"
#include <QTimer>
GLWidget::GLWidget( QWidget *parent )
: QGLWidget( QGLFormat(QGL::SampleBuffers), parent )
{
m_timer = new QTimer( this );
m_timer->setSingleShot( false );
connect( m_timer, SIGNAL(timeout()), this, SLOT(updateGL()) );
m_timer->start( 7 );
setWindowTitle( "NeHe Lesson 6" );
}
GLWidget::~GLWidget()
{
glDeleteTextures( 6, m_textures );
}
void GLWidget::initializeGL()
{
glShadeModel( GL_SMOOTH ); // Enable smooth shading
qglClearColor( Qt::black );
glClearDepth( 1.0f ); // Depth buffer setup
glEnable( GL_DEPTH_TEST );
glEnable( GL_TEXTURE_2D );
glDepthFunc( GL_LEQUAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
loadTextures();
}
void GLWidget::loadTextures()
{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
m_textures[0] = bindTexture( QPixmap(":/img/scifi.bmp") );
m_textures[1] = bindTexture( QPixmap(":/img/scifi2.bmp") );
m_textures[2] = bindTexture( QPixmap(":/img/scifi3.bmp") );
m_textures[3] = bindTexture( QPixmap(":/img/scifi4.bmp") );
m_textures[4] = bindTexture( QPixmap(":/img/scifi5.bmp") );
m_textures[5] = bindTexture( QPixmap(":/img/scifi6.bmp") );
}
void GLWidget::drawCube()
{
// Front face
glBindTexture( GL_TEXTURE_2D, m_textures[0] );
glBegin( GL_QUADS );
glNormal3f( 0.0f, 0.0f, 1.0f );
glTexCoord2f( 0.0f, 0.0f ); glVertex3f(-1.0f,-1.0f, 1.0f ); // Bottom left
glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f,-1.0f, 1.0f ); // Bottom right
glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); // Top right
glTexCoord2f( 0.0f, 1.0f ); glVertex3f(-1.0f, 1.0f, 1.0f ); // Top left
glEnd();
// Back face
glBindTexture( GL_TEXTURE_2D, m_textures[1] );
glBegin( GL_QUADS );
glNormal3f( 0.0f, 0.0f, -1.0f );
glTexCoord2f( 1.0f, 0.0f ); glVertex3f(-1.0f,-1.0f,-1.0f ); // Bottom right
glTexCoord2f( 1.0f, 1.0f ); glVertex3f(-1.0f, 1.0f,-1.0f ); // Top right
glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f,-1.0f ); // Top left
glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f,-1.0f,-1.0f ); // Bottom left
glEnd();
// Top Face
glBindTexture( GL_TEXTURE_2D, m_textures[2] );
glBegin( GL_QUADS );
glNormal3f( 0.0f, 1.0f, 0.0f );
glTexCoord2f( 0.0f, 1.0f ); glVertex3f(-1.0f, 1.0f,-1.0f ); // Top left
glTexCoord2f( 0.0f, 0.0f ); glVertex3f(-1.0f, 1.0f, 1.0f ); // Bottom left
glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); // Bottom right
glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f,-1.0f ); // Top right
glEnd();
// Bottom Face
glBindTexture( GL_TEXTURE_2D, m_textures[3] );
glBegin( GL_QUADS );
glNormal3f( 0.0f, -1.0f, 0.0f );
glTexCoord2f( 1.0f, 1.0f ); glVertex3f(-1.0f,-1.0f,-1.0f ); // Top right
glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f,-1.0f,-1.0f ); // Top left
glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f,-1.0f, 1.0f ); // Bottom left
glTexCoord2f( 1.0f, 0.0f ); glVertex3f(-1.0f,-1.0f, 1.0f ); // Bottom right
glEnd();
// Right face
glBindTexture( GL_TEXTURE_2D, m_textures[4] );
glBegin( GL_QUADS );
glNormal3f( 1.0f, 0.0f, 0.0f );
glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f,-1.0f,-1.0f ); // Bottom right
glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f,-1.0f ); // Top right
glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); // Top left
glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f,-1.0f, 1.0f ); // Bottom left
glEnd();
// Left Face
glBindTexture( GL_TEXTURE_2D, m_textures[5] );
glBegin( GL_QUADS );
glNormal3f( -1.0f, 0.0f, 0.0f );
glTexCoord2f( 0.0f, 0.0f ); glVertex3f(-1.0f,-1.0f,-1.0f ); // Bottom left
glTexCoord2f( 1.0f, 0.0f ); glVertex3f(-1.0f,-1.0f, 1.0f ); // Bottom right
glTexCoord2f( 1.0f, 1.0f ); glVertex3f(-1.0f, 1.0f, 1.0f ); // Top right
glTexCoord2f( 0.0f, 1.0f ); glVertex3f(-1.0f, 1.0f,-1.0f ); // Top left
glEnd();
}
void GLWidget::paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glTranslatef( 0.0f, 0.0f, -5.0f );
glRotatef( m_xrot, 1.0f, 0.0f, 0.0f );
glRotatef( m_yrot, 0.0f, 1.0f, 0.0f );
glRotatef( m_zrot, 0.0f, 0.0f, 1.0f );
drawCube();
m_xrot += 0.3f;
m_yrot += 0.2f;
m_zrot += 0.4f;
}
void GLWidget::resizeGL( int width, int height )
{
if( height == 0 )
height = 1;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0f, static_cast<GLfloat>(width)/height, 0.1f, 100.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}