NeHe教程Qt实现——lesson09

NeHe 系列教程之九: 在3D空间中移动位图

英文教程地址:lesson09

本课基于第一课的代码, 利用颜色混合的方法,将一个黑白纹理与随机颜色进行混合,产生绚丽的效果。

首先是定义相关变量和数据结构,如下所示:

namespace {
    bool    twinkle;                        // Twinkling Stars
    bool    tp;                         // 'T' Key Pressed?
    const   int num = 50;                         // Number Of Stars To Draw

    typedef struct                          // Create A Structure For Star
    {
        int r, g, b;                        // Stars Color
        GLfloat dist;                       // Stars Distance From Center
        GLfloat angle;                      // Stars Current Angle
    }stars;                              // Structures Name Is Stars
    stars star[num];                    // Make 'star' Array Of 'num' Using Info From The Structure

    GLfloat zoom=-15.0f;                        // Viewing Distance Away From Stars
    GLfloat tilt=90.0f;                     // Tilt The View
    GLfloat spin;                           // Spin Twinkling Stars

    GLuint  loop;                           // General Loop Variable
    GLuint  texture[1];                     // Storage For One Texture
}

加载纹理的代码跟之前课程代码类似。

然后是初始化代码:

void MyGLWidget::initializeGL()
{
    loadTextures();
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);   // Enables Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);  // Black Background
    glClearDepth(1.0f);             // Depth Buffer Setup
 //   glEnable(GL_DEPTH_TEST);        // Enables Depth Testing
 //   glDepthFunc(GL_LEQUAL);        // The Type Of Depth Test To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);           // Set The Blending Function For Translucency
    glEnable(GL_BLEND);                 // Enable Blending

    for (loop=0; loop<num; loop++)               // Create A Loop That Goes Through All The Stars
    {
        star[loop].angle=0.0f;              // Start All The Stars At Angle Zero
        star[loop].dist=(float(loop)/num)*5.0f;     // Calculate Distance From The Center
        star[loop].r=rand()%256;            // Give star[loop] A Random Red Intensity
        star[loop].g=rand()%256;            // Give star[loop] A Random Green Intensity
        star[loop].b=rand()%256;            // Give star[loop] A Random Blue Intensity
    }
}

注意,开启混合的时候要关闭深度测试。

接着是绘制代码,如下所示:

void MyGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth Buffer
    glLoadIdentity();       // Reset The Current Modelview Matrix
    glBindTexture(GL_TEXTURE_2D, texture[0]);       // Select Our Texture

    for (loop=0; loop<num; loop++)               // Loop Through All The Stars
    {
        glLoadIdentity();               // Reset The View Before We Draw Each Star
        glTranslatef(0.0f,0.0f,zoom);           // Zoom Into The Screen (Using The Value In 'zoom')
        glRotatef(tilt,1.0f,0.0f,0.0f);         // Tilt The View (Using The Value In 'tilt')
        glRotatef(star[loop].angle,0.0f,1.0f,0.0f); // Rotate To The Current Stars Angle
        glTranslatef(star[loop].dist,0.0f,0.0f);    // Move Forward On The X Plane
        glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);    // Cancel The Current Stars Angle
        glRotatef(-tilt,1.0f,0.0f,0.0f);        // Cancel The Screen Tilt

        if (twinkle)                    // Twinkling Stars Enabled
        {
            // Assign A Color Using Bytes
            glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
            glBegin(GL_QUADS);          // Begin Drawing The Textured Quad
                glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
                glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
                glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
                glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
            glEnd();                // Done Drawing The Textured Quad
        }

        glRotatef(spin,0.0f,0.0f,1.0f);         // Rotate The Star On The Z Axis
        // Assign A Color Using Bytes
        glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
        glBegin(GL_QUADS);              // Begin Drawing The Textured Quad
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
        glEnd();                    // Done Drawing The Textured Quad

        spin+=0.01f;                    // Used To Spin The Stars
        star[loop].angle += float(loop)/num;      // Changes The Angle Of A Star
        star[loop].dist -= 0.01f;             // Changes The Distance Of A Star

        if (star[loop].dist<0.0f)            // Is The Star In The Middle Yet
        {
           star[loop].dist += 5.0f;          // Move The Star 5 Units From The Center
           star[loop].r = rand()%256;        // Give It A New Red Value
           star[loop].g = rand()%256;        // Give It A New Green Value
           star[loop].b = rand()%256;        // Give It A New Blue Value
        }
    }
}

按键T 的处理, 当按下T键时,会有闪烁效果,且亮度更大:

void MyGLWidget::keyReleaseEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_T:
        tp = false;
        break;
    default:
        QGLWidget::keyReleaseEvent(e);
    }
}

void MyGLWidget::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_F:
        fullscreen = !fullscreen;
        if (fullscreen) {
            showFullScreen();
        } else {
            resize(640, 480);
            showNormal();
        }
        break;
    case Qt::Key_T:
        if (!tp) {
            tp = TRUE;
            twinkle = !twinkle;
        }
        break;
    case Qt::Key_Up:
        tilt -= 0.5f;
        break;
    case Qt::Key_Down:
        tilt += 0.5f;
        break;
    case Qt::Key_PageUp:
        zoom -= 0.2f;
        break;
    case Qt::Key_PageDown:
        zoom += 0.2f;
        break;
    case Qt::Key_Escape:
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(NULL, "NeHe",
                           "Do you want to exit?",
                           QMessageBox::Yes | QMessageBox::No,
                           QMessageBox::Yes);
        if (reply == QMessageBox::Yes) {
                qApp->quit();
        }
        break;
    default:
        QGLWidget::keyPressEvent(e);
        break;
    }
}

运行效果如下所示: (T 键按下)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值