77范文网 - 专业文章范例文档资料分享平台

Qt+OpenGL中文教程(8)

来源:网络收集 时间:2020-04-03 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

}

void NeHeWidget::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 ); }

现在您应该比较好的理解纹理映射(贴图)了。您应该掌握了给任意四边形表面贴上您所喜爱的图像的技术。一旦您对2D纹理映射的理解感到自信的时候,试试给立方体的六个面贴上不同的纹理。

当您理解纹理坐标的概念后,纹理映射并不难理解。 本课程的源代码。

纹理滤波、光源和键盘控制

这一课我会教您如何使用三种不同的纹理滤波方式。教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照。这一课包含了很多内容,如果您对前面的课程有疑问的话,先回头复习一下。进入后面的代码之前,很好的理解基础知识十分重要。

我们要在第一课的代码上进行改动就可以了。

我们将要增加一个loadGLTextures()函数来处理有关纹理操作的。我们将增加一些变量,稍后我们对这些变量进行解释。

NeHeWidget类

(由nehewidget.h展开。) protected:

void loadGLTextures();

在这个函数中我们会载入指定的图片并生成相应当纹理。 protected:

bool fullscreen;

GLfloat xRot, yRot, zRot; GLfloat zoom;

GLfloat xSpeed, ySpeed; GLuint texture[3]; GLuint filter;

bool light; };

上面就是添加的三个变量xRot、yRot、zRot来处理立方体在三个方向上的旋转。zoom是场景深入屏幕的距离。xSpeed和ySpeed是立方体在X轴和Y轴上旋转的速度。texture[3]用来存储三个纹理。filter表明的是使用哪个纹理。light是说明现在是否使用光源。 (由nehewidget.cpp展开。)

GLfloat lightAmbient[4] = { 0.5, 0.5, 0.5, 1.0 }; GLfloat lightDiffuse[4] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat lightPosition[4] = { 0.0, 0.0, 2.0, 1.0 }; 这里定义了三个数组,它们描述的是和光源有关的信息。

我们将使用两种不同的光。第一种称为环境光。环境光来自于四面八方。所有场景中的对象都处于环境光的照射中。第二种类型的光源叫做漫射光。漫射光由特定的光源产生,并在您的场景中的对象表面上产生反射。处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显得要暗一些。这样在我们所创建的木板箱的棱边上就会产生的很不错的阴影效果。

创建光源的过程和颜色的创建完全一致。前三个参数分别是RGB三色分量,最后一个是alpha通道参数。

因此,第一行有关lightAmbient的代码使我们得到的是半亮(0.5)的白色环境光。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。

第二行有关lightDiffuse的代码使我们生成最亮的漫射光。所有的参数值都取成最大值1.0。它将照在我们木板箱的前面,看起来挺好。

第三行有关lightPosition的代码使我们保存光源的位置。前三个参数和glTranslate中的一样。依次分别是XYZ轴上的位移。由于我们想要光线直接照射在木箱的

正面,所以XY轴上的位移都是0.0。第三个值是Z轴上的位移。为了保证光线总在木箱的前面,所以我们将光源的位置朝着观察者(就是您哪。)挪出屏幕。我们通常将屏幕也就是显示器的屏幕玻璃所处的位置称作Z轴的0.0点。所以Z轴上的位移最后定为2.0。假如您能够看见光源的话,它就浮在您显示器的前方。当然,如果木箱不在显示器的屏幕玻璃后面的话,您也无法看见箱子。最后一个参数取为1.0。这将告诉OpenGL这里指定的坐标就是光源的位置,以后的教程中我会多加解释。

NeHeWidget::NeHeWidget( QWidget* parent, const char* name, bool fs ) : QGLWidget( parent, name ) {

xRot = yRot = zRot = 0.0; zoom = -5.0;

xSpeed = ySpeed = 0.0;

filter = 0;

light = false;

fullscreen = fs;

setGeometry( 0, 0, 640, 480 );

setCaption( \

if ( fullscreen ) showFullScreen(); }

我们需要在构造函数中给各个变量赋初值。xRot、yRot、zRot是0.0。zoom是-5.0。xSpeed和ySpeed都是0。filter是0。light是false。

void NeHeWidget::loadGLTextures() {

QImage tex, buf;

if ( !buf.load( \ {

qWarning( \not read image file, using single-color instead.\); QImage dummy( 128, 128, 32 ); dummy.fill( Qt::green.rgb() ); buf = dummy; }

tex = QGLWidget::convertToGLFormat( buf );

glGenTextures( 3, &texture[0] );

这一部分,上一章讲过了。我们这里创建了3个纹理。

glBindTexture( GL_TEXTURE_2D, texture[0] );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

第六课中我们使用了线性滤波的纹理贴图。这需要机器有相当高的处理能力,但它们看起来很不错。这一课中,我们接着要创建的第一种纹理使用GL_NEAREST方式。从原理上讲,这种方式没有真正进行滤波。它只占用很小的处理能力,看起来也很差。唯一的好处是这样我们的工程在很快和很慢的机器上都可以正常运行。您会注意到我们在MIN和MAG时都采用了GL_NEAREST,你可以混合使用GL_NEAREST和GL_LINEAR。纹理看起来效果会好些,但我们更关心速度,所以全采用低质量贴图。MIN_FILTER在图像绘制时小于贴图的原始尺寸时采用。MAG_FILTER在图像绘制时大于贴图的原始尺寸时采用。

glBindTexture( GL_TEXTURE_2D, texture[1] );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

这个纹理与第六课的相同,线性滤波。唯一的不同是这次放在了texture[1]中。因为这是第二个纹理。如果放在texture[0]中的话,它将覆盖前面创建的GL_NEAREST纹理。

glBindTexture( GL_TEXTURE_2D, texture[2] );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );

这里是创建纹理的新方法。Mipmapping!您可能会注意到当图像在屏幕上变得很小的时候,很多细节将会丢失。刚才还很不错的图案变得很难看。当您告诉OpenGL创建一个 mipmapped的纹理后,OpenGL将尝试创建不同尺寸的高质量纹理。当您向屏幕绘制一个mipmapped纹理的时候,OpenGL将选择它已经创建的外观最佳的纹理(带有更多细节)来绘制,而不仅仅是缩放原先的图像(这将导致细节丢失)。

我曾经说过有办法可以绕过OpenGL对纹理宽度和高度所加的限制——64、128、256,等等。办法就是gluBuild2DMipmaps。据我的发现,您可以使用任意的位图来创建纹理。OpenGL将自动将它缩放到正常的大小。

因为是第三个纹理,我们将它存到texture[2]。这样本课中的三个纹理全都创建好了。 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, tex.width(), tex.height(), GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说教育文库Qt+OpenGL中文教程(8)在线全文阅读。

Qt+OpenGL中文教程(8).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/jiaoyu/930971.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: