本文所介绍的着色器将基于OpenGL 3.3
前言:OpenGL实现可编程逻辑管线,开发人员就可以自定义其中的某些流程,从 《penGL渲染管线之概述 (一)》(点击进入)可以看出,可编程逻辑管线的实现方式只是将之前的固定管线中可编程的部分提取出来供开发人员自定义。目前,开发人员可以使用的包括顶点着色器、几何着色器、片元着色器。它们的功能请继续阅读《penGL渲染管线之概述 (一)》。
概述:着色器是OpenGL可编程逻辑管线中的某些流程,目前可供开发人员自定的包括顶底、几何、片元着色器。他们都使用GLSL(OpenGL Shader Language),因为它们对向量和矩阵有特别的支持,所以很适合用于图形计算。
语法:
我们使用 in 来修饰需要传入当前着色器的变量,使用out修饰当前着色器需要往后传递的变量,使用uniform修饰所有着色器公用变量。
#version 330 core // 使用OpenGL3.3;并且在core模式下运行,只有这样才能使用可编程管线
layout (location = 0) in type in_variable_nam;
layout (location = 1) in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
int main()
{
// 处理输入并进行一些图形操作
...
// 输出处理过的结果到输出变量
out_variable_name = weird_stuff_we_processed;
}
着色器在编译的时候会自动串接多个shader间的in out变量。对于Uniform变量,我们需要通过手动传入或者OpenGL自动传入。有下面几种数据类型:int, float, double, uint, bool。同时我们还可以使用vec和mat,例如vec4,mat4,mat3x4等,我们可以在前面加b, i,u,d分别表示内部的数据类型为bool, int, uint, double。默认情况下是float。后面带数字则表示向量或矩阵大小。
我们可以使用xyzw、rgbd、stpq来分别获取向量的第1/2/3/4个分量,并且可以任意组合,例如:vec2 someVec = lastVec.zx。也可以使用它们的任意组合来创建一个和原来一样长的同类型新变量,例如:vec4 someVec = vec4(lastVec.zx, lastVec.x, lastVec.y)。
对于输入,我们使用layout (location = 0)标识符来限定,具体用法在下个文章里详细介绍。location 后面的值表示第几个属性,内容需要使用glVertexAttribPointer() 和glEnableVertexAttribArray()定义,具体的在下个文章介绍。
对于Uniform,我们先获取着色器程序对象中uniform变量的位置,然后手动改变该变量的值(并不是所有的Uniform变量都通过下面的方式更改)例如:
GLfloat timeValue = glfwGetTime();
GLfloat greenValue = (sin(timeValue) / 2) + 0.5;
// 通过变量名称,获取Uniform变量的位置
GLint vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
// 必须要使用着色器程序才能够改变里面的变量值
glUseProgram(shaderProgram);
// 通过uniform变量的的位置改变变量值
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);