您的位置:首页 > 编程语言 > Qt开发

Qt OpenGL----纹理贴图

2015-05-04 16:26 477 查看
为了让三围图形看上去更真实,可以在三维物体上贴上纹理图像。纹理贴图能够保证当三围物体变换和渲染时,纹理能够表现出正确的行为。纹理通常是二维的,但它也可以是一维或者三维的。这里通过一个简单的例子来学习基本的纹理贴图功能。例子是对立方体每一面进行不同的纹理贴图并进行旋转。废话不多说,直接看代码:

类定义:

#ifndef MYGL_H_
#define MYGL_H_

#include <QtGui>
#include <QtOpenGL>
#include<gl/glu.h>
class MyGLWidget : public QGLWidget
{
Q_OBJECT

public:
MyGLWidget(QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0);
~MyGLWidget();

protected:
GLfloat xRot, yRot, zRot;
GLuint texture[6];

void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void loadGLTextures();
void timerEvent(QTimerEvent *event);
void mouseDoubleClickEvent( QMouseEvent * event );
};

#endif /*MYGL_H_*/


类实现:

#include <QtGui>
#include <QtOpenGL>

#include "mygl.h"

MyGLWidget::MyGLWidget(QWidget * parent, const QGLWidget * shareWidget, Qt::WindowFlags f)
{
xRot = yRot = zRot =0.0;
setMinimumSize(320,240);
resize(640,480);
setWindowTitle(tr("OpenGL纹理"));
startTimer(500);
}

MyGLWidget::~MyGLWidget()
{
}

void MyGLWidget::initializeGL()
{
loadGLTextures();
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0, 0.0, 0.0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
}

void MyGLWidget::paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glTranslatef( 0.0,  0.0, -5.0 );
glRotatef( xRot,  1.0,  0.0,  0.0 );
glRotatef( yRot,  0.0,  1.0,  0.0 );
glRotatef( zRot,  0.0,  0.0,  1.0 );

glBindTexture( GL_TEXTURE_2D, texture[0] );
glBegin( GL_QUADS );
// front
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0,  1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0,  1.0 );
glEnd();

glBindTexture( GL_TEXTURE_2D, texture[1] );
glBegin( GL_QUADS );
// back
glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );
glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0, -1.0 );
glEnd();

glBindTexture( GL_TEXTURE_2D, texture[2] );
glBegin( GL_QUADS );
// top
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0,  1.0,  1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0,  1.0,  1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );
glEnd();

glBindTexture( GL_TEXTURE_2D, texture[3] );
glBegin( GL_QUADS );
// bottom
glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0, -1.0, -1.0 );
glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );
glEnd();

glBindTexture( GL_TEXTURE_2D, texture[4] );
glBegin( GL_QUADS );
// right
glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0, -1.0, -1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0,  1.0,  1.0 );
glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );
glEnd();

glBindTexture( GL_TEXTURE_2D, texture[5] );
glBegin( GL_QUADS );
// left
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0,  1.0,  1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );
glEnd();
}

void MyGLWidget::timerEvent(QTimerEvent *event)
{
xRot += 0.3;
yRot += 0.2;
zRot += 0.4;
update();
}

void MyGLWidget::resizeGL(int width, int height)
{
glViewport( 0, 0, (GLint)width, (GLint)height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}

void MyGLWidget::mouseDoubleClickEvent( QMouseEvent * event )
{
if(windowState() &  Qt::WindowFullScreen)
showNormal();
else
showFullScreen();
}

void MyGLWidget::loadGLTextures()
{
QImage tex, buffer;
QString fileName(":texture%1.bmp");

glGenTextures(6, &texture[0]);

for(short i=0; i<6; i++) {
buffer.load(fileName.arg(i+1));
tex = QGLWidget::convertToGLFormat( buffer );
glBindTexture( GL_TEXTURE_2D, texture[i] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, tex.width(), tex.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
首先在initializeGL()函数中加入启用二维纹理贴图功能的语句,如下:

<span style="white-space:pre">	</span>glEnable(GL_TEXTURE_2D)
使用纹理之前,需要创建纹理对象,这里通过函数loadGLTextures()来实现。在loadTextures()这个函数中装入一个QImage对象作为纹理贴图,由于OpenGL并不认识QT的QImage图像格式,所以要调用QGLWidget::convertToGLFormat()函数将QImage对象转换为OpenGL API能够识别的图像格式。转换后的QImage已经不是QT能识别的格式,但width(),height()和bits()返回的值仍然是有效的,能够在OpenGL应用中使用。

函数glGenTextures(GLsizei n, GLunit *textureNames)在数组textureNames中返回n个当前未使用的值,表示纹理对象的名称。glBindTexture()函数创建和使用纹理对象。

glTexImage2D()函数真正的创建纹理。第一个参数GL_TEXTURE_2D告诉OpenGL此纹理是一个2D纹理;第二个参数在只有一种分辨率的纹理贴图的情况下,应该为0;第三个参数确定了数据在哪些成分(RGBA、深度、亮度)作为图像的纹理单元,这里使用GL_RGB;tex.width()是纹理的宽度;tex.height()是纹理的高度;第6个参数是边框的值;GL_RGBA告诉OpenGL纹理图像数据由红、绿、蓝三色数据以及alpha通道数据组成;GL_UNSIGNED_BYTE说明组成图像的数据是无符号字节类型的;最后tex.bits()指明了OpenGL纹理数据的来源。接下来是语句:

<span style="white-space:pre">	</span>glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
上面两行代码告诉OpenGL在显示图像时,当图像放大的比原始纹理大(GL_TEXTRUE_MAG_FILTER)或者缩小的比原始纹理小(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。通常这两种情况都采用GL_LINEAR,这使得纹理从很远处到离屏幕很近都平滑显示。使用GL_LINEAR需要CPU和显卡做更多的运算。如果计算机配置较低,可以采用GL_NEAREST。但过滤的纹理在放大的时候,看起来比较粗糙。当然也可以结合这两种滤波方式。在近处使用GL_LINEAR,在远处使用GL_NEAREST。

接下来在paintGL()中使用纹理,函数中glTexCoord2f()函数设置纹理坐标,glTexCoord2f()的第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是文理的右侧。glTexCoord2f()的第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部。

最后实现main.cpp

#include <QtGui>
#include "mygl.h"

int main(int argc, char **argv)
{
Q_INIT_RESOURCE(texture);
QApplication app(argc, argv);
MyGLWidget myglWidget;
myglWidget.show();
return app.exec();
}


运行结果:



源程序代码:http://download.csdn.net/detail/mojianc/8660233点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: