Qt OpenGL----纹理贴图

本文介绍如何在OpenGL中对三维物体进行纹理贴图,包括贴图的加载、初始化、绘制过程以及如何创建和使用纹理对象,实现真实感的三维图形效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

类定义:

#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.youkuaiyun.com/detail/mojianc/8660233点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值