OpenGL ES 入门 — 2.GLSL基础
在OpenGL 3.0之前,OpenGL 使用的是固定渲染管线,使用存储着色器完成渲染,存储着色器就是写好了着色程序,直接修改参数,调用API就可以满足渲染,而3.1版本以后,我们可以通过 GLSL(OpenGL Shading Langruage)自定义着色程序(主要是顶点着色器和片元着色器程序)来完成渲染。
在OpenGL ES中,我们就是通过使用GLSL来自己编写着色器的,所以接下来介绍下GLSL基础知识。
简介
GLSL作为一种着色器编写语言是纯粹和GPU打交道的计算机语言。
渲染结构图中Client通过三种方式向server发送数据
- Attributes,属性以向量传递数据,属性只有向顶点着色器传递才有意义。
- Uniforms,Uniforms可以在顶点着色器和片元着色器使用,Uniforms只能使用不可以修改。
- Texture Data,可以在顶点着色器和片元着色器使用。
最常见用法是在顶点着色器里生成所需要的值,然后传给片元着色器用。
需要注意的是:
- GLSL支持函数重载。
- GLSL不能自动提升数据类型,所以类型必须严格保持一致。
float f = 2.3;
bool b = bool(f); // b is true
- GLSL没有指针,字符串,字符,它基本上是一种处理数字数据的语言。
- GLSL不支持联合、枚举类型、结构体位字段及按位运算符。
数据类型
- 标量
GLSL有三种标量基本数据类型:float,int和bool。
- 向量数据类型
vec3 v; //声明三维浮点型向量v
v[1]=3.0; //给向量v的第二个元素赋值
// 下面两种等价
vec3 v = vec3(0.6);
vec3 v = vec3(0.6, 0.6, 0.6);
另外,可以用选择运算符的方式来使用向量。选择运算符是对于向量的各个元素(最多为4个)约定俗成的名称,用一个小写拉丁字母来表示:
- 顶点 (x、y、z、w)
- 颜色 (r、g、b、a)
- 纹理 (s、t、r、q)
vec4 v1=vec4(1.0, 2.0, 3.0, 4.0); //四维浮点型向量
vec4 v2;
v2.xy=v1.yz; //将v1的第二个和第三个元素复制到v2的第一个和第二个元素
v2.z=2.0; //给v2的第三个元素赋值
v2.xy=v1.yx; //将v1的头两个元素互换,再复制到v2的头两个元素中
- 矩阵数据类型
mat4 m; //声明四维浮点型方阵m
m[2][3]=2.0; //给方阵的第三列、第四行元素赋值
// 下面两种等价,初始化矩阵对角
mat2 m = mat2(1.0)
mat2 m = mat2(1.0, 0.0, 0.0, 1.0);
- 取样器(Sampler)
sampler1D 访问一个一维纹理
sampler2D 访问一个二维纹理
sampler3D 访问一个三维纹理
samplerCube 访问一个立方贴图纹理
sampler1DShadow 访问一个带对比的一维深度纹理
sampler2DShadow 访问一个带对比的二维深度纹理
uniform sampler2D grass;
vcc2 coord = vec2(100, 100);
vec4 color = texture2D(grass, coord);
如果一个着色器要在程序里结合多个纹理,可以使用取样器数组:
const int tex_nums = 4;
uniform sampler2D textures[tex_nums];
for(int i = 0; i < tex_nums; ++i) {
sampler2D tex = textures[i];
// todo ...
}
- 结构体
struct light
{
vec3 position;
vec3 color;
};
light ceiling_light;
- 数组
数组索引是从0开始的,而且没有指针概念
// 创建一个10个元素的数组
vec4 points[10];
// 创建一个不指定大小的数组
vec4 points[];
points[2] = vec4(1.0); // points现在大小为3
points[7] = vec4(2.0); // points现在大小为8
void
限定符
限定符常用的限定符有:
-
const,和C++里差不多,定义不可变常量,表示限定的变量在编译时不可被修 改。
-
attribute,该限定符标记的是一种全局变量,该变量在顶点着色器中是只读(read-only)的,该变量被用作从OpenGL应用程序向顶点着色器中传递参数,因此该限定符仅能用于顶点着色器,例如顶点坐标、颜色,法线,纹理坐标。
attribute vec4 position;
attribute vec2 textureCoord0;//纹理坐标
- uniform,一般是外部应用程序传给顶点着色器和片断着色器,也是一种全局变量,该变量对于一个图元(primitive)来说是不可更改的,它可以从OpenGL应用程序中接收传递来的参数,例如:
uniform mat4 viewProjectMatix;
uniform mat4 viewMatix;
uniform vec3 lightPosition;
- varying,用于传递顶点着色器的值给片元着色器,它提供了从顶点着色器向片元着色器传递数据的方法,varying限定符可以在顶点着色器中定义变量,然后再传递给光栅化器,光栅化器对数据插值后,再将每个片段的值交给片元着色器,注意在顶点着色器定义的变量名要跟片元着色器中接收的变量名一样。
varying vec2 textureCoord0;
着色器渲染过程
混合操作
通过在选择器(.)后列出各分量名,就可以选择这些分量
vec4 v4;
v4.rgba; // 得到vec4
v4.rgb; // 得到vec3
v4.b; // 得到float
v4.xy; // 得到vec2
v4.xgba; // 错误!分量名不是同一类
v4.wxyz; // 打乱原有分量顺序
v4.xxyy; // 重复分量