1. 程式人生 > >Qt+OpenGL之紋理貼圖

Qt+OpenGL之紋理貼圖

NeNe的程式碼中是載入到了一個正方體當中,程式碼很長。其實單純的想要紋理貼圖是很方便的。具體的紋理貼圖技術在NeNe的書中的有很詳細的介紹。

.h檔案:

#ifndef PICGLWIDGET_H
#define PICGLWIDGET_H

#include <QtGui/QWidget>
#include <QWidget>
#include <QtOpenGL>
#include <GL/GLU.h>
#include <gl/gl.h>

class PicGLWidget : public QGLWidget
{
    Q_OBJECT
    
public:
    explicit PicGLWidget(QWidget *parent = 0);
    ~PicGLWidget();

protected:
    void loadGLTextures ();

    void initializeGL();  //初始化OpenGL視窗部件
    void paintGL();  //繪製整個OpenGL視窗,只要有更新發生,這個函式就會被呼叫
    void resizeGL(int width, int height); //處理視窗大小變化事件的,引數是新狀態下的寬和高
    void keyPressEvent(QKeyEvent *e);  //滑鼠處理函式

protected:
    bool fullscreen;  //判斷是否全屏的變數
    float Zyot;
    GLuint texture[1];
};

#endif // PICGLWIDGET_H

.cpp檔案:
#include "picglwidget.h"

PicGLWidget::PicGLWidget(QWidget *parent)
    : QGLWidget(parent)
{
    fullscreen = false;
    Zyot = -10.0f;
}

void PicGLWidget::initializeGL()
{
    setGeometry(300, 150, 500, 500);//設定視窗初始位置和大小
    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);//進行透視校正

    glBlendFunc(GL_SRC_ALPHA, GL_ONE);//源畫素因子採用alpha通道值,目標畫素因子採用1.0
    glEnable(GL_BLEND);
}

void PicGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, Zyot);
    glBindTexture(GL_TEXTURE_2D, texture[0]);//繫結紋理目標
    glBegin(GL_QUADS);
        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 PicGLWidget::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);//建立透視投影矩陣
      glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE);
      glMatrixMode(GL_MODELVIEW);//以下2句和上面出現的解釋一樣
      glLoadIdentity();
}

void PicGLWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
        {
            /*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 PicGLWidget::loadGLTextures()
{
    QImage tex, buf;
        if(!buf.load("./images/2.bmp"))//這個時候因為debug沒有在外面,所以圖片資料夾就是本目錄了
        {
            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(1, &texture[0]);//開闢3個紋理記憶體,索引指向texture[0]

        /*建立第一個紋理*/
        glBindTexture(GL_TEXTURE_2D, texture[0]);//將建立的紋理記憶體指向的內容繫結到紋理物件GL_TEXTURE_2D上,經過這句程式碼後,以後對
                                                //GL_TEXTURE_2D的操作的任何操作都同時對應與它所繫結的紋理物件
        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);//當所顯示的紋理比載入進來的紋理小時,採用GL_NEAREST的方法來處理
                                                                          //GL_NEAREST方式速度非常快,因為它不是真正的濾波,所以佔用記憶體非常
                                                                          // 小,速度就快了
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//當所顯示的紋理比載入進來的紋理大時,採用GL_NEAREST的方法來處理
}

PicGLWidget::~PicGLWidget()
{
    
}

當然,你需要在pro檔案中新增opengl。