GLSL 学习
着色器语言,是一种面向过程的语言:
基本语法与C/C++基本相同。
支持向量和矩阵操作
通过限定符操作来管理输入输出类型
提供内置函数来提供丰富的扩展功能
SL
着色器是用来实现图像渲染的,用来替代固定渲染管线的可编程程序
OpenGLES中着色器分为
顶点着色器: 针对每个顶点执行一次,用于确定顶点的位置
片元着色器: 针对每个片元(像素)执行一次,用于确定每个片元(像素)的颜色
(OpenGLES1.x 固定渲染管道, OpenGLES2.0 可编程渲染管道)
OpenGLES的着色器语言GLSL是一种高级的图形化编程语言,其源自应用广泛的C语言。与传统的C语言不同的是,它提供了更加丰富的针对于图像处理的原生类型,诸如向量、矩阵之类。OpenGLES 主要包含以下特性:
GLSL数据类型:
主要分为标量、向量、矩阵、采样器、结构体、数组、空类型(void表示)七种类型,没有double、long等类型(没有union、enum、unsigned以及位运算等特性)
标量:只有大小没有方向的量,GLSL中标量只有bool、int和float三种
向量:向量我们可以看做是数组,在GLSL通常用于储存颜色、坐标等数据
共有vec2、vec3、vec4,ivec2、ivec3、ivec4、bvec2、bvec3和bvec4九种类型,数字代表维数、i表示int类型、b表示bool类型
颜色向量:
rgba表示分量,就如同取数组的中具体数据的索引值。三维颜色向量就用rgb表示分量。比如对于颜色向量vec4 color,color[0]和color.r都表示color向量的第一个值,也就是红色的分量。
位置向量:
用xyzw表示分量,xyz分别表示xyz坐标,w表示向量的模。三维坐标向量为xyz表示分量,二维向量为xy表示分量
纹理向量:用stpq表示分量,三维用stp表示分量,二维用st表示分量
矩阵:有2*2、3*3、4*4三种类型的矩阵,分别用mat2、mat3、mat4表示。
采样器:
采样器是专门用来对纹理进行采样工作的,在GLSL中一般来说,一个采样器变量表示一副或者一套纹理贴图。所谓的纹理贴图可以理解为我们看到的物体上的皮肤。
GLSL限定符:
attritude:一般用于各个顶点各不相同的量。如顶点坐标、颜色,法线,纹理坐标等。
uniform:参数常量,一般用于对于3D物体中所有顶点都相同的量。比如光源位置、变换矩阵、光照参数等。
varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。
const:常量。
uniform:
uniform空间被顶点着色器和片段着色器分享,因此在顶点着色器中声明的uniform,片段着色器中可以直接访问。
当应用程序装载uniform 时,它的值在顶点着色器和片段着色器都可用。
在链接阶段,链接器将分配常量在项目里的实际地址,那个地址是被应用程序使用和加载的标识。
uniform 存储在硬件上被称为常量存储(分配在硬件上的存储常量值的空间,存储需要的空间是固定的,因此程序中这种uniform 的数量是受限的。
通过读gl_MaxVertexUniformVectors 和gl_MaxFragmentUniformVectors编译变量可得到具体的限制数值,或调用glGetIntegerv传入GL_MAX_VERTEX_UNIFORM_VECTORS 或GL_MAX_FRAGMENT_UNIFORM_ VECTORS参数获取)
OpenGL ES 2.0必须至少提供256 个顶点着色器uniform 和224个片段着色器uniform。
GLSL函数
函数参数修饰符:
in: 输入参数,无修饰符时默认为此修饰符。
out:输出参数。
inout:既可以作为输入参数,又可以作为输出参数。
内置函数:
Sampler:
通常是在fragment shader片元着色器内定义,是一个uniform类型的变量,一个sampler和一个texture对应,类型也是对应的,比如sampler2D对应的就是GL_TEXTURE_2D类型的纹理对象。
sampler变量在texture函数中使用(采样器针对纹理进行采样,获取纹理像素信息)。
sampler1D、sampler2D、sampler3D、samplerCube、sampler1DArray、sampler2DArray、sampler2DRect、sampler1DShadow、samplerCubeShadow、samplerBuffer等
纹理采样函数texture函数:
它是一个lookup 函数(以给定的纹理坐标去纹理的数据中查到相应的颜色的信息),得到每一个像素的颜色信息渲在每一个片元上。
texture2D、texture2DProj、texture2DLod、texture2DProjLod、textureCube、textureCubeLod及texture3D、texture3DProj、texture3DLod、texture3DProjLod等:
texture表示纹理采样,2D表示对2D纹理采样,3D表示对3D纹理采样
Lod后缀,只适用于顶点着色器采样
Proj表示纹理坐标st会除以q
如:
vec4 texture2D(sampler2D sampler, vec2 coord, [float bias])
vec4 texture2DProj(sampler2D sampler, vec3 coord, [float bias]
vec4 texture2DProj(sampler2D sampler, vec4 coord, [float bias]
vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod)
vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod)
vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod)
系列函数功能为使用二维纹理坐标coord在由sampler参数指定的2D纹理中执行纹理采样.
1、Proj后缀函数
会将纹理坐标(coord.s, coord.t)除以coord的最后一个部分(coord.q).
含有类型为vec4的coord参数,则忽略其第三部分(coord.p)
2. bias参数函数
含有bias参数的纹理采样函数只能在片元着色器中调用,且此参数仅对sampler为mipmap类型的纹理时有意义.
3. Lod后缀函数
带有”Lod”后缀的纹理采样函数仅适用于顶点着色器. 函数仅对sampler为mipmap类型的纹理有意义.
4. texture3D系列纹理采样函数在标准的OpenGL ES 2.0 中还没有支持.
texture2D拥有三个参数,第一个参数表示纹理采样器。第二个参数表示纹理坐标,可以是二维、三维、或者四维。
第三个参数加入后只能在片元着色器中调用,且只对采样器为mipmap类型纹理时有效
纹理如何传入Fragment shader:
1、fragment shader中定义包括纹理采样器sampler0,如:
uniform sampler2D sampler0;
2、在代码中得到fragment shader中sampler0的句柄samplerId:
GLuint samplerId = GLES20.glGetUniformLocation(Program, “sampler0”); //建立代码和shader间通道
3、把纹理单元赋给shader中sampler
想让sampler对哪个纹理单元(GL_TEXTUREi—系统中可以以i的索引值表示)中的纹理进行采样/处理,如纹理单元选取GL_TEXTURE0,就给sampler2D赋值为0。
GLES20.glUniform1i(samplerId, 0); // 通过samplerId,把纹理单元赋值给shader中sampler(即sampler0)
4、后续shader中的sampler0的采样对象就是GL_TEXTURE0上绑定的纹理(纹理初始化:glGenTextures()->glBindTexture()->glTexParameteri()->GLUtils.texImage2D())
vec4 texture2D(sampler,vec2)取到相应的像素值并做处理,例如
vec4 color1 = texture2D(sampler0,texCoord); //无论纹理像素是什么格式的,都返回vec4类型
浮点精度
与顶点着色器不同的是,在片元着色器中使用浮点型时,必须指定浮点类型的精度,否则编译会报错。精度分别为:
lowp:低精度。8位。
mediump:中精度。10位。
highp:高精度。16位。
片元着色器最上面加上,如: uniform mediump float;
(precision <精度> <类型>,即可制定某种类型的默认精度。精度越高,画质越好,耗费资源越多)
内建变量
顶点着色器的内建变量:
输入变量:
gl_Position:顶点坐标
gl_PointSize:点的大小,没有赋值则为默认值1,通常设置绘图为点绘制才有意义。
片元着色器的内建变量:
输入变量:
gl_FragCoord:当前片元相对窗口位置所处的坐标。
gl_FragFacing:bool型,表示是否为属于光栅化生成此片元的对应图元的正面。
输出变量:
gl_FragColor:当前片元颜色
gl_FragData:vec4类型的数组。向其写入的信息,供渲染管线的后继过程使用。