使用OpenGL ES 2.0和Qt编写鼠标旋转纹理三维立方体

该示例介绍了如何使用OpenGL ES 2.0和Qt来创建一个鼠标可旋转的纹理三维立方体。通过MainWidget类处理OpenGL ES 2.0初始化、绘图和事件,GeometryEngine类负责几何图形处理。示例包含顶点和片段着色器的实现,使用四元数表示对象方向,并展示了如何加载纹理到GPU内存中。
摘要由CSDN通过智能技术生成

示例说明

实例说明了如何使用OpenGL ES 2.0和Qt编写鼠标旋转纹理三维立方体。展示了如何有效地处理多边形几何图形,以及如何为可编程图形流水线编写简单的顶点和片段着色器。此外,它还演示了如何使用四元数来表示三维对象的方向。
这个示例是为OpenGLES2.0编写的,但它也适用于桌面OpenGL,因为这个示例非常简单,大多数情况下与桌面OpenGL API都是相同的。它也可以在没有OpenGL支持的情况下进行编译,但是它只显示了一个标签,说明了OpenGL支持是必需的。

代码解析

该示例由两个类组成:
1,MainWidget类继承扩展了QGLWidget,包含OpenGL ES 2.0初始化、绘图以及鼠标和计时器事件处理
2,GeometryEngine类处理多边形几何图形。将多边形几何转换为顶点缓冲区对象,并从顶点缓冲区对象绘制几何图形。

MainWidget类定义

#include "geometryengine.h"

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QVector2D>
#include <QBasicTimer>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>

class GeometryEngine;

class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
   
    Q_OBJECT

public:
    explicit MainWidget(QWidget *parent = 0);
    ~MainWidget();

protected:
    void mousePressEvent(QMouseEvent *e) override;
    void mouseReleaseEvent(QMouseEvent *e) override;
    void timerEvent(QTimerEvent *e) override;

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

    void initShaders();
    void initTextures();

private:
    QBasicTimer timer;
    QOpenGLShaderProgram program;
    GeometryEngine *geometries;

    QOpenGLTexture *texture;

    QMatrix4x4 projection;

    QVector2D mousePressPosition;
    QVector3D rotationAxis;
    qreal angularSpeed;
    QQuaternion rotation;
};

MainWidget类实现

由于OpenGLES2.0不再支持固定的图形管道,所以它必须由我们自己来实现。这使得图形管道非常灵活,但同时也变得更加困难,因为用户必须实现图形管道才能运行最简单的示例。它还使图形管道更高效,因为用户可以决定应用程序需要什么样的管道。
首先,我们必须实现顶点着色。以顶点数据和model-view-projection matrix(MVP)为参数.利用MVP矩阵变换顶点位置到屏幕空间,并将纹理坐标传递给破片着色器。纹理坐标将自动插值在多边形表面。
在此之后,我们需要实现第二部分的图形管线-片段着色器。在这个练习中,我们需要实现处理纹理的片段着色器。它将插值的纹理坐标作为参数,并从给定的纹理中查找片段颜色。
使用QGLShaderProgram,我们可以编译、链接和绑定着色器代码到图形管道。此代码使用Qt资源文件访问着色器源代码。
QGLWidget接口实现了将纹理从QImage加载到GL纹理内存的方法。我们仍然需要使用OpenGL提供的功能来指定GL纹理单元和配置纹理筛选选项。

#include "mainwidget.h"

#include <QMouseEvent>

#include <math.h>

MainWidget::MainWidget(QWidget *parent) :
    QOpenGLWidget(parent),
    geometries(0),
    texture(0),
    angularSpeed(0)
{
   
}

MainWidget::~MainWidget()
{
   
    //在删除纹理和缓冲区时,确保上下文是当前的。
    makeCurrent();
    delete texture;
    delete geometries;
    doneCurrent();
}

//! [0]
void MainWidget::mousePressEvent(QMouseEvent *e)
{
   
    // 保存鼠标按下位置
    mousePressPosition = QVector2D(e->localPos());
}

void MainWidget::mouseReleaseEvent(QMouseEvent *e)
{
   
    // 鼠标释放位置-鼠标按下位置
    QVector2D diff = QVector2D(e->localPos()) - mousePressPosition;

    //旋转轴垂直于鼠标位置差矢量
    QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();

    // 加速角速度相对于鼠标扫掠的长度
    qreal acc = diff.length() / 100.0;

    // 计算新的旋转轴为加权和
    rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();

    // 增加角速度
    angularSpeed += acc;
}

void MainWidget::timerEvent(QTimerEvent *)
{
   
    // 降低角速度(摩擦)
    angularSpeed *= 0.99;

    // 当速度低于阈值时停止旋转
    if (angularSpeed < 0.01) {
   
        angularSpeed = 0.0;
    } else 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值