Quellcode durchsuchen

V1.2.2
1、封装了着色器程序类
2、新添加了纹理

apple vor 6 Tagen
Ursprung
Commit
17e25d224c

+ 2 - 1
demo/OpenGLDemo/CMakeLists.txt

@@ -13,6 +13,7 @@ file(GLOB LOCAL_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/GLWidget/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/GLShader/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/GLLearning/*.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/GLLearning/Shader/*.cpp
 
     ${CMAKE_SOURCE_DIR}/External/module/Logs/*.cpp
     ${CMAKE_SOURCE_DIR}/External/module/ThreadPool/*.cpp
@@ -46,7 +47,7 @@ target_include_directories(${this_exe} PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}/GLWidget
     ${CMAKE_CURRENT_SOURCE_DIR}/GLShader
     ${CMAKE_CURRENT_SOURCE_DIR}/GLLearning
-    
+    ${CMAKE_CURRENT_SOURCE_DIR}/GLLearning/Shader
     # ${CURL_INCLUDE_DIR}
     # ${FFMPEG_INCLUDE_DIR}
 )

+ 141 - 0
demo/OpenGLDemo/GLLearning/Shader/Shader.cpp

@@ -0,0 +1,141 @@
+#include "Shader.h"
+#include "spdlog/spdlog.h"
+
+#include <QFile>
+#include <qglobal.h>
+
+Shader::Shader(const QString vertexPath, const QString fragmentPath)
+{
+    /* 获取OpenGL上下文 */
+    auto ctx = QOpenGLContext::currentContext();
+    if(!ctx)
+    {
+        SPDLOG_ERROR("获取OpenGL上下文失败");
+        return;
+    }
+    m_glFuncs = ctx->functions();
+    SPDLOG_DEBUG("加载着色器代码");
+    QByteArray vertexShaderSource;
+    QByteArray fragmentShaderSource;
+    if(!loadShaderSourceFromFile(vertexPath, vertexShaderSource))
+    {
+        SPDLOG_ERROR("加载顶点着色器失败: {}", vertexPath.toStdString());
+        return;
+    }
+    if(!loadShaderSourceFromFile(fragmentPath, fragmentShaderSource))
+    {
+        SPDLOG_ERROR("加载片段着色器失败: {}", fragmentPath.toStdString());
+        return;
+    }
+
+    /* 编译着色器 */
+    SPDLOG_DEBUG("编译着色器...");
+    GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
+    GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
+
+    /* 创建着色器程序 */
+    m_programID = m_glFuncs->glCreateProgram();
+    /* 将顶点着色器和片段着色器附加到着色器程序对象上 */
+    m_glFuncs->glAttachShader(m_programID, vertexShader);
+    m_glFuncs->glAttachShader(m_programID, fragmentShader);
+    /* 链接着色器程序 */
+    m_glFuncs->glLinkProgram(m_programID);
+    printOpenGLLinkError(m_programID);
+
+    /* 删除着色器对象 */
+    m_glFuncs->glDeleteShader(vertexShader);
+    m_glFuncs->glDeleteShader(fragmentShader);
+    SPDLOG_INFO("着色器创建成功");
+}
+
+Shader::~Shader()
+{
+
+}
+
+void Shader::use()
+{
+    m_glFuncs->glUseProgram(m_programID);
+}
+
+GLuint Shader::getProgramID() const
+{
+    return m_programID;
+}
+
+/* 设置uniform工具 */
+void Shader::setBool(const QString &name, bool value) 
+{
+    auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
+    m_glFuncs->glUniform1i(location, (int)value);
+}
+
+void Shader::setInt(const QString &name, int value) 
+{
+    auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
+    m_glFuncs->glUniform1i(location, value);
+}
+
+void Shader::setFloat(const QString &name, float value) 
+{
+    auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
+    m_glFuncs->glUniform1f(location, value);
+}
+
+/* 打开着色器文件,加载着色器代码 */
+bool Shader::loadShaderSourceFromFile(const QString &filePath, QByteArray &outShaderSource)
+{
+    QFile file(filePath);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+    {
+        SPDLOG_ERROR("无法打开着色器文件: {}", filePath.toStdString());
+        SPDLOG_ERROR("错误信息: {}", file.errorString().toStdString());
+        return false;
+    }
+    outShaderSource = file.readAll();
+    file.close();
+    return true;
+}
+
+/* 编译着色器 */
+GLuint Shader::compileShader(const QByteArray &shaderSource, GLenum shaderType)
+{
+    const char* sourceCStr = shaderSource.constData();
+    /* 创建着色器对象 */
+    GLuint shader = m_glFuncs->glCreateShader(shaderType);
+    /* 加载着色器源码 */
+    m_glFuncs->glShaderSource(shader, 1, &sourceCStr, nullptr);
+    /* 编译着色器 */
+    m_glFuncs->glCompileShader(shader);
+    printOpenGLCompileError(shader);
+    return shader;
+}
+
+
+
+/* 打印编译错误 */
+void Shader::printOpenGLCompileError(GLuint errorCode)
+{
+    int sucess;
+    char infoLog[512];
+    m_glFuncs->glGetShaderiv(errorCode, GL_COMPILE_STATUS, &sucess);
+    if (!sucess)
+    {
+        m_glFuncs->glGetShaderInfoLog(errorCode, 512, nullptr, infoLog);
+        SPDLOG_ERROR("OpenGL编译错误: {}", infoLog);
+    }
+
+}
+
+/* 打印着色器链接错误 */
+void Shader::printOpenGLLinkError(GLuint errorCode)
+{
+    int sucess;
+    char infoLog[512];
+    m_glFuncs->glGetProgramiv(errorCode, GL_LINK_STATUS, &sucess);
+    if (!sucess)
+    {
+        m_glFuncs->glGetProgramInfoLog(errorCode, 512, nullptr, infoLog);
+        SPDLOG_ERROR("OpenGL链接错误: {}", infoLog);
+    }
+}

+ 41 - 0
demo/OpenGLDemo/GLLearning/Shader/Shader.h

@@ -0,0 +1,41 @@
+#ifndef __SHADER_H__
+#define __SHADER_H__
+
+#include <QOpenGLFunctions_3_3_Core>
+#include <QOpenGLFunctions>
+#include <qchar.h>
+#include <qglobal.h>
+
+
+class Shader
+{
+public:
+    Shader(const QString vertexPath, const QString fragmentPath);
+    ~Shader();
+
+    void use();
+    GLuint getProgramID() const;
+
+    /* 设置uniform工具 */
+    void setBool(const QString &name, bool value);
+    void setInt(const QString &name, int value);
+    void setFloat(const QString &name, float value);
+
+private:
+    /* 打开着色器文件,加载着色器代码 */
+    bool loadShaderSourceFromFile(const QString &filePath, QByteArray &outShaderSource);
+    /* 编译着色器 */
+    GLuint compileShader(const QByteArray &shaderSource, GLenum shaderType);
+    /* 打印编译错误 */
+    void printOpenGLCompileError(GLuint errorCode);
+    /* 打印着色器链接错误 */
+    void printOpenGLLinkError(GLuint errorCode);
+
+private:
+    GLuint m_programID = 0;
+    QOpenGLFunctions* m_glFuncs = nullptr;
+};
+
+
+
+#endif // __SHADER_H__

+ 12 - 0
demo/OpenGLDemo/GLLearning/ShaderSource/fragmentShader1.glsl

@@ -0,0 +1,12 @@
+#version 330 core
+
+in vec4 vertexColor;
+in vec2 TexCoord;
+out vec4 FragColor1;
+
+uniform sampler2D ourTexture;
+
+void main()
+{
+    FragColor1 = texture(ourTexture, TexCoord);
+}

+ 14 - 0
demo/OpenGLDemo/GLLearning/ShaderSource/vertexShader1.glsl

@@ -0,0 +1,14 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec3 aColor;
+layout (location = 2) in vec2 aTexCoord;
+
+out vec4 vertexColor;
+out vec2 TexCoord;
+
+void main()
+{
+    gl_Position = vec4(aPos, 1.0);
+    vertexColor = vec4(aColor, 1.0);
+    TexCoord = vec2(aTexCoord.x, -aTexCoord.y);
+}

+ 161 - 0
demo/OpenGLDemo/GLLearning/WidgetGL4.cpp

@@ -0,0 +1,161 @@
+#include "WidgetGL4.h"
+#include <gl/gl.h>
+#include <qimage.h>
+#include <qopenglext.h>
+#include <QTime>
+#include <QImage>
+#include <setjmp.h>
+
+
+#include "spdlog/spdlog.h"
+
+
+WidgetGL4::WidgetGL4(QWidget *parent)
+{
+
+}
+
+WidgetGL4::~WidgetGL4()
+{
+
+}
+
+
+void WidgetGL4::initializeGL()
+{
+    /* 初始化OpenGL函数 */
+    initializeOpenGLFunctions();
+
+    /* 创建VAO */
+    glGenVertexArrays(1, &m_VAO);
+    /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */
+    glBindVertexArray(m_VAO);
+
+    /* ------------------------------ 设置VBO ------------------------------ */
+    float vertices[] = {
+        /* -----位置-----   ----颜色-----       -----纹理坐标----- */
+        0.5f, 0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // 右上角
+        0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // 右下角
+        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // 左下角
+        -0.5f, 0.5f, 0.0f,  1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // 左上角
+    };
+
+    unsigned int indices[] = {
+        // 注意索引从0开始! 
+        // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
+        // 这样可以由下标代表顶点组合成矩形
+
+        0, 1, 3, // 第一个三角形
+        1, 2, 3  // 第二个三角形
+    };
+    GLuint VBO = 0;
+    /* 顶点缓冲对象 */
+    glGenBuffers(1, &VBO);
+    /* 将VBO绑定到缓冲对象上(其实是用于激活这个VBO对象,可以对这个对象进行操作了)
+       说明:OpenGL的对象操作都要依赖OpenGL提供的函数,有很多对象类型,这里将VBO绑定在 GL_ARRAY_BUFFER 上,就像放在了对应的操作台上,之后就可以对这个对象进行
+       操作,后续的一切对 GL_ARRAY_BUFFER 的操作就是对VBO的操作 */
+    glBindBuffer(GL_ARRAY_BUFFER, VBO);
+    /* 将数据拷贝到VBO中 */
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+    /* 创建EBO */
+    GLuint EBO = 0;
+    glGenBuffers(1, &EBO);
+    /* 绑定EBO */
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+    /* 将索引数据拷贝到EBO中 */
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+    /* 设置顶点链接属性 */
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), 0);
+    /* 启用顶点属性,这里是启用位置为0的顶点属性 */
+    glEnableVertexAttribArray(0);
+
+    /* 设置颜色属性 */
+    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(3*sizeof(float)));
+    glEnableVertexAttribArray(1);
+
+    /* 设置纹理坐标属性 */
+    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(6*sizeof(float)));
+    glEnableVertexAttribArray(2);
+
+    /* 解绑VBO */
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    /* 解绑VAO */
+    glBindVertexArray(0);
+
+    /* 创建着色器对象 */
+    m_shader = new Shader(":/GLLearning/ShaderSource/vertexShader1.glsl", ":/GLLearning/ShaderSource/fragmentShader1.glsl");
+    m_shaderProgam = m_shader->getProgramID();
+
+    /* 加载纹理图片 */
+    QImage image;
+    bool ret = image.load(":/image/1.jpg");
+    if (!ret)
+    {
+        SPDLOG_ERROR("加载纹理图片失败");
+        return;
+    }
+    /* 创建纹理 */
+    
+    glGenTextures(1, &m_texture1);
+    glBindTexture(GL_TEXTURE_2D, m_texture1);
+    /* 设置纹理参数 */
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    /*  将纹理图片数据传递给OpenGL */
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
+    glGenerateMipmap(GL_TEXTURE_2D);
+}
+
+void WidgetGL4::resizeGL(int w, int h)
+{
+    /* 设置视口 */
+    glViewport(0, 0, w, h);
+}
+
+void WidgetGL4::paintGL()
+{
+    /* 清屏 */
+    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    /* 绘制四边形 */
+    m_shader->use();
+    glBindVertexArray(m_VAO);
+    glBindTexture(GL_TEXTURE_2D, m_texture1);
+
+    // glDrawArrays(GL_TRIANGLES, 0, 6);
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+    /* 解绑VAO */
+    glBindVertexArray(0);
+}
+
+/* 打印编译错误 */
+void WidgetGL4::printOpenGLCompileError(GLuint errorCode)
+{
+    int sucess;
+    char infoLog[512];
+    glGetShaderiv(errorCode, GL_COMPILE_STATUS, &sucess);
+    if (!sucess)
+    {
+        glGetShaderInfoLog(errorCode, 512, nullptr, infoLog);
+        SPDLOG_ERROR("OpenGL编译错误: {}", infoLog);
+    }
+
+}
+
+/* 打印着色器链接错误 */
+void WidgetGL4::printOpenGLLinkError(GLuint errorCode)
+{
+    int sucess;
+    char infoLog[512];
+    glGetProgramiv(errorCode, GL_LINK_STATUS, &sucess);
+    if (!sucess)
+    {
+        glGetProgramInfoLog(errorCode, 512, nullptr, infoLog);
+        SPDLOG_ERROR("OpenGL链接错误: {}", infoLog);
+    }
+}

+ 39 - 0
demo/OpenGLDemo/GLLearning/WidgetGL4.h

@@ -0,0 +1,39 @@
+#ifndef __WIDGETGL4_H__
+#define __WIDGETGL4_H__
+
+#include <QOpenGLWidget>
+#include <QOpenGLFunctions_3_3_Core>
+#include <GL/gl.h>
+
+#include "Shader.h"
+
+
+class WidgetGL4 : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
+{
+    Q_OBJECT
+public:
+    explicit WidgetGL4(QWidget *parent = nullptr);
+    ~WidgetGL4() override;
+protected:
+    void initializeGL() override;
+    void resizeGL(int w, int h) override;
+    void paintGL() override;
+
+private:
+    /* 打印编译错误 */
+    void printOpenGLCompileError(GLuint errorCode);
+    /* 打印着色器链接错误 */
+    void printOpenGLLinkError(GLuint errorCode);
+
+private:
+    GLuint m_shaderProgam = 0;
+    GLuint m_VAO = 0;
+    GLuint m_texture1 = 0;
+    Shader* m_shader = nullptr;
+};
+
+
+
+
+#endif // __WidgetGL4_H__
+

+ 10 - 7
demo/OpenGLDemo/resShaderCode.qrc

@@ -1,8 +1,11 @@
+<!DOCTYPE RCC>
 <RCC>
-    <qresource prefix="/">
-        <file>shaderCode/vertexShaderRGBA.glsl</file>
-        <file>shaderCode/fragmentShaderRGBA.glsl</file>
-        <file>shaderCode/vertexShaderYUV420.glsl</file>
-        <file>shaderCode/fragmentShaderYUV420.glsl</file>
-    </qresource>
-</RCC>
+  <qresource prefix="/">
+    <file>GLLearning/ShaderSource/fragmentShader1.glsl</file>
+    <file>GLLearning/ShaderSource/vertexShader1.glsl</file>
+    <file>shaderCode/fragmentShaderRGBA.glsl</file>
+    <file>shaderCode/fragmentShaderYUV420.glsl</file>
+    <file>shaderCode/vertexShaderRGBA.glsl</file>
+    <file>shaderCode/vertexShaderYUV420.glsl</file>
+  </qresource>
+</RCC>

+ 2 - 1
demo/OpenGLDemo/widget.cpp

@@ -10,6 +10,7 @@
 #include "WidgetGL1.h"
 #include "WidgetGL2.h"
 #include "WidgetGL3.h"
+#include "WidgetGL4.h"
 
 
 Widget::Widget(QWidget *parent)
@@ -38,7 +39,7 @@ Widget::Widget(QWidget *parent)
 
     QVBoxLayout* vLayout = new QVBoxLayout(ui->widget_display);
     vLayout->setContentsMargins(0, 0, 0, 0);
-    m_gl1 = new WidgetGL3(ui->widget_display);
+    m_gl1 = new WidgetGL4(ui->widget_display);
     vLayout->addWidget(m_gl1);
 
     QTimer* timer = new QTimer(this);