OpenGL学习日记2——着色器

学习视频链接

OpenGL,Qt实现:1入门篇(已更完)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1UL411W71w?p=12&vd_source=0471cde1c644648fafd07b54e303c905

目录

一、封装代码读取shader

1.1 编码使用 UTF8 

1.2 头文件和对象

1.3 使用对象操作着色器

1.4 新建着色器

二、着色器

2.1 一个 shader 程序的典型结构

2.2 顶点数量

2.3 类型

2.4 输入输出

2.5 代码

2.6 layout(location = ...)


一、封装代码读取shader

1.1 编码使用 UTF8 

OpenGL学习日记2——着色器_第1张图片

1.2 头文件和对象

OpenGL学习日记2——着色器_第2张图片

注释掉相关的内容

OpenGL学习日记2——着色器_第3张图片 OpenGL学习日记2——着色器_第4张图片

1.3 使用对象操作着色器

OpenGL学习日记2——着色器_第5张图片 OpenGL学习日记2——着色器_第6张图片

#include "openglwidget.h"
#include 

float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

// 创建VBO和VAO对象,并赋予ID
unsigned int VAO, VBO;

// unsigned int shaderProgram;

const char* vertexShaderScource =
        "#version 330 core\n"
        "layout (location = 0) in vec3 aPos;\n"
        "void main()\n"
        "{\n"
        "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
        "}\n\0";

const char* fragmentShaderScource =
        "#version 330 core\n"
        "out vec4 FragColor;\n"
        "void main()\n"
        "{\n"
        "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
        "}\n\0";

OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

OpenGLWidget::~OpenGLWidget()
{
    makeCurrent();
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &VAO);
    //glDeleteProgram(shaderProgram);
    doneCurrent();
}

void OpenGLWidget::drawShape(OpenGLWidget::Shape shape)
{
    m_shape = shape;
    update();
}

void OpenGLWidget::setWireframe(bool wireframe)
{
    makeCurrent();
    if(wireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    update();
    doneCurrent();
}

// 初始化的槽函数
// 在第一次调用paintGL()或resizeGL()之前调用一次,然后在小部件被分配新的QGLContext时调用一次
void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();


    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    // 当前绑定到target的缓冲区对象创建一个新的数据存储
    // 如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    // 开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

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

    /*unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderScource, NULL);
    glCompileShader(vertexShader);

    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderScource, NULL);
    glCompileShader(fragmentShader);

    shaderProgram = glCreateProgram();*/
    /*glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);*/

    bool success;
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderScource);
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderScource);
    success = shaderProgram.link();
    if(success)
        qDebug() << "ERR:" << shaderProgram.log();

    /*glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);*/
}

void OpenGLWidget::resizeGL(int w, int h)
{

}

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

    switch (m_shape) {
    case Triangle:
        shaderProgram.bind();
        //glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        break;
    default:
        break;
    }
}

1.4 新建着色器

OpenGL学习日记2——着色器_第7张图片

OpenGL学习日记2——着色器_第8张图片

OpenGL学习日记2——着色器_第9张图片

着色器可以混用 

OpenGL学习日记2——着色器_第10张图片

运行结果没问题

OpenGL学习日记2——着色器_第11张图片

二、着色器

2.1 一个 shader 程序的典型结构

对于顶点着色器,输入变量为 顶点属性 (vertex attribute)

#version version_number
in type in_variable_name ;
in type in_variable_name ; 
out type out_variable name ;
uniform type uniform_name ;
void main ( )
{
        // process input(s) and do some weird graphics stuff ...
        // output processed stuff to output variable
        out_variable_name = weird_stuff_we_processed;
}

2.2 顶点数量

我们能声明的顶点属性数量是有上限的,可以通过下面的代码获取:

nt nrAttributes;
glGetIntegerv(GL_MAX_VERTEX ATTRIBS, &nrAttributes) ;

OpenGL 确保至少有 16 个包含 4 分量的顶点属性可用,但是有些硬件或许允许更多的顶点属性

2.3 类型

1、GLSL 中包含 C 等其它语言大部分的默认基础数据类型:

int、float、double、uint 和 bool

2、GLSL 也有两种容器类型:

(1) 向量(Vector)

vecn: the default vector of n floats

bvecn: a vector of n booleans

ivecn: a vector of n integers

uvecn: a vector of n unsigned integers

dvecn: a vector of n double components

(2) 矩阵 (Matrix) 

3、重组

向量允许一些有趣而灵活的分量选择方式,叫做重组 (Swizzling):

vec2 vect = vec2(0.5, 0.7);

vec4 result = vec4(vect, 0.0, 0.0);

vec4 otherResult = vec4(result.xyz, 1.0);

2.4 输入输出

在发送方着色器中声明一个输出

在接收方着色器中声明一个类似的输入

当类型和名字都一致,OpenGL 将把变量链接到一起 (在链接程序对象时完成)

OpenGL学习日记2——着色器_第12张图片

2.5 代码

1、输入、输出

OpenGL学习日记2——着色器_第13张图片

OpenGL学习日记2——着色器_第14张图片

2、其他语法

OpenGL学习日记2——着色器_第15张图片

 还可以 .xxz 之类的

2.6 layout(location = ...)

顶点着色器接收的是一种特殊形式的输入,否则就会效率低下

从顶点数据中直接接收输入。为了定义顶点数据该如何管理,我们使用 location 这一元数据(mietadata) 指定输入变量,这样我们才可以在 CPU 上配置顶点属性。例如: layout (location = 0)。layout 这个的标识,使得我们能把它链接到顶点数据。

可以忽略 layout(location = 0) 标识符,通过在 OpenGL 代码中使用 glGetAttribLocation 查询属性位置值 (Location),或是 glBindAttribLocation 属性位置值 (Location),但是推荐在着色器中设置它们,这样会更容易理解而且节省你 (和OpenGL) 的工作量。

下图中从 0 开始存数据,从 2 开始读数据,程序会报错 

OpenGL学习日记2——着色器_第16张图片

OpenGL学习日记2——着色器_第17张图片

现在我们获取到 shader 里面读取数据是从 2 开始,所以我们存放数据也是从 2 开始,这样就能顺利的运行程序了

OpenGL学习日记2——着色器_第18张图片

2.7 Uniform

Uniform:另一种从 CPU 的应用,向 GPU 中的着色器发送数据的方式

uniform 是全局的 (Global),可以被任意着色器程序在任意阶段访问

注意:如果声明了一个 uniform 却没用过,编译器会默移除这个变量,导致最后编译出的版本中并不会包含它,这可能导致几个非常麻烦的错误

OpenGL 在其核心是一个 C 库,所以它不支持类型重载,在函数参数类型不同的时候就要为其定义新的函数:glUniform 是一个典型例子。这个函数有一个特定的后缀,标识设定的 uniform 的类型。可能的后缀有:

OpenGL学习日记2——着色器_第19张图片

代码:

使用定时器,定期改变颜色

OpenGL学习日记2——着色器_第20张图片

OpenGL学习日记2——着色器_第21张图片 OpenGL学习日记2——着色器_第22张图片

OpenGL学习日记2——着色器_第23张图片

2.8 GLSL更多属性

把颜色数据加进顶点数据中

OpenGL学习日记2——着色器_第24张图片 

OpenGL学习日记2——着色器_第25张图片

 OpenGL学习日记2——着色器_第26张图片

OpenGL学习日记2——着色器_第27张图片

OpenGL学习日记2——着色器_第28张图片

 OpenGL学习日记2——着色器_第29张图片

三、练习

 

你可能感兴趣的:(OpenGL,学习,着色器)