【OpenGL学习笔记七】着色器语言(GLSL)

目录

典型着色器结构

数据类型

顶点着色器特性

片段着色器特性

从顶点着色器向片段着色器发送数据

从CPU中的应用向GPU中的着色器发送数据


GLSL规范:https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.20.pdf

GLSL是类C语言

着色器是各自独立的小程序,但是最终各个着色器是要link到一起构成一个整体程序的

典型着色器结构

  1. 开头总是版本声明
  2. 使用in关键字定义输入变量
  3. 定义out关键字定义输出变量
  4. 定义uniform
  5. main函数
#version version_number
in type in_variable_name;
in type in_variable_name;

out type out_variable_name;

uniform type uniform_name;

int main()
{
  // 处理输入并进行一些图形操作
  ...
  // 输出处理过的结果到输出变量
  out_variable_name = weird_stuff_we_processed;
}

数据类型

GLSL中包含了C的基本数据类型int float double uint bool,还包含了两个容器类型向量(Vector)和矩阵(Matrix),由于向量可以是一维的,所以直接使用向量和矩阵两个数据类型即可。

【OpenGL学习笔记七】着色器语言(GLSL)_第1张图片

顶点着色器特性

顶点着色器的每个输入变量叫做顶点属性。

能声明的顶点属性是有限制的,一般由硬件来决定。

OpenGL确保至少有16个包含4分量的顶点属性可用。

顶点着色器的输入是从顶点数据中直接接收数据,即从VBO中直接接收数据,

下面代码定义的顶点数据vertices[]将会通过VBO,传输给顶点着色器的输入vec3 posVertex

static const float vertices[] ={
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    -0.5f, 0.5f, 0.0f
};
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3* sizeof (float),(void*)0);
glEnableVertexAttribArray(0);


//顶点着色器程序
#version 330
layout(location = 0) in vec3 posVertex;
void main()
{
    gl_Position = vec4(posVertex, 1.0f);
}

片段着色器特性

片段着色器必须要定义一个vec4的输出,因为片段着色器需要生成一个最终输出的颜色。如果在片段着色器中定义输出颜色,OpenGL会把物体渲染为黑色或者白色。

从顶点着色器向片段着色器发送数据

  1. 在顶点着色器中定义一个类型的变量
  2. 在片段着色器中定义一个同类型和名字的变量

在link着色器的时候,当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起

//顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0

out vec4 vertexColor; // 为片段着色器指定一个颜色输出

void main()
{
    gl_Position = vec4(aPos, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
    vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把输出变量设置为暗红色
}

/*************************************************************/

//片段着色器
#version 330 core
out vec4 FragColor;

in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)

void main()
{
    FragColor = vertexColor;
}

从CPU中的应用向GPU中的着色器发送数据

OpenGL通过将着色器中变量定义前加入uniform关键字,来声明改变量中的数据可以从CUP传入。

uniform特性:

  1. uniform是全局的。
  2. uniform定义的变量必须在每个着色器对象中是独一无二的。
  3. uniform可以被任意着色器在任意位置访问。

uniform的使用:

在一个着色器中添加uniform关键字至类型和变量名前来声明一个GLSL的uniform

#version 330 core
out vec4 FragColor;

//1.在OpenGL程序代码中设定这个变量
uniform vec4 ourColor; 

void main()
{
    FragColor = ourColor;
}
/******************************************************************/

float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
//2.获取uniform "ourColor"的位置
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
//3.更新ourColor前必须调用glUseProgram
glUseProgram(shaderProgram);
//4.通过glUniform4f更新GPU中的数据
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

【OpenGL学习笔记七】着色器语言(GLSL)_第2张图片

 

你可能感兴趣的:(OpenGL开发专栏,OpenGL)