这一行生成 mipmapped 纹理。我们使用三种颜色(红,绿,蓝)来生成一个2D纹理。tex.width()是位图宽度,tex.height()是位图高度,
extureImage[0]->sizeY 是位图高度,GL_RGBA意味着我们依次使用RGBA色彩。GL_UNSIGNED_BYTE意味着纹理数据的单位是字节。tex.bits()指向我们创建纹理所用的位图。 }
loadGLTextures()函数就是用来载入纹理的。
void NeHeWidget::paintGL() {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity();
glTranslatef( 0.0, 0.0, zoom );
glRotatef( xRot, 1.0, 0.0, 0.0 ); glRotatef( yRot, 0.0, 1.0, 0.0 );
glBindTexture( GL_TEXTURE_2D, texture[filter] ); 根据filter变量来决定使用哪个纹理。
glBegin( GL_QUADS );
glNormal3f( 0.0, 0.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 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );
glNormal3f( 0.0, 0.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 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );
glNormal3f( 0.0, 1.0, 0.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 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );
glNormal3f( 0.0, -1.0, 0.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 ); glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );
glNormal3f( 1.0, 0.0, 0.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 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );
glNormal3f( -1.0, 0.0, 0.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 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glEnd();
这里绘制正方体的方法,上一章已经讲解过了。 xRot += xSpeed; yRot += ySpeed;
将xRot和yRot的旋转值分别增加xSpeed和ySpeed个单位。xSpeed和ySpeed的值越大,立方体转得就越快。
}
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 );
glLightfv( GL_LIGHT1, GL_AMBIENT, lightAmbient ); glLightfv( GL_LIGHT1, GL_DIFFUSE, lightDiffuse ); glLightfv( GL_LIGHT1, GL_POSITION, lightPosition );
glEnable( GL_LIGHT1 );
这里开始设置光源。第一行设置环境光的发光量,光源GL_LIGHT1开始发光。这一课的开始处我们我们将环境光的发光量存放在lightAmbient数组中。现在我们就使用此数组(半亮度环境光)。
接下来我们设置漫射光的发光量。它存放在lightDiffuse数组中(全亮度白光)。 然后设置光源的位置。位置存放在lightPosition 数组中(正好位于木箱前面的中心,X-0.0,Y-0.0,Z方向移向观察者2个单位,位于屏幕外面)。 最后,我们启用一号光源。我们还没有启用GL_LIGHTING,所以您看不见任何光线。记住:只对光源进行设置、定位、甚至启用,光源都不会工作。除非我们启用GL_LIGHTING。
}
void NeHeWidget::keyPressEvent( QKeyEvent *e ) {
switch ( e->key() ) {
case Qt::Key_L: light = !light; if ( !light ) {
glDisable( GL_LIGHTING ); } else {
glEnable( GL_LIGHTING ); }
updateGL(); break;
按下了L键,就可以切换是否打开光源。 case Qt::Key_F: filter += 1;; if ( filter > 2 ) {
filter = 0; }
updateGL(); break;
按下了F键,就可以转换一下所使用的纹理(就是变换了纹理滤波方式的纹理)。 case Qt::Key_PageUp:
zoom -= 0.2; updateGL(); break;
按下了PageUp键,将木箱移向屏幕内部。 case Qt::Key_PageDown: zoom += 0.2; updateGL(); break;
按下了PageDown键,将木箱移向屏幕外部。 case Qt::Key_Up: xSpeed -= 0.01; updateGL(); break;
按下了Up方向键,减少xSpeed。 case Qt::Key_Down: xSpeed += 0.01; updateGL(); break;
按下了Dowm方向键,增加xSpeed。 case Qt::Key_Right: ySpeed += 0.01; updateGL(); break;
按下了Right方向键,增加ySpeed。 case Qt::Key_Left: ySpeed -= 0.01; updateGL(); break;
按下了Left方向键,减少ySpeed。 case Qt::Key_F2:
fullscreen = !fullscreen; if ( fullscreen ) {
showFullScreen(); } else {
showNormal();
setGeometry( 0, 0, 640, 480 ); }
update(); break;
case Qt::Key_Escape: close(); } }
这一课完了之后,您应该学会创建和使用这三种不同的纹理映射过滤方式。并使用键盘和场景中的对象交互。最后,您应该学会在场景中应用简单的光源,使得场景看起来更逼真。 本课程的源代码。
融合