基于Qt的OpenGL编程(3.x以上GLSL可编程管线版)---(三)着色器

本篇目的是生成彩色三角形,如下图所示。并且按照Vries的方法优化类结构,详细的优化类思想及每条OpenGL函数的解析请看源教程。

(这是基于visual studio教程的原地址

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

项目组织结构如下:

因为QOpenGLShader与QOpenGLShaderProgram对glfw繁杂的shader创立过程进行了大量简化,故我使用他们建立使用shader对象。QOpenGLShaderProgram对shader的数据管理非常方便,故不再在shader.h中移植下图这些成员函数,具体如何应用,直接使用shaderprogram.setUniformValue(shaderprogram.UniformLocation(name), value)即可。

shader.h

#ifndef SHADER_H
#define SHADER_H

#include <QDebug>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QString>

class Shader {
public:
  Shader(const QString& vertexSourcePath, const QString& fragmentSourcePath);
  ~Shader();
  QOpenGLShaderProgram shaderProgram;

  void use(){
    shaderProgram.bind();
  }


};

#endif // SHADER_H

shader.cpp

#include "shader.h"

Shader::Shader(const QString& vertexPath, const QString& fragmentPath){
    QOpenGLShader vertexShader(QOpenGLShader::Vertex);
    bool success = vertexShader.compileSourceFile(vertexPath);
    if(!success){
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << endl;
        qDebug() << vertexShader.log() << endl;
    }

    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    success  =fragmentShader.compileSourceFile(fragmentPath);
    if(!success){
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << endl;
        qDebug() << fragmentShader.log() << endl;
    }

   shaderProgram.addShader(&vertexShader);
   shaderProgram.addShader(&fragmentShader);
   success = shaderProgram.link();
   if(!success){
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << endl;
        qDebug() << shaderProgram.log() << endl;
   }
}

Shader::~Shader(){
}

对于widget.h里的Triangle类,仍打算使用QOpenGLFunctions_3_3_core核心类对象,作为数据传输工具,因为QOpenGLFunctions类没有Vries所使用的glGenVertexArray()函数,即没有顶点数组对象这一概念,下图是原教程截图。现在在初学阶段,暂时仍使用core核心类,解决这一问题。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QDebug>
#include <QOpenGLFunctions_3_3_Core>
#include "shader.h"

class Triangle : public QOpenGLWidget
{
public:
    Triangle();
    GLuint a;
    ~Triangle();
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
private:
    Shader *ourShader;
    QOpenGLFunctions_3_3_Core *core;

};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
GLuint VBO, VAO;

Triangle::Triangle(){
}

Triangle::~Triangle(){
}

void Triangle::initializeGL(){

    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    ourShader = new Shader(":/shaders/vertexshadersource.vert", ":/shaders/fragmentshadersource.frag");

    //VAO,VBO数据部分
    GLfloat vertices[] = {
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  // Bottom Right
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  // Bottom Left
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f   // Top
    };



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

    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
    core->glEnableVertexAttribArray(0);
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    core->glEnableVertexAttribArray(1);


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

    core->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

}

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

void Triangle::paintGL(){

    core->glClear(GL_COLOR_BUFFER_BIT);

    ourShader->use();
    core->glBindVertexArray(VAO);
    core->glDrawArrays(GL_TRIANGLES, 0, 3);

}

main.cpp

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

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

    return a.exec();
}

这里对与shader。我们将其当作资源文件,放进资源进行管理,

想项目添加资源文件,增加资源前缀,这里网络上向qt添加资源的方法有很多,不再赘述。

vertexshadersource.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec3 ourColor;

void main(){
  gl_Position = vec4(aPos, 1.0f);
  ourColor = aColor;
}

fragmentshadersource.frag

#version 330 core
out vec4 FragColor;
in vec3 ourColor;

void main(void)
{
    FragColor = vec4(ourColor, 1.0f);
}

将上述代码进行组装,则生成三角形窗口

猜你喜欢

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