着色器

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGLWidget>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QDebug>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QTime>
#include <QtMath>
#include <QTimer>

namespace Ui {
class Widget;
}

class Triangle : public QGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    explicit Triangle();
    ~Triangle();
protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int w, int h);
private:
    GLuint shaderProgram;
    QOpenGLFunctions_3_3_Core *core;
    shader *ourShader;
};

#endif // WIDGET_H
widget.h
#include "widget.h"
#include "ui_widget.h"

GLuint VBO, VAO;
const char *vertexShaderSource ="#version 330 core
"
    "layout (location = 0) in vec3 aPos;
"
    "void main()
"
    "{
"
    "   gl_Position = vec4(aPos, 1.0);
"
    "}";

const char *fragmentShaderSource = "#version 330 core
"
    "out vec4 FragColor;
"
    "uniform vec4 ourColor;
"
    "void main()
"
    "{
"
    "   FragColor = ourColor;
"
    "}
";


Triangle::Triangle()
{

}

Triangle::~Triangle()
{

}

void Triangle::initializeGL()
{
    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    if (!core) {
          qWarning() << "Could not obtain required OpenGL context version";
          exit(1);
    }

    GLuint vertexShader = core->glCreateShader(GL_VERTEX_SHADER);
    core->glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    core->glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    core->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << endl;
    }
    // fragment shader
    GLuint fragmentShader;
    fragmentShader = core->glCreateShader(GL_FRAGMENT_SHADER);
    core->glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    core->glCompileShader(fragmentShader);
    core->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << endl;
    }

    shaderProgram = core->glCreateProgram();
    core->glAttachShader(shaderProgram, vertexShader);
    core->glAttachShader(shaderProgram, fragmentShader);
    core->glLinkProgram(shaderProgram);
    core->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        core->glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << endl;
    }

    core->glDeleteShader(vertexShader);
    core->glDeleteShader(fragmentShader);

    float vertices[] = {
        // positions         // colors
         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);
    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), nullptr);
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (void*)(3 * sizeof(float)));
    core->glEnableVertexAttribArray(0);

    QTimer *timer = new QTimer(this);
    timer->setInterval(100);
    connect(timer, &QTimer::timeout, this, [=](){
        repaint();});
    timer->start();
}

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

    core->glUseProgram(shaderProgram);
    core->glBindVertexArray(VAO);

    float timeValue = QTime(0,0,0).msecsTo(QTime::currentTime())/1000.0f;
    float greenValue = qSin(timeValue) / 2.0f + 0.5f;
    qDebug()<<"greenValue"<<greenValue;
    int vertexColorLocation = core->glGetUniformLocation(shaderProgram, "ourColor");
    core->glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);


    core->glDrawArrays(GL_TRIANGLES, 0, 3);
    core->glUseProgram(0);
}

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

更多属性

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGLWidget>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QDebug>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QTime>
#include <QtMath>
#include <QTimer>

#include "shader.h"

namespace Ui {
class Widget;
}

class Triangle : public QGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    explicit Triangle();
    ~Triangle();
protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int w, int h);
private:
    GLuint shaderProgram;
    QOpenGLFunctions_3_3_Core *core;
    shader *m_shader;
};

#endif // WIDGET_H
widget.h
#include "widget.h"
#include "ui_widget.h"

GLuint VBO, VAO;
const char *vertexShaderSource ="#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.0);
"
    "   ourColor = aColor;
"
    "}";

const char *fragmentShaderSource = "#version 330 core
"
    "out vec4 FragColor;
"
    "in vec3 ourColor;
"
    "void main()
"
    "{
"
    "   FragColor = vec4(ourColor, 1.0f);
"
    "}
";


Triangle::Triangle()
{

}

Triangle::~Triangle()
{

}

void Triangle::initializeGL()
{
    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    if (!core) {
          qWarning() << "Could not obtain required OpenGL context version";
          exit(1);
    }

    GLuint vertexShader = core->glCreateShader(GL_VERTEX_SHADER);
    core->glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    core->glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    core->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << endl;
    }
    // fragment shader
    GLuint fragmentShader;
    fragmentShader = core->glCreateShader(GL_FRAGMENT_SHADER);
    core->glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    core->glCompileShader(fragmentShader);
    // check for shader compile errors
    core->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << endl;
    }

    // link shaders
    shaderProgram = core->glCreateProgram();
    core->glAttachShader(shaderProgram, vertexShader);
    core->glAttachShader(shaderProgram, fragmentShader);
    core->glLinkProgram(shaderProgram);
    core->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        core->glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << endl;
    }

    core->glDeleteShader(vertexShader);
    core->glDeleteShader(fragmentShader);

    float vertices[] = {
        // positions         // colors
         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);
    core->glGenBuffers(1, &VBO);
    core->glBindVertexArray(VAO);

    core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //position attribute
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), nullptr);
    core->glEnableVertexAttribArray(0);
    //color attribute
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (void*)(3 * sizeof(float)));
    core->glEnableVertexAttribArray(1);
}

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

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

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

自己的着色器

#ifndef SHADER_H
#define SHADER_H

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

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

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

signals:

public slots:
};

#endif // SHADER_H
shader.h
#include "shader.h"

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

    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    success  =fragmentShader.compileSourceFile(fragmentSourcePath);
    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()
{

}
shader.cpp
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGLWidget>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QDebug>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QTime>
#include <QtMath>
#include <QTimer>

#include "shader.h"

namespace Ui {
class Widget;
}

class Triangle : public QGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    explicit Triangle();
    ~Triangle();
protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int w, int h);
private:
//    GLuint shaderProgram;
    QOpenGLFunctions_3_3_Core *core;
    shader *ourShader;
};

#endif // WIDGET_H
widget.h
#include "widget.h"
#include "ui_widget.h"

GLuint VBO, VAO;
const char *vertexShaderSource ="#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.0);
"
    "   ourColor = aColor;
"
    "}";

const char *fragmentShaderSource = "#version 330 core
"
    "out vec4 FragColor;
"
    "in vec3 ourColor;
"
    "void main()
"
    "{
"
    "   FragColor = vec4(ourColor, 1.0f);
"
    "}
";


Triangle::Triangle()
{

}

Triangle::~Triangle()
{

}

void Triangle::initializeGL()
{
    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    if (!core) {
          qWarning() << "Could not obtain required OpenGL context version";
          exit(1);
    }
    ourShader = new shader(":/vertexshadersource.vert", ":/fragmentshadersource.frag");

    GLuint vertexShader = core->glCreateShader(GL_VERTEX_SHADER);
    core->glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    core->glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    core->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << endl;
    }
    // fragment shader
    GLuint fragmentShader;
    fragmentShader = core->glCreateShader(GL_FRAGMENT_SHADER);
    core->glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    core->glCompileShader(fragmentShader);
    // check for shader compile errors
    core->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        core->glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << endl;
    }

    // link shaders
//    shaderProgram = core->glCreateProgram();
//    core->glAttachShader(shaderProgram, vertexShader);
//    core->glAttachShader(shaderProgram, fragmentShader);
//    core->glLinkProgram(shaderProgram);
//    core->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
//    if (!success) {
//        core->glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
//        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << endl;
//    }

    core->glDeleteShader(vertexShader);
    core->glDeleteShader(fragmentShader);

    float vertices[] = {
        // positions         // colors
         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);
    core->glGenBuffers(1, &VBO);
    core->glBindVertexArray(VAO);

    core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //position attribute
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), nullptr);
    core->glEnableVertexAttribArray(0);
    //color attribute
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (void*)(3 * sizeof(float)));
    core->glEnableVertexAttribArray(1);
}

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

    ourShader->use();
//    core->glUseProgram(shaderProgram);
    core->glBindVertexArray(VAO);
    core->glDrawArrays(GL_TRIANGLES, 0, 3);
    core->glUseProgram(0);
}

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

着色器练习

  1. 修改顶点着色器让三角形上下颠倒:
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aColor;
    
    out vec3 ourColor;
    
    void main(){
      gl_Position = vec4(aPos.x, -aPos.y, aPos.z, 1.0f);
      ourColor = aColor;
    }
    vertexshadersource.vert
  2. 使用uniform定义一个水平偏移量,在顶点着色器中使用这个偏移量把三角形移动到屏幕右侧:
    void Triangle::paintGL()
    {
        core->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        core->glClear(GL_COLOR_BUFFER_BIT);
    
        ourShader->use();
        ourShader->shaderProgram.setUniformValue("xOffset", 0.5f);
    //    core->glUseProgram(shaderProgram);
        core->glBindVertexArray(VAO);
        core->glDrawArrays(GL_TRIANGLES, 0, 3);
        core->glUseProgram(0);
    }
    
    //vertexshadersource.vert
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aColor;
    
    out vec3 ourColor;
    
    uniform float xOffset;
    
    void main(){
      gl_Position = vec4(aPos.x + xOffset, -aPos.y, aPos.z, 1.0f);
      ourColor = aColor;
    }
    答案
  3. 使用out关键字把顶点位置输出到片段着色器,并将片段的颜色设置为与顶点位置相等(来看看连顶点位置值都在三角形中被插值的结果)。做完这些后,尝试回答下面的问题:为什么在三角形的左下角是黑的?:
    fragmentshadersource.frag
    #version 330 core
    out vec4 FragColor;
    //in vec3 ourColor;
    in vec3 ourPosition;
    
    void main(void)
    {
        FragColor = vec4(ourPosition, 1.0f);
    }
    
    vertexshadersource.vert
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aColor;
    
    out vec3 ourPosition;
    
    void main(){
      gl_Position = vec4(aPos, 1.0f);
      ourPosition = aPos;
    }
    
    /* 
    Answer to the question: Do you know why the bottom-left side is black?
    -- --------------------------------------------------------------------
    Think about this for a second: the output of our fragment's color is equal to the (interpolated) coordinate of 
    the triangle. What is the coordinate of the bottom-left point of our triangle? This is (-0.5f, -0.5f, 0.0f). Since the
    xy values are negative they are clamped to a value of 0.0f. This happens all the way to the center sides of the 
    triangle since from that point on the values will be interpolated positively again. Values of 0.0f are of course black
    and that explains the black side of the triangle.
    */
    
    位置做了颜色,左下角是-0.5,-0.50.0。然后颜色没有负的。就是0,0,0了黑色。
    中间又有颜色是因为其他角不是黑的
    答案
原文地址:https://www.cnblogs.com/ch122633/p/12069578.html