Qt5.12 + OpenGL 创建第一个多边形Core版

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,可以点个在看,让它可以帮助到更多老铁~

原教程地址:

https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

程序参考地址:

https://blog.csdn.net/z136411501/article/details/79834381

        这里介绍第二种方法,使用QOpenGLFunctions_3_3_Core类对象,Core类其实是一种Qt对OpenGL特定版本的包装类对象,可以直接使用该版本OpenGL的所有函数。

效果图如下:

    代码和之前比“几乎”没变,只是把所有gl开头的函数都换成了

m_core->gl ******来调用了。

头文件如下:

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>


class MyGLWidget : public QOpenGLWidget
{
    Q_OBJECT


public:
    MyGLWidget();


    ~MyGLWidget();


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


private:
    //顶点缓冲对象 Vertex Buffer Object,VBO,教程中第一个出现的OpenGL对象
    GLuint VBO;               
    GLuint VAO;


    GLuint EBO;


    GLuint m_shaderProgram;    //着色器程序对象
    QOpenGLFunctions_3_3_Core *m_core;

        这里我们不再继承 QOpenGLExtraFunctions,对gl相关函数的调用则是通过m_core进行。

        源文件如下:

//着色器语言GLSL(OpenGL Shading Language)编写的顶点着色器
static const char *vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec3 aPos;\n"
        "void main(){\n"
        "  gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
        "}\n\0";




//着色器语言GLSL(OpenGL Shading Language)编写的片段着色器
static const char *fragmentShaderSource =
        "#version 330 core\n"
        "out vec4 FragColor;\n"
        "void main(){\n"
        "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
        "}\n\0";


#if 0
    #define TRIANGLE
#elif 1
    #define RECTANGLE
#endif


MyGLWidget::MyGLWidget()
{


}


MyGLWidget::~MyGLWidget()
{


}


void MyGLWidget::initializeGL()
{


    m_core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();//获取上下文


    //着色器部分
    GLuint vertexShader = m_core->glCreateShader(GL_VERTEX_SHADER);                //创建顶点着色器对象
    m_core->glShaderSource(GLuint(vertexShader), 1, &vertexShaderSource, nullptr); //着色器源码附加到着色器对象
    m_core->glCompileShader(GLuint(vertexShader));                                 //编译


    int is_success;                                             //检查是否编译成功,未成功则需返回错误
    char infoLog[512];
    m_core->glGetShaderiv(GLuint(vertexShader), GL_COMPILE_STATUS, &is_success);
    if (!is_success)
    {
        m_core->glGetShaderInfoLog(GLuint(vertexShader), 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << infoLog ;
    }




    GLuint fragmentShader = m_core->glCreateShader(GL_FRAGMENT_SHADER);  //创建片段着色器对象,与顶点着色器相似
    m_core->glShaderSource(GLuint(fragmentShader), 1, &fragmentShaderSource, nullptr);
    m_core->glCompileShader(GLuint(fragmentShader));


    m_core->glGetShaderiv(GLuint(fragmentShader), GL_COMPILE_STATUS, &is_success);
    if (!is_success)
    {
        m_core->glGetShaderInfoLog(GLuint(fragmentShader), 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << infoLog;
    }




    m_shaderProgram = m_core->glCreateProgram();                         //创建着色器程序对象
    m_core->glAttachShader(m_shaderProgram, GLuint(vertexShader));
    m_core->glAttachShader(m_shaderProgram, GLuint(fragmentShader));
    m_core->glLinkProgram(m_shaderProgram);                              //之前编译的着色器附加到程序对象上


    m_core->glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &is_success);//检查是否编译成功,未成功则需返回错误
    if (!is_success) {
        m_core->glGetProgramInfoLog(m_shaderProgram, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog ;
    }


    m_core->glDeleteShader(vertexShader);                               //着色器对象链接到程序对象以后,删除着色器对象
    m_core->glDeleteShader(fragmentShader);


    //VAO,VBO数据部分


#ifdef TRIANGLE
    GLfloat vertices[] = {
        -0.5f, -0.5f, 0.0f, // left
        0.5f, -0.5f, 0.0f,  // right
        0.0f,  0.5f, 0.0f   // top
    };
#else                                      //绘制矩形
    GLfloat vertices[] = {
         0.5f,  0.5f, 0.0f,  // top right
         0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };


    unsigned int indices[] = { // 注意索引从0开始!
        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };
#endif
//两个参数,第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
    m_core->glGenVertexArrays(1, &VAO);          
    m_core->glGenBuffers(1, &VBO);               //顶点缓冲对象处理
    m_core->glGenBuffers(1, &EBO);
    m_core->glBindVertexArray(VAO);
    m_core->glBindBuffer(GL_ARRAY_BUFFER, VBO);  //使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上
    //之前定义的顶点数据复制到缓冲的内存中
    m_core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);      
#ifdef RECTANGLE
    m_core->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    m_core->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
#endif
//glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)
    m_core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);  
    m_core->glEnableVertexAttribArray(0);        //以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的


    m_core->glBindBuffer(GL_ARRAY_BUFFER, 0);
    m_core->glBindVertexArray(0);


}


void MyGLWidget::resizeGL(int w, int h)
{
    m_core->glViewport(0, 0, w, h);
}


void MyGLWidget::paintGL()
{
    m_core->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    m_core->glClear(GL_COLOR_BUFFER_BIT);


    m_core->glUseProgram(m_shaderProgram); //激活程序对象
    m_core->glBindVertexArray(VAO);
#ifdef TRIANGLE
    m_core->glDrawArrays(GL_TRIANGLES, 0, 3);
#else                                         //绘制矩形
    m_core->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
#endif
//    glUseProgram(0);


}

小结:

对于程序中 文字解释的排版欢迎大家多提出宝贵的意见,感谢!

最后,如需完整工程可在公众号后台留言

学不可以已

发布了91 篇原创文章 · 获赞 94 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/ACK_ACK/article/details/103692048