您的位置:首页 > 编程语言 > Qt开发

Qt_OpenGL:光照纹理滤波色彩混合小测

2014-12-08 20:46 513 查看
Qt_OpenGL:光照纹理滤波色彩混合小测



此测试程序包含了光照、纹理滤波和色彩融合等知识点。

//.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QtOpenGL>
#include <QWidget>

class GLWidget : public QGLWidget
{
    Q_OBJECT

public:
    explicit GLWidget(QGLWidget *parent = 0);
    ~GLWidget();

protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int width, int height);
    void keyPressEvent(QKeyEvent *e);
    void loadTextures();
    bool fullscreen;
    GLuint texture[3];

private:
    float rotate_angle;
    float zoom;
    float rotate_speed;
    int filter;
    bool light;
    bool blend;

};

#endif // GLWIDGET_H


//.cpp

<pre name="code" class="cpp"><pre name="code" class="cpp">#include "glwidget.h"
#include <QtGui>
#include <QtCore>
#include <QtOpenGL>
#include <glut.h>

static const GLfloat light_ambient[4]={0.5, 0.5, 0.5, 1.0};
static const GLfloat light_diffuse[4]={1.0, 1.0, 1.0, 1.0};
static const GLfloat light_position[4]={0.0, 0.0, 2.0, 0.0};

GLWidget::GLWidget(QGLWidget *parent) :
    QGLWidget(parent)
{
  //  setCaption("The Opengl for Qt Framework");
    fullscreen = false;
    rotate_angle = 0.0;
    zoom = -5.0;
    rotate_speed = 3.0;
    filter = 0;
    light = false;
    blend = false;
}

void GLWidget::initializeGL()
{
    setGeometry(300, 150, 500, 500);//设置窗口初始位置和大小
    loadTextures();
    glEnable(GL_TEXTURE_2D);//允许采用2D纹理技术
    glShadeModel(GL_SMOOTH);//设置阴影平滑模式
    glClearColor(0.0, 0.0, 0.0, 0);//改变窗口的背景颜色,不过我这里貌似设置后并没有什么效果
    glClearDepth(1.0);//设置深度缓存
    glEnable(GL_DEPTH_TEST);//允许深度测试
    glDepthFunc(GL_LEQUAL);//设置深度测试类型
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//进行透视校正

    /*opengl中支持8个光源,即GL_LIGHT0~GL_LIGHT7*/
    glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);//指定光源1的环境光参数
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);//指定光源1的漫射光参数
    glLightfv(GL_LIGHT1, GL_POSITION, light_position);//指定光源1的位置
    glEnable(GL_LIGHT1);//允许光源1的使用
  //  glEnable(GL_LIGHTING);//我们还需要启动总光源开关,默认的时候不开,后面的L键来控制开启和关闭

    glColor4f(1.0, 1.0, 1.0, 0.5);//后面的步骤都是以全亮绘制物体,并且50%的透明度
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}

void GLWidget::paintGL()
{
    //glClear()函数在这里就是对initializeGL()函数中设置的颜色和缓存深度等起作用
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /*下面开始画立方体,并对其进行纹理映射*/
    glLoadIdentity();
    glTranslatef(0.0, 0.0, zoom);
    glRotatef(rotate_angle, -0.4f, 0.4f, -1.0f);
    glBindTexture(GL_TEXTURE_2D, texture[filter]);//这句代码一定要,因为在initializeGL()函数中已绑定一个固定的纹理目标了
    glBegin(GL_QUADS);
    //上顶面
    glNormal3f(0.0, 1.0, 0.0);//该函数指定是法线的方向为向量(x, y, z)方向,在使用光源且对空间物体进行纹理映射时,
                              //每个面都需要指定其法线的方向,否则会出现各种意外的结果。
    glTexCoord2f(0.0, 1.0);//将2D的纹理坐标映射到3D的空间物体表面上
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(1.0f, 1.0f, -1.0f);
    //下顶面
    glNormal3f(0.0, -1.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(1.0f, -1.0f, -1.0f);
    //正前面
    glNormal3f(0.0, 0.0, 1.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(1.0f, 1.0f, 1.0f);
    //右侧面
    glNormal3f(1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(1.0f, 1.0f, -1.0f);
    //背后面
    glNormal3f(0.0, 0.0, -1.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(1.0f, 1.0f, -1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    //左侧面
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glEnd();
    rotate_angle += rotate_speed;
}

void GLWidget::resizeGL(int width, int height)
{
    if(0 == height)
        height = 1;//防止一条边为0
    glViewport(0, 0, (GLint)width, (GLint)height);//重置当前视口,本身不是重置窗口的,只不过是这里被Qt给封装好了
    glMatrixMode(GL_PROJECTION);//选择投影矩阵
    glLoadIdentity();//重置选择好的投影矩阵
    gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);//建立透视投影矩阵
    glMatrixMode(GL_MODELVIEW);//以下2句和上面出现的解释一样
    glLoadIdentity();

}
void GLWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
        /*L键位开启光照的开关*/
        case Qt::Key_L:
            light = !light;
            if(!light)
                glDisable(GL_LIGHTING);
            else
                glEnable(GL_LIGHTING);
            updateGL();
            break;
        /*B键位选择是否采用色彩融合*/
        case Qt::Key_B:
            blend = !blend;
            if(blend)
                {
                    glEnable(GL_BLEND);
                    glDisable(GL_DEPTH_TEST);
                }
            else
                {
                    glDisable(GL_BLEND);
                    glEnable(GL_DEPTH_TEST);
                }
            updateGL();
            break;
        /*F键位选择纹理滤波的方式*/
        case Qt::Key_F:
            filter += 1;
            if(filter > 2)
                filter = 0;
            updateGL();
            break;
        /*PageUp键为将木箱移到屏幕内部方向*/
        case Qt::Key_PageUp:
            zoom -= 0.2;
            updateGL();
            break;
        /*PageDown键为将木箱移到屏幕外部方向*/
        case Qt::Key_PageDown:
            zoom += 0.2;
            updateGL();
            break;
        /*Up键为加快立方体旋转的速度*/
        case Qt::Key_Up:
            rotate_speed += 1.0;
            updateGL();
            break;
        /*Down键为减慢立方体旋转的速度*/
        case Qt::Key_Down:
            rotate_speed -= 1.0;
            updateGL();
            break;
        /*F1键为全屏和普通屏显示切换键*/
        case Qt::Key_F1:
            fullscreen = !fullscreen;
            if(fullscreen)
                showFullScreen();
            else
            {
                setGeometry(300, 150, 500, 500);
                showNormal();
            }
            updateGL();
            break;
        /*Ese为退出程序键*/
        case Qt::Key_Escape:
            close();
    }
}

/*加载纹理*/
void GLWidget::loadTextures()
{
    QImage tex, buf;
    if(!buf.load(":resources/c.jpg"))
   // if(!buf.load(":resources/c.jpg"))
    {
        qWarning("Cannot open the image...");
        QImage dummy(128, 128, QImage::Format_RGB32);//当没找到所需打开的图片时,创建一副128*128大小,深度为32位的位图
        dummy.fill(Qt::green);
        buf = dummy;
    }
    tex = convertToGLFormat(buf);//将Qt图片的格式buf转换成opengl的图片格式tex
    glGenTextures(3, &texture[0]);//开辟3个纹理内存,索引指向texture[0]

    /*建立第一个纹理*/
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    /*建立第二个纹理*/
    glBindTexture(GL_TEXTURE_2D, texture[1]);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, 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);

    /*建立第三个纹理*/
    glBindTexture(GL_TEXTURE_2D, texture[2]);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, tex.width(), tex.height(), GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
    //该函数对所加载的纹理像素没有要求是2的n次方,可以是任意的像素
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    //mipmap方式是当物体很远时,也能保留很好的细节,所以它的运算量很大,速度很慢,这里GL_LINEAR_MIPMAP_NEAREST是混合使用
}

GLWidget::~GLWidget()
{
}





//main.cpp

#include "glwidget.h"
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    GLWidget w;
    w.show();
    return a.exec();
}


//运行截图:












内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: