学习资料来源:java
OpenGL ES 3.0编程指南android
OpenGL ES 2 for Android —a Quick-Start Guidec++
https://developer.android.com/guide/topics/graphics/opengl编程
上一节中学习了opengl es的大致执行过程,这一节学习一下着色器这块内容。数组
若是要使用着色器进行渲染的时候,须要建立两个基本对象:着色器和程序对象。着色器对象和程序对象能够理解为c中的编译器和连接程序:ide
在c中将一段代码编译成目标代码,在建立目标文件后,c连接程序会将对象文件连接为最后的程序函数
着色器对象是包含的歌着色器的对象。源代码提供给着色器对象,而后着色器对象被编译成一个目标形式。学习
得到连接后的桌而起对象通常6个步骤:ui
注意:居于Android系统code
//GL_VERTEX_SHADER or GL_FRAGMENT_SHADER 建立对应的着色器,返回着色器句柄 int shader1= GLES30.glCreateShader(type); //删除对应的着色器对象句柄 GLES30.glDeleteShader(shader1); //为着色器对象提供源代码,参数依次:shader句柄,shader代码 GLES30.glShaderSource(shader,shaderSourceCode); //编译着色器对象 GLES30.glCompileShader(shader);
上述描述了如何去建立和编译一个着色器对象。
建立程序对象代码以下:
//建立程序对象 mProgram = GLES30.glCreateProgram(); //与着色器进行连接,每一个程序对象须要连接一个顶点着色器和一个片断着色器 GLES30.glAttachShader(mProgram, vertexShader); GLES30.glAttachShader(mProgram, fragmentShader); //连接程序对象 GLES30.glLinkProgram(mProgram);
上面写好后能够看到对应着上方的六个步骤。全部步骤完成后须要在执行以下代码:
GLES30.glUseProgram(mProgram);
该代码代表激活程序对象,而后就能够渲染了。
###opengl es 着色语言
在计算机图形中,两个基本数据类型组成变换基础:向量和矩阵。这两种数据在opengl es的着色语言中也是核心(ps:学很差线性代数就流泪...)。opengl es着色语言数据类型以下:
变量分类 | 类型 | 描述 |
---|---|---|
标量 | float,int,uint,bool | 与c对应变量解释一致 |
浮点向量 | float,vec2,vec3,vec4 | 有1,2,3,4个份量的基于浮点的向量类型 |
整数向量 | int,,ivec2,ivec3,ivec4 | 有1,2,3,4个份量的基于整数的向量类型 |
无符号向量 | uint,,uvec2,uvec3,uvec4 | 有1,2,3,4个份量的基于无符号整数的向量类型 |
布尔变量 | bool,bvec2,bvec3,bvec4 | 有1,2,3,4个份量的基于布尔值的向量类型 |
矩阵 | mat2(mat2x2底下类推),mat2x3,mat3x2,mat3,mat3x4,mat4x2,mat4x3,mat4 | 2x2,2x3,3x2,3x3,3x4,4x2,4x3,4x4的基于浮点的矩阵 |
声明例子,与c语法相近:
float a; vec4 v; mat4 m; ivec2 iv;
标量
float mm=1.0; float mm=1;//不正确,语法很是严格 bool ll=true; int kk=0; int ka=0.0;//error float sd=float(ll) //转换成float
向量
vec4 myVec4=vec4(1.0);//myVec4={1.0,1.0,1.0,1.0} vec3 myVec3=vec3(1.0,1.0,1.0); vec3 temp=vec3(myVec3);//赋值操做 vec2 myVec2=vec2(myVec3);//myVec2={1.0,1.0}即取x,y点 vec4 myVec4=vec4(myVec2,temp);//myVec4={myVec2.x,myVec2.y,temp.x,temp.y}
向量和矩阵份量
向量的单独份量能够用两种方式访问,**"."运算符号和数组下标的形式。**根据组成向量 的份量数量,每一个份量可使用{x,y,z,w}或{r,g,b,a}或者{s,t,p,q}来访问。使用"."运算符号售后,能够再操做中从新排列响亮的份量,如:
vec3 my3=vec3(1.0,0.0,3.0); vec3 temp; temp=my3.xyz;//(1.0,0.0,3.0) temp=my3.yzx;//(0.0,3.0,1.0)
矩阵有向量组成,如mat2能够当作两个vec2等,例子:
mat4 m=mat4(1.0); vec4 v4=m[0]; float k=mat4[0][1];
常量
const float zrto=0.0;
结构体
struct ff{ vec4 volor; float end; } fo; //初始化能够跟c相同,也能够以下 fo=ff(vec4(0.0,0.0,0.0,0.0),4.0);
数组
float fl[4]; vec4 vec[2];
函数
函数声明跟c语言的相同,惟一不一样在于函数参数的传递方法,opengl es有特殊的限定符,定义函数是否能够修改可变参数:
限定符 | 描述 |
---|---|
in | 指定参数按值传送,函数不能修改 |
inout | 规定变量按引用传入函数,若是该值被修改,他将在函数退出后变化 |
out | 表示该变量不被传入函数,但在函数返回时候被修改 |
关于opengl es着色语言中的函数还要注意一点,**函数不能递归。**这一限制的缘由是某些实现经过吧函数代码真正内嵌到GPU生成的最终程序实施函数调用。着色语言有意构造这种内嵌式实现,以支持没有堆栈的GPU。
顶点着色器的输入和输出
定点输入变量用于指定顶点着色器中每一个顶点的输入,用in关键字指定。他们一般存储位置,发现,纹理坐标和颜色这样的数据。(能够理解为从咱们程序中写的代码中去读取对应变量的值)
in vec4 a_Position; in vec3 a_color; out vec3 v_color; void main()[ v_color=a_color; ]
这个着色器的两个顶点输入变量a_position和a_color的数据由应用程序加载。相对应的有in就有out,out表明着来自顶点着色器的输出变量。基本上来讲,从顶点着色器out的值由片断着色器接收,这些out出去的变量在片断着色器中会经过in的形式进行接收。
控制流语句(if else)跟c同样,不展开。