OpenGL-Shader-GLSL

定义

OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。GLSL其使用C语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。

GLSL结构

  • 结构
#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;
}
  • main类似C语言的入口函数
  • GLSL定义inout关键字来保证数据的传输,比如顶点着色器想将顶点颜色传给片段着色器着色器,就只需要在顶点着色器中定义out vec4 vertextColor,然后在片段器中定义in vec4 vertextColor就可以在片段着色器中使用顶点的颜色了。
  • 在之前绘制三角形的时候也看见过一点着色器代码,在运行顶点着色器的时候,我们需要通过外部告诉顶点着色器相关的顶点属性,所以这时候就需要看另一个关键词了layout(location=0),比如你想从外面接收顶点的位置的信息:layout(location = 0) in vec3 aPos;,这时候你就可以在代码中使用glVertexAttribPointer查询并设置相关属性。0表示你的顺序id,如果你想给顶点着色器传其他参数,就可以新增layout(location = 0) in ? ?;,以下为示例代码:
const char* vertexShaderSource = "#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";
  • Uniform关键词,也是一种从CPU向GPU发送数据的方式,并且Uniform为全局变量,所以需要保证在着色其为独一无二的变量,它可以在着色其的任何阶段进行访问,并会一直保存他们的数据,如果在着色器代码中定义了Uniform千万记得在OpenGL中使用它,不然会被GLSL自动删除,造成不知名错误.。
  • OpenGL中设置Uniform变量,首先使用glGetUniformLocation查询变量所在的位置值,然后就可以通过glUniform1f设置其变量。在设置Uniform时,可以不使用glUseProgram,但是如果在更新Uniform时,就需要调用后才能更新。针对不同的变量类似,也有其他的设置函数,比如glUniform3fvglUniform4fv,示例代码如下:
//设置float
void SetFloat(const char* name, float value)
{
    const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
    glUniform1f(loc,value);
}
//设置vec3
void Shader::SetVector3(const char* name, glm::vec3 vec3)
{
    const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
    glUniform3fv(loc, 1, glm::value_ptr(vec3));
}
//设置vec4
void SetVector4(const char* name, glm::vec4 vec4)
{
    const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
    glUniform4fv(loc, 1, glm::value_ptr(vec4));
}
//设置矩阵
void Shader::SetMatrix4(const char* name, glm::mat4 matrix)
{
    unsigned int loc = glGetUniformLocation(ShaderProgram, name);
    glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(matrix));
}
  • 设置Uniform的函数表,格式glUniform+n+类型,(n:1~4, 矩阵例外
序号 类型 解释 示例
0 f float值 glUniform1f
1 i int值 glUniform1i
2 ui 无符号int值 glUniform1ui
3 fv float向量值 glUniform4fv
4 Matrix2fv 2*2矩阵 glUniformMatrix2fv
5 Matrix3fv 3*3矩阵 glUniformMatrix3fv
6 Matrix4fv 4*4矩阵 glUniformMatrix4fv

GLSL支持变量

序号 变量 解释
0 int 整型
1 float 浮点型
2 double 双精度浮点型
3 uint 无符号整型
4 vecn 包含n个float分量的默认向量(n表示可以有1、2、3或者4个数量)
5 bvecn 包含n个bool分量的默认向量(n表示可以有1、2、3或者4个数量)
6 iecn 包含n个int分量的默认向量(n表示可以有1、2、3或者4个数量)
7 uvecn 包含n个uint分量的默认向量(n表示可以有1、2、3或者4个数量)
8 dvecn 包含n个double分量的默认向量(n表示可以有1、2、3或者4个数量)

设置三角形的顶点颜色

  • 在顶点数据中添加顶点颜色
//顶点数据
    const float vertices[18] = {
        //位置                //颜色    
        -0.5f, -0.5f, 0.0f,  1.0f,0.0f,0.0f,
        0.5f, -0.5f, 0.0f,   0.0f,1.0f,0.0f,
        0.0f,  0.5f, 0.0f,   0.0f,0.0f,1.0f
    };
  • 在顶点着色器中新增顶点颜色的输入,颜色变量的属性位置更改为1,并定义一个vertexColor向片段着色器输出顶点颜色
const char* vertexShaderSource = "#version 330 core\n"
        "layout(location = 0) in vec3 aPos;\n"
        "layout(location = 1) in vec3 aColor;\n"
        "out vec3 vertextColor;\n"
        "void main()\n"
        "{\n"
            "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
            "vertextColor =aColor;\n"
        "}\n";
  • 将片段着色器中定义一个颜色变量接收顶点着色器传过来的顶点颜色,并将最终的输出颜色改为顶点的颜色
const char* fragmentShaderSource = "#version 330 core\n"
        "out vec4 FragColor;\n"
        "in vec3 vertextColor;\n"
        "void main()\n"
        "{\n"
        "   FragColor = vec4(vertextColor,1.0);\n"
        "}\n";
  • 使用glVertexAttribPointer更新顶点数据
//解析顶点数据--位置数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
//以顶点属性位置值作为参数,启用顶点属性
glEnableVertexAttribArray(0);
//解析顶点数据--颜色数据
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));
//以顶点属性位置值作为参数,启用顶点属性
glEnableVertexAttribArray(1);
  • 运行截图
    这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq992817263/article/details/79435740