基于Qt的OpenGL编程(3.x以上GLSL可编程管线版)---(二)你好,三角形_QOpenGLExtraFunctions版

本篇文章,是一项带引号的“翻译”类型文章。

Joey De Vries  的现代OpenGL教程是我看过最好的图形学教程,没有之一。奈何原作者是在Visual Studio平台进行开发,针对GUI和OpenGL的结合,没有多言。在自己实际开发应用中,没有好的GUI确是造成不少困扰,故我欲作为一名搬运工,将Vries大神的代码进行Qt平台的“移植”。预了解代码中关于OpenGL函数的详细解释,请看Vries的教程,连接如下。

(这是此篇教程的原地址https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/)

本篇目的是创立窗口,生成三角形,如下图所示。

Qt对OpenGL的支持,要求,必须public继承QOpenGLWidget类,然后重写这三个函数。

这里介绍第一种方法,继承QOpenGLExtraFunction

为了使用glShaderSource()这种OpenGL成员函数,要求必须proteced继承QOpenGLFunctions类,或QOpenGLExtraFunctions类,这里选择继承QOpenGLExtraFunctions类,因为这个类是QOpenGLFunctions类的子类,多了glGenVertexArrays(1, &VAO)这一函数。

项目组织结构如下:

widget.h如下

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QDebug>

class Triangle : public QOpenGLWidget, protected QOpenGLExtraFunctions
{
public:
    Triangle();
    ~Triangle();
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
private:
    GLuint shaderProgram;
};

#endif // WIDGET_H

widget.cpp如下

#include "widget.h"
GLuint VBO, VAO;
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";
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";
Triangle::Triangle(){

}

Triangle::~Triangle(){

}

void Triangle::initializeGL(){

    //着色器部分
    this->initializeOpenGLFunctions();
    //core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
    }

    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
    }
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //VAO,VBO数据部分
    GLfloat vertices[] = {
            -0.5f, -0.5f, 0.0f, // left
             0.5f, -0.5f, 0.0f, // right
             0.0f,  0.5f, 0.0f  // top
    };


    glGenVertexArrays(1, &VAO);//两个参数,第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

}

void Triangle::resizeGL(int w, int h){
    glViewport(0, 0, w, h);
}

void Triangle::paintGL(){
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glUseProgram(0);
}

main函数如下

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Triangle t;
    t.show();

    return a.exec();
}

在继承QOpenGLExtraFunctions的情形下,整个Vries的代码可以在基本无改动的情况下,直接移植。

猜你喜欢

转载自blog.csdn.net/z136411501/article/details/79832561