着色器 (shader) 是用着色语言写的小的,基于 C 语言的程序。现在有很许多种着色语言,但你如果做 OS X 或者 iOS 开发的话,你应该专注于 OpenGL 着色语言,或者叫 GLSL。你可以将 GLSL 的理念应用到其他的更专用的语言 (比如 Metal) 上去。
顶点坐标和纹理坐标未必是相同的坐标
在 OpenGL ES 中你必须创建两种着色器:顶点着色器 (vertex shaders) 和片段着色器 (fragment shaders)。顶点着色器定义了在 2D 或者 3D 场景中几何图形是如何处理的。一个顶点指的是 2D 或者 3D 空间中的一个点。在图像处理中,有 4 个顶点:每一个顶点代表图像的一个角。顶点着色器设置顶点的位置,并且把位置和纹理坐标这样的参数发送到片段着色器。
1、shader 变量的qualifier:
默认:无修饰符,普通变量读写, 与外界无连接;
const:常量 const vec3 zAxis = vec3(0.0, 0.0, 1.0);
attribute: 申明传给vertex shader的变量;只读;不能为array或struct;attribute vec4 position;
uniform: 表明整个图元处理中值相同;只读; uniform vec4 lightPos;
varying: 被差值;读写; varying vec3 normal;
in, out, inout;
1)Uniform 在顶点着色器和片段着色器里都可以被访问到。只读
2)Attributes 仅仅在顶点着色器中被访问。Attribute 是在随着每一个顶点不同而会发生变动的输入值,例如顶点的位置和纹理坐标等。顶点着色器利用这些变量来计算位置,以它们为基础计算一些值,然后把这些值以 varyings 的方式传到片段着色器。
3)Varying 在顶点着色器和片段着色器都会出现。Varying 是用来在顶点着色器和片段着色器传递信息的,并且在顶点着色器和片段着色器中必须名字一致。数值在顶点着色器被写入到 varying ,然后在片段着色器被读出。
4)向量类型包含特定数量的浮点数:vec2
包含两个浮点数,vec3
包含三个浮点数,vec4
包含四个浮点数。
5)在 mat2
中,你需要传入两个 vec2
或者四个浮点数
6)向量中单独的成分可以通过{x,y,z,w},{r,g,b,a}或者{s,t,p,q}的记法来表示。这些不同的记法用于顶点,颜色,纹理坐标。在成分选择中,你不可以混合使用这些记法。
vec3 myVec = {0.5, 0.35, 0.7};
float r = myVec.r;
float myYz = myVec.yz;
float myQ = myVec.q;//出错,数组越界访问,q代表第四个元素
float myRY = myVec.ry; //不合法,混合使用记法
2、shader变量的精度:
highp, mediump, lowp
3、shader内置变量:
1)gl_Position: 用于vertex shader, 写顶点位置;被图元收集、裁剪等固定操作功能所使用;
其内部声明是:highp vec4 gl_Position;
2)gl_PointSize: 用于vertex shader, 写光栅化后的点大小,像素个数;
其内部声明是:mediump float gl_Position;
3)gl_FragColor: 用于Fragment shader,写fragment color;被后续的固定管线使用;
mediump vec4 gl_FragColor;
4)gl_FragData: 用于Fragment shader,是个数组,写gl_FragData[n] 为data n;被后续的固定管线使用;
mediump vec4 gl_FragData[gl_MaxDrawBuffers];
5)gl_FragColor和gl_FragData是互斥的,不会同时写入;
6)gl_FragCoord: 用于Fragment shader,只读, Fragment相对于窗口的坐标位置 x,y,z,1/w; 这个是固定管线图元差值后产生的;z 是深度值; mediump vec4 gl_FragCoord;
7)gl_FrontFacing: 用于判断 fragment是否属于 front-facing primitive;只读;
bool gl_FrontFacing;
8)gl_PointCoord: 仅用于 point primitive; mediump vec2 gl_PointCoord;