Преглед на файлове

V1.2
1、重新完成了OpenGL的学习demo

apple преди 1 седмица
родител
ревизия
c5681de6a7

+ 75 - 4
demo/OpenGLDemo/GLLearning/WidgetGL1.cpp

@@ -22,15 +22,20 @@ void WidgetGL1::initializeGL()
     /* 初始化OpenGL函数 */
     initializeOpenGLFunctions();
 
+    /* 创建VAO */
+    glGenVertexArrays(1, &m_VAO);
+    /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */
+    glBindVertexArray(m_VAO);
 
+    /* ------------------------------ 设置VBO ------------------------------ */
     /* 顶点输入 */
     float vertices[] = {
         -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
     };
+    GLuint VBO = 0;
     /* 顶点缓冲对象 */
-    GLuint VBO;
     glGenBuffers(1, &VBO);
     /* 将VBO绑定到缓冲对象上(其实是用于激活这个VBO对象,可以对这个对象进行操作了)
        说明:OpenGL的对象操作都要依赖OpenGL提供的函数,有很多对象类型,这里将VBO绑定在 GL_ARRAY_BUFFER 上,就像放在了对应的操作台上,之后就可以对这个对象进行
@@ -39,7 +44,17 @@ void WidgetGL1::initializeGL()
     /* 将数据拷贝到VBO中 */
     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
 
-    /* 顶点着色器 */
+    /* 设置顶点链接属性 */
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0);
+    /* 启用顶点属性,这里是启用位置为0的顶点属性 */
+    glEnableVertexAttribArray(0);
+
+    /* 解绑VBO */
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    /* 解绑VAO */
+    glBindVertexArray(0);
+
+    /* ------------------------------ 顶点着色器 ------------------------------ */
     const char* vertexShaderSource = R"(
         #version 330 core
         layout (location = 0) in vec3 aPos;
@@ -56,16 +71,59 @@ void WidgetGL1::initializeGL()
     /* 编译着色器 */
     glCompileShader(vertexShader);
     printOpenGLCompileError(vertexShader);
+
+    /* ------------------------------ 片段着色器 ------------------------------ */
+    const char* fragmentShaderSource = R"(
+        #version 330 core
+        out vec4 FragColor;
+
+        void main()
+        {
+            FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
+        }
+    )";
+    /* 创建片段着色器对象 */
+    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+    /* 加载片段着色器源码 */
+    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
+    /* 编译着色器 */
+    glCompileShader(fragmentShader);
+    printOpenGLCompileError(fragmentShader);
+
+    /* ------------------------------ 着色器程序对象 ------------------------------ */
+    m_shaderProgam = glCreateProgram();
+    /* 将顶点着色器和片段着色器附加到着色器程序对象上 */
+    glAttachShader(m_shaderProgam, vertexShader);
+    glAttachShader(m_shaderProgam, fragmentShader);
+    /* 链接着色器程序 */
+    glLinkProgram(m_shaderProgam);
+    /* 销毁顶点着色器和片段着色器 */
+    glDeleteShader(vertexShader);
+    glDeleteShader(fragmentShader);
+
+
+    
+    
 }
 
 void WidgetGL1::resizeGL(int w, int h)
 {
-
+    /* 设置视口 */
+    glViewport(0, 0, w, h);
 }
 
 void WidgetGL1::paintGL()
 {
-
+    /* 清屏 */
+    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    /* 绘制三角形 */
+    glUseProgram(m_shaderProgam);
+    glBindVertexArray(m_VAO);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    /* 解绑VAO */
+    glBindVertexArray(0);
 }
 
 /* 打印编译错误 */
@@ -81,3 +139,16 @@ void WidgetGL1::printOpenGLCompileError(GLuint errorCode)
     }
 
 }
+
+/* 打印着色器链接错误 */
+void WidgetGL1::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);
+    }
+}

+ 5 - 0
demo/OpenGLDemo/GLLearning/WidgetGL1.h

@@ -22,7 +22,12 @@ protected:
 private:
     /* 打印编译错误 */
     void printOpenGLCompileError(GLuint errorCode);
+    /* 打印着色器链接错误 */
+    void printOpenGLLinkError(GLuint errorCode);
 
+private:
+    GLuint m_shaderProgam = 0;
+    GLuint m_VAO = 0;
 };
 
 

+ 181 - 0
demo/OpenGLDemo/GLLearning/WidgetGL2.cpp

@@ -0,0 +1,181 @@
+#include "WidgetGL2.h"
+#include <gl/gl.h>
+#include <qopenglext.h>
+
+
+#include "spdlog/spdlog.h"
+
+
+WidgetGL2::WidgetGL2(QWidget *parent)
+{
+
+}
+
+WidgetGL2::~WidgetGL2()
+{
+
+}
+
+
+void WidgetGL2::initializeGL()
+{
+    /* 初始化OpenGL函数 */
+    initializeOpenGLFunctions();
+
+    /* 创建VAO */
+    glGenVertexArrays(1, &m_VAO);
+    /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */
+    glBindVertexArray(m_VAO);
+
+    /* ------------------------------ 设置VBO ------------------------------ */
+    /* 顶点输入 */
+    float vertices[] = {
+        -0.8f, -0.5f, 0.0f,
+        -0.2f, -0.5f, 0.0f,
+        -0.5f,  0.5f, 0.0f,
+        -0.2f, -0.5f, 0.0f,
+        0.8f, -0.5f, 0.0f,
+        0.3f,  0.5f, 0.0f
+    };
+    // float vertices[] = {
+    //     0.5f, 0.5f, 0.0f,   // 右上角
+    //     0.5f, -0.5f, 0.0f,  // 右下角
+    //     -0.5f, -0.5f, 0.0f, // 左下角
+    //     -0.5f, 0.5f, 0.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, 3*sizeof(float), 0);
+    /* 启用顶点属性,这里是启用位置为0的顶点属性 */
+    glEnableVertexAttribArray(0);
+
+    /* 解绑VBO */
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    /* 解绑VAO */
+    glBindVertexArray(0);
+
+    /* ------------------------------ 顶点着色器 ------------------------------ */
+    const char* vertexShaderSource = R"(
+        #version 330 core
+        layout (location = 0) in vec3 aPos;
+
+        void main()
+        {
+            gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
+        }
+    )";
+    /* 创建顶点着色器对象 */
+    GLuint vertexShader  = glCreateShader(GL_VERTEX_SHADER);
+    /* 加载顶点着色器源码 */
+    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
+    /* 编译着色器 */
+    glCompileShader(vertexShader);
+    printOpenGLCompileError(vertexShader);
+
+    /* ------------------------------ 片段着色器 ------------------------------ */
+    const char* fragmentShaderSource = R"(
+        #version 330 core
+        out vec4 FragColor;
+
+        void main()
+        {
+            FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
+        }
+    )";
+    /* 创建片段着色器对象 */
+    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+    /* 加载片段着色器源码 */
+    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
+    /* 编译着色器 */
+    glCompileShader(fragmentShader);
+    printOpenGLCompileError(fragmentShader);
+
+    /* ------------------------------ 着色器程序对象 ------------------------------ */
+    m_shaderProgam = glCreateProgram();
+    /* 将顶点着色器和片段着色器附加到着色器程序对象上 */
+    glAttachShader(m_shaderProgam, vertexShader);
+    glAttachShader(m_shaderProgam, fragmentShader);
+    /* 链接着色器程序 */
+    glLinkProgram(m_shaderProgam);
+    /* 销毁顶点着色器和片段着色器 */
+    glDeleteShader(vertexShader);
+    glDeleteShader(fragmentShader);
+
+
+    
+    
+}
+
+void WidgetGL2::resizeGL(int w, int h)
+{
+    /* 设置视口 */
+    glViewport(0, 0, w, h);
+}
+
+void WidgetGL2::paintGL()
+{
+    /* 清屏 */
+    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    /* 绘制四边形 */
+    glUseProgram(m_shaderProgam);
+    glBindVertexArray(m_VAO);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+    // glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+    /* 解绑VAO */
+    glBindVertexArray(0);
+}
+
+/* 打印编译错误 */
+void WidgetGL2::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 WidgetGL2::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);
+    }
+}

+ 37 - 0
demo/OpenGLDemo/GLLearning/WidgetGL2.h

@@ -0,0 +1,37 @@
+#ifndef __WIDGETGL2_H__
+#define __WIDGETGL2_H__
+
+
+#include <QOpenGLWidget>
+#include <QOpenGLFunctions_3_3_Core>
+#include <GL/gl.h>
+
+
+
+class WidgetGL2 : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
+{
+    Q_OBJECT
+public:
+    explicit WidgetGL2(QWidget *parent = nullptr);
+    ~WidgetGL2() 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;
+};
+
+
+
+
+#endif // __WIDGETGL2_H__
+

+ 6 - 3
demo/OpenGLDemo/widget.cpp

@@ -2,11 +2,12 @@
 #include "./ui_widget.h"
 
 #include <QTimer>
+#include <qboxlayout.h>
 #include "spdlog/spdlog.h"
 
 #include "PlayerGLWidget2.h"
 #include "WidgetGL1.h"
-
+#include "WidgetGL2.h"
 
 
 Widget::Widget(QWidget *parent)
@@ -33,8 +34,10 @@ Widget::Widget(QWidget *parent)
     // m_timer.setSingleShot(false);
     // m_timer.start(10); // 60 FPS
 
-    auto gl1 = new WidgetGL1(ui->widget_display);
-    
+    QVBoxLayout* vLayout = new QVBoxLayout(ui->widget_display);
+    vLayout->setContentsMargins(0, 0, 0, 0);
+    m_gl1 = new WidgetGL2(ui->widget_display);
+    vLayout->addWidget(m_gl1);
 }
 
 Widget::~Widget()

+ 2 - 0
demo/OpenGLDemo/widget.h

@@ -6,6 +6,7 @@
 #include "PlayerGLWidget.h"
 #include "PlayerGLWidget2.h"
 #include <QTimer>
+#include <qwidget.h>
 
 QT_BEGIN_NAMESPACE
 namespace Ui { class Widget; }
@@ -28,6 +29,7 @@ private:
     Ui::Widget *ui;
 
     PlayerGLWidget *m_playerGLWidget = nullptr;
+    QWidget* m_gl1 = nullptr;
 
     QTimer m_timer;