opengl

1.头文件

#ifndef COPENGLWIDGET_H
#define COPENGLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QMouseEvent>

class COPenGLWidget : public QOpenGLWidget, public QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    COPenGLWidget(QWidget* parent = nullptr);

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

    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    virtual void wheelEvent(QWheelEvent *event) override;
private:
    void Init();
    void ShaderProgram();   // 着色器程序
    void GetShaderSource(const QString &path, std::string &str);    // 获取着色器源码
    void BindShader();  // 绑定着色器
    bool CheckCompileErrors(unsigned int shader, std::string type); // 检查着色器编译错误
    void DrawCoordinate();  // 坐标轴
private:
    std::string m_vShaderSource;    // 顶点着色器
    std::string m_fShaderSource;    // 片段着色器
    unsigned int m_coordId;
    int m_mousebuttonStatus;    //鼠标按钮状态,0:松开状态,1:左键按下,2:右键按下
    QPoint m_leftmousebuttonPos;    // 左键按下位置
    QPoint m_rightmousebuttonPos;   // 右键按下位置
    float m_pitch;  // 俯仰角
    float m_yaw;    // 偏航角
    float m_roll;   // 翻滚角
    float m_zoom;   // 缩放
};

#endif // COPENGLWIDGET_H

2.源文件

#include "copenglwidget.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <QFile>
#include <QTextStream>

const int src_width = 800;
const int src_height = 600;
const float PI = 3.141593f;

COPenGLWidget::COPenGLWidget(QWidget* parent) :
    QOpenGLWidget(parent),
    m_coordId(0),
    m_mousebuttonStatus(0),
    m_pitch(0.0f), m_yaw(0.0f), m_roll(0.0f)
{
    QSurfaceFormat format;
    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setVersion(3, 3);
    setFormat(format);

    Init();
}

void COPenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    ShaderProgram();
}

void COPenGLWidget::resizeGL(int w, int h)
{

}

void COPenGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    DrawCoordinate();
}

void COPenGLWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton) {
        m_mousebuttonStatus = 1;
        m_leftmousebuttonPos = event->pos();
    } else if (event->button() == Qt::RightButton) {
        m_mousebuttonStatus = 2;
        m_rightmousebuttonPos = event->pos();
    }
}

void COPenGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
     m_mousebuttonStatus = 0;
     update();
}

void COPenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(m_mousebuttonStatus == 1) {
        float x = event->pos().x() - m_leftmousebuttonPos.x();
        float y = event->pos().y() - m_leftmousebuttonPos.y();
        m_pitch += PI * x / rect().width();
        m_yaw += PI * y / rect().height();
        m_leftmousebuttonPos = event->pos();
        update();
    } else if (m_mousebuttonStatus == 2) {
        float x = event->pos().x() - m_rightmousebuttonPos.x();
        if(x > 0) {
            m_roll += 0.05;
        } else {
            m_roll -= 0.05;
        }
        m_rightmousebuttonPos = event->pos();
        update();
    }
}

void COPenGLWidget::wheelEvent(QWheelEvent *event)
{
    if(event->delta() > 0) {
        m_zoom *= 1.05;
    } else {
        m_zoom *= 0.95;
    }
    if(m_zoom < 0.2) {
        m_zoom = 0.2;
    }
    update();
}

void COPenGLWidget::Init()
{

}

void COPenGLWidget::ShaderProgram()
{
    // 获取着色器源码
    GetShaderSource(":/shaders/axis.vert", m_vShaderSource);
    GetShaderSource(":/shaders/axis.frag", m_fShaderSource);
    // 绑定着色器
    BindShader();
}

void COPenGLWidget::GetShaderSource(const QString &path, std::string &str)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    str = in.readAll().toStdString();
    file.close();
}

void COPenGLWidget::BindShader()
{
    const char* vShaderSource = m_vShaderSource.c_str();
    const char* fShaderSource = m_fShaderSource.c_str();
    // 顶点着色器
    unsigned int vertex = glCreateShader(GL_VERTEX_SHADER); // 创建顶点着色器
    glShaderSource(vertex, 1, &vShaderSource, nullptr);     // 绑定着色器
    glCompileShader(vertex);    // 编译着色器
    CheckCompileErrors(vertex, "VERTEX");   // 检查着色器编译错误
    // 片段着色器
    unsigned int fragment = glCreateShader(GL_FRAGMENT_SHADER); // 创建片段着色器
    glShaderSource(fragment, 1, &fShaderSource, nullptr);   // 绑定着色器
    glCompileShader(fragment);  // 编译着色器
    CheckCompileErrors(fragment, "FRAGMENT");   // 检查着色器编译错误
    // 链接着色器
    m_coordId = glCreateProgram();
    glAttachShader(m_coordId, vertex);
    glAttachShader(m_coordId, fragment);
    glLinkProgram(m_coordId);
    CheckCompileErrors(m_coordId, "PROGRAM");   // 检查链接错误
    // 删除着色器
    glDeleteShader(vertex);
    glDeleteShader(fragment);
}

bool COPenGLWidget::CheckCompileErrors(unsigned int shader, std::string type)
{
    int success;
    char infoLog[512];
    if(type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if(!success) {
            glGetShaderInfoLog(shader, 512, nullptr, infoLog);
            return false;
        }
    } else {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if(!success) {
            glGetProgramInfoLog(shader, 512, nullptr, infoLog);
            return false;
        }
    }
    return true;
}

void COPenGLWidget::DrawCoordinate()
{
    float vertex[] = {
        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f
    };
    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof (vertex), vertex, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);


    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glUseProgram(m_coordId);

    // 投影矩阵
    glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)src_width / (float)src_height, 0.1f, 1000.0f);
    // 视图矩阵
    glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 10.0f);     // 摄像机位置
    glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, 0.0f);    // 摄像机 指向的方向
    glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);       // 上向量
    glm::mat4 view = glm::lookAt(cameraPos, cameraFront, cameraUp); // 视图矩阵
    //  模型矩阵
    glm::mat4 model = glm::mat4();
    model  = glm::translate(model, glm::vec3(-0.45f, -0.35f, 9.0f));
    model = glm::rotate(model, m_pitch, glm::vec3(1.0f, 0.0f, 0.0f));
    model = glm::rotate(model, m_yaw, glm::vec3(0.0f, 1.0f, 0.0f));
    model = glm::rotate(model, m_roll, glm::vec3(0.0f, 0.0f, 1.0f));

    //  返回 全局变量的位置
    unsigned int modelLoc = glGetUniformLocation(m_coordId, "model");
    unsigned int viewLoc  = glGetUniformLocation(m_coordId, "view");
    unsigned int projectLoc = glGetUniformLocation(m_coordId, "projection");
    // 将矩阵 传入管线
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]);
    glUniformMatrix4fv(projectLoc, 1, GL_FALSE, &projection[0][0]);

    glBindVertexArray(VAO);
    glDrawArrays(GL_LINES, 0, 6);

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
}

3.顶点着色器
axis.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec3 ourColor;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main(){
    gl_Position = projection * view * model * vec4(aPos, 1.0f);
    ourColor = aColor;
}

4.片段着色器
axis.frag

#version 330 core
out vec4 FragColor;
in vec3 ourColor;

void main(){
    FragColor = vec4(ourColor, 1.0f);
}

5.结果


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容