典型的着色器:
着色器的开头总是要声明版本,接着是输入和输出变量、uniform和main函数。着色器入口是main函数。顶点着色器输入变量也叫顶点属性(Vertex Attribute),OpenGL保证至少16个4分量定点可用
#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;
}
重组
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;
输入输出
使用location元数据指定输入变量,layout (location = 0),顶点着色器提供一个额外的layout标识。也可以忽略这个标识符,在OpenGL中使用glGetAttribLocation查询属性位置值。
片段着色器将一个输出一个vec4颜色,
Uniform
Vertex Shader可以接受VAO的数据,也可以接收来自CPU的Uniform的数据。
Uniform是一种从CPU的应用向GPU中的着色器发送数据的方式,uniform是全局的,uniform可以被着色器的任意阶段访问。
在fragmentShader中添加一个uniform类型的数据。
const char* fragmentShaderSource =
"#version 330 core \n"
"in vec4 vertexColor; \n"
"uniform vec4 ourColor; \n"
"out vec4 FragColor; \n"
"void main(){ \n"
" FragColor =ourColor;} \n";
glGetUniformLocation获得shaderProgram下某个名称的uniform的location,再使用glUniform4f将目标的localtion的Uniform进行赋值。更新uniform之前必须使用程序(调用glUseProgram),因为他是在当前激活着色器程序中设置uniform的。
float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
//glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glUseProgram(shaderProgram);
glUniform4f(vertexColorLocation, 0, greenValue, 0, 1.0f);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
网友评论