Qt OpenGL----纹理贴图
2015-05-04 16:26
477 查看
为了让三围图形看上去更真实,可以在三维物体上贴上纹理图像。纹理贴图能够保证当三围物体变换和渲染时,纹理能够表现出正确的行为。纹理通常是二维的,但它也可以是一维或者三维的。这里通过一个简单的例子来学习基本的纹理贴图功能。例子是对立方体每一面进行不同的纹理贴图并进行旋转。废话不多说,直接看代码:
类定义:
类实现:
函数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纹理数据的来源。接下来是语句:
接下来在paintGL()中使用纹理,函数中glTexCoord2f()函数设置纹理坐标,glTexCoord2f()的第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是文理的右侧。glTexCoord2f()的第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部。
最后实现main.cpp
运行结果:
源程序代码:http://download.csdn.net/detail/mojianc/8660233点击打开链接
类定义:
#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点击打开链接
相关文章推荐
- qt5.6.0 opengl —— 纹理贴图
- Qt中使用OpenGL的纹理贴图
- qt5_qml_Opengl_shader 第二弹----------------------纹理贴图(RGB)
- qt5_qml_Opengl_shader 第三弹-----------------------纹理贴图(YUV)
- qt5_qml_Opengl_shader 第四弹----------------------纹理贴图(YUV视频循环播放)
- OpenGL+Qt界面(四) 纹理贴图
- Qt+OpenGL之纹理贴图
- 纹理窗口Qt+OpenGL之纹理贴图
- Qt下的OpenGL 编程纹理和贴图
- Qt-OpenGL中的多纹理贴图
- Qt5.6.0+OpenGL 纹理贴图首战告捷
- NeHe的opengl教程delphi版(6)----纹理映射(贴图)
- openGL学习笔记6 bmp 2D纹理贴图
- opengl 绘制简单的带纹理贴图的立方体
- [OpenGL]纹理贴图实现 总结
- Qt结合GLSL贴出纹理(一、采用原生OpenGL API)
- 使用glfw库将OpenCV读取到的图片作为OpenGL的背景纹理贴图
- OpenGL基本概念入门——纹理贴图
- 基于Qt的OpenGL编程(3.x以上GLSL可编程管线版)---(四)纹理
- 改造的opengl纹理贴图