opengl

1.头文件

#ifndef COPENGLWIDGET_H
#define COPENGLWIDGET_H

#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 

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

你可能感兴趣的:(opengl)