目录
1,典型结构,输入输出
GLSL中包含 C 等其他语言大部分的默认基础数据类型
int , float ,double ,uint ,和 bool。
.
GLSL 有两种容器类型:
-
向量(Vector)
向量各类型解释(
n代表分量数量,可取 2、3、4): -
vecn:单精度浮点向量(最常用,如 vec2/vec3/vec4) -
bvecn:布尔向量(bvec2/bvec3/bvec4,元素是 bool) -
ivecn:有符号整数向量(ivec2/ivec3/ivec4) -
uvecn:无符号整数向量(uvec2/uvec3/uvec4) -
dvecn:双精度浮点向量(dvec2/dvec3/dvec4)
javascript
vec2 vect = vec2(0.5,0.7);
vec4 result = vec4(vect,0.0,0.0);
vec4 otherResult = vec4(result.xyz,1.0);
【示例】 :
//顶点着色器
javascript
#version 330 core
layout(location = 0) in vec3 aPos;
out vec4 vertexColor;
void main(){
gl_Position = vec4(aPos,1.0);
vertexColor = vec4(0.5,0.0,0.0,1.0);
}
//片段着色器
javascript
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
void main(){
FragColor = vertexColor;
}
2,Layout
顶点着色器接收的是一种特殊形式的输入,否则就会效率低下。
从顶点数据中直接接收输入。为了定义顶点数据该如何管理,可以使用 loaction 指定输入变量。这样就可以在 CPU 上配置顶点属性。
例如:layout (location = 0) , layout 这个标识能把它链接到顶点数据。
【示例】:
javascript
//顶点坐标 + 顶点颜色(每个顶点 6 个 float:前 3 个位置,后 3 个颜色)
float vertices[] = {
// 位置 // 颜色
-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 // 顶部:蓝
};
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 ourColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"ourColor = aColor;\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"in vec3 ourColor;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(ourColor, 1.0f);\n"
"}\0";
unsigned int shaderProgram;
void MyOpenGLWidget::initializeGL()
{
// 初始化当前 OpenGL 上下文的函数指针
// QOpenGLFunctions_3_3_Core::initializeOpenGLFunctions()
// 如果上下文不是 3.3 Core,会返回 false
bool ok = initializeOpenGLFunctions();
qDebug() << "initializeOpenGLFunctions:" << ok;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// VAO:保存顶点属性配置信息(怎么解析VBO里的数据)
// VBO:GPU显存缓冲区,用来存放顶点原始坐标数据
glGenVertexArrays(1, &VAO); // 生成1个顶点数组对象VAO,把返回的ID存入变量VAO
glGenBuffers(1, &VBO); // 生成1个顶点缓冲对象VBO,把返回的ID存入变量VBO
glBindVertexArray(VAO); // 绑定VAO到当前上下文,之后所有顶点属性配置都会记录进这个VAO
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 绑定VBO到当前上下文,之后所有顶点属性配置都会记录进这个VBO
//将数据传入显存
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 把顶点数据复制到当前绑定到的 VBO
//告知显卡如何解析:位置属性 location=0,从第 0 个 float 开始,步长 6 个 float
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
//开启位置属性
glEnableVertexAttribArray(0);
//告知显卡如何解析:颜色属性 location=1,从第 3 个 float 开始,步长 6 个 float
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
//开启颜色属性
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//编译顶点着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//编译片段着色器
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 链接成功后可以删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
查看上面的代码。
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
这段代码表示,将 vertices\[\] 数组,划分为多个顶点,每个顶点有 6 个 float
这几个顶点分别是 -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 。
每个顶点从 第 0 个开始,数三个,摘取出来做成一个集合,并将这个集合定义为 index = 0 。
.
.
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
这个和上面不同的是,摘取每个顶点从 第 3 个开始,数三个,摘取出来做成一个集合,并将这个集合定义为 index = 1
两个集合就是
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
javascript
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 ourColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"ourColor = aColor;\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"in vec3 ourColor;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(ourColor, 1.0f);\n"
"}\0";
上面这段 GLSL 代码中
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
这段代码表示 aPos 向量映射 index = 0 的顶点数据。
aColor 向量映射 index = 1 的顶点数据。
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
这段代码就表示 index = 0 也就是 aPos 数据定性为位置数据。