Qt使用OpenGL实现立方体贴图

效果如下:

在这里插入图片描述

实现代码3个文件,TestWidget.h、TestWidget.cpp、main.cpp。

TestWidget.h:

#ifndef TESTWIDGET_H
#define TESTWIDGET_H

#include <QGLWidget>

class TestWidget : public QGLWidget
{
    Q_OBJECT

public:
    explicit TestWidget(QWidget *parent = nullptr);
    ~TestWidget() override;

protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int w, int h) override;
    virtual void paintGL() override;

    virtual void keyPressEvent(QKeyEvent *e) override;
    virtual void timerEvent(QTimerEvent *event) override;

private:
    void loadGLTexture();

private:
    GLfloat xRot;
    GLfloat yRot;
    GLfloat zRot;
    GLuint texture[1];
};

#endif // TESTWIDGET_H

TestWidget.cpp:

#include "TestWidget.h"
#include <QKeyEvent>
#include <QCoreApplication>

TestWidget::TestWidget(QWidget *parent)
    : QGLWidget(parent)
{
    xRot = 10.0;
    yRot = 10.0;
    zRot = 10.0;

    resize(500,400);
    startTimer(10);
}

TestWidget::~TestWidget()
{

}

// 加载纹理
void TestWidget::loadGLTexture()
{
    // 加载图片
    QImage buf;
    if(!buf.load(":/logo.png"))
    {
        QImage dummy(128, 128, QImage::Format_RGB32);
        dummy.fill(QColor(Qt::green).rgb());
        buf = dummy;
    }
    QImage tex = QGLWidget::convertToGLFormat(buf);

    // 创建一个纹理名字
    glGenTextures(1, &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_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

// 初始化opengl
void TestWidget::initializeGL()
{
    // 载入纹理
    loadGLTexture();

    // 启用纹理
    glEnable(GL_TEXTURE_2D);

    // 其他初始化
    glShadeModel(GL_SMOOTH);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(1.0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

// 尺寸改变
void TestWidget::resizeGL(int w, int h)
{
    h = (h == 0) ? 1 : h;

    glViewport(0, 0, (GLint)w, (GLint)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
//    gluPerspective(45.0,(GLfloat)w/(GLfloat)h,0.1,100.0);

    GLfloat zNear = 0.1;
    GLfloat zFar = 100.0;
    GLfloat aspect = (GLfloat)w / (GLfloat)h;
    GLfloat fH = tan(GLfloat(90.0 / 360.0 * 3.14159)) * zNear;
    GLfloat fW = fH * aspect;
    glFrustum(-fW, fW, -fH, fH, zNear, zFar);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 绘制代码,着色分为两种:平滑着色GL_SMOOTH、单调着色GL_FLAT
void TestWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glBindTexture(GL_TEXTURE_2D, texture[0]);

    // 立方体
    glPushMatrix();
    glTranslatef(-0.5, -0.5, -3.0);
    glRotatef(xRot, 1.0, 0.0, 0.0);
    glRotatef(yRot, 0.0, 1.0, 0.0);
    glRotatef(zRot, 0.0, 0.0, 1.0);

    glBegin(GL_QUADS);
    {
        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 0.0, 0.0);
        glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(0.0, 1.0, 0.0);

        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 1.0, 1.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(0.0, 0.0, 1.0);
        glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 0.0, 1.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0);

        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(0.0, 1.0, 0.0);
        glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 1.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(0.0, 0.0, 1.0);

        glTexCoord2f(0.0, 0.0); glVertex3f(1.0, 0.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(1.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, 0.0, 1.0);

        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 1.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(0.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, 0.0);

        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f(0.0, 0.0, 1.0);
        glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 0.0, 1.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 0.0, 0.0);
    }
    glEnd();
    glPopMatrix();
}

// 全屏切换
void TestWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_Escape:
        showNormal();
        break;
    case Qt::Key_F1:
        showFullScreen();
        break;
    default:
        break;
    }
}

// 定时滚动
void TestWidget::timerEvent(QTimerEvent *event)
{
    xRot += 0.5;
    yRot += 0.5;
    zRot += 0.5;
    updateGL(); // 重新绘制
}

main.cpp:

#include <QApplication>
#include "TestWidget.h"

int main( int argc, char **argv )
{
  QApplication a(argc,argv);

  TestWidget w;
  w.show();
  
  return a.exec();
}

本文涉及工程代码:

https://gitee.com/bailiyang/cdemo/tree/master/Qt/60OpenGLTest/OpenGlTest

参考链接:

《Qt OpenGL纹理映射》

《Qt OpenGL教程》

《QT5.7中使用OpenGL开发记录(一)---- 第一个工程》

《立方体贴图》



若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值