在上一篇博客我们简单的搭建了一个OpenGL ES的框架,本节让我们看看如何编写OpenGL ES 代码绘制一个简单的三角形吧。
首先 我们编写顶点着色器和片元着色器
顶点着色器(Vertex Shader) 用来确定形状。
片元着色器(Fragment Shader)用来确定颜色
着色器代码,如下:
//顶点着色器
public static final String VERTEX_SHADER_SOURCE ="" +
"attribute vec4 vPosition;\n" +
"void main(){\n" +
" gl_Position = vPosition;\n" +
"}";
//片元着色器
public static final String FRAGMENT_SHADER_SOURCE = "" +
"precision mediump float;\n" +
"uniform vec4 fColor;\n" +
"void main() {\n" +
" gl_FragColor = fColor;\n" +
"}";
上面就是最简单的着色器代码了,就是两段字符串。当然你也可以写在单独的文件中,然后编写工具类加载成String。
- 首先分析顶点着色器
1、attribute 属性变量,只能用在顶点着色器,用来将数据由应用程序传输给顶点着色器
2、vec4是数据类型,表示包含4个浮点型数据的向量
3、vPosition就是我们自己定义的变量了。
4、gl_Position 是顶点着色器内置变量,表示顶点着色器中顶点位置。
通常我们在应用程序中把位置传给vPosition变量,在由vPosition变量传给gl_Position,这样顶点位置就确定了。
- 接着分析片元着色器
1、precision mediump 是精度,在片元着色器中使用浮点类型数据,必须指定其精度。precision lowp 低精度、precision mediump 中精度、precision highp 高精度。
2、uniform 一致变量,着色器执行期间一致变量的值是不变的
3、gl_FragColor: vec4类型,片元着色器内置变量,表示片元颜色
我们在应用程序中把颜色传给我们自己定义的fColor变量,在由fColor变量传给gl_FragColor,这样颜色就确定了。
着色器创建好了,接着需要使用它们。
//创建顶点着色器,vShader是创建的着色器的句柄
int vShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
//设置着色器的源码
GLES20.glShaderSource(vShader, VERTEX_SHADER_SOURCE);
//编译代码
GLES20.glCompileShader(vShader);
//创建片元着色器
int fShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
//设置着色器的源码
GLES20.glShaderSource(fShader, FRAGMENT_SHADER_SOURCE);
//编译
GLES20.glCompileShader(fShader);
//创建程序
glProgram = GLES20.glCreateProgram();
//将两个着色器添加到程序中
GLES20.glAttachShader(glProgram,vShader);
GLES20.glAttachShader(glProgram,fShader);
//链接程序
GLES20.glLinkProgram(glProgram);
GLES20.glCreateShader() 创建一个着色器对象,方法的参数可以是GL_VERTEX_SHADER 和或GL_FRAGMENT_SHADER ,代表是创建顶点着色器还是片元着色器,方法的返回值可以理解为着色器的指针或者句柄。
经过上面的代码,我们将创建好了opengl es 程序对象了,并且把我们的着色器添加进去,并且进行了链接,接着我们就可以使用该程序。
public void draw() {
//加载并使用链接好的程序
GLES20.glUseProgram(glProgram);
//获取指定名称的attribute变量位置
int vPositionLocation = GLES20.glGetAttribLocation(glProgram, "vPosition");
//允许使用顶点坐标数组
GLES20.glEnableVertexAttribArray(vPositionLocation);
//将顶点数据赋值到指定属性
GLES20.glVertexAttribPointer(vPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
//获取指定名称的uniform变量位置
int fColorLocation = GLES20.glGetUniformLocation(glProgram, "fColor");
//给指定的Uniform变量赋值 因为color包含4个值所以调用glUniform4fv
GLES20.glUniform4fv(fColorLocation,1,color,0);
//绘制
//GL_TRIANGLES会是三角形 0:告诉 OpenGL 从顶点数组的开头处开始读顶点,vertexCount:告诉 OpenGL 读入vertexCount个顶点
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,vertexCount);
//禁用指定顶点属性
GLES20.glDisableVertexAttribArray(vPositionLocation);
GLES20.glUseProgram(GLES20.GL_NONE);
}
glVertexAttribPointer(
int indx,//我们要修改的顶点属性的位置
int size,//每个顶点属性组件的数量,这里传入3,每个顶点由(x,y,z)组成
int type,//每个组件的数据类型
boolean normalized,//是否归一化处理
int stride,//指定连续顶点属性之间的偏移量,偏移量0表示精密排列
java.nio.Buffer ptr//顶点数据
)
glDrawArrays(
int mode,//GL_TRIANGLES 绘制三角形
int first,// 0:告诉 OpenGL 从顶点数组的开头处开始读顶点
int count // 读入几个顶点
);
接下来就是确定顶点数据
上图是二维坐标系,事实上opengles 坐标系是三维的 还有一个z轴我没有画。
我们要在这样一个坐标系中绘制一个三角形,如图
这样我们就确定了顶点位置了。
//顶点位置
static float[] triangle = {
-0.5f,-0.5f,0f,
0.5f,-0.5f,0f,
0f,0.5f,0f
};
//每个顶点三个组件组成(x,y,z)
private int COORDS_PER_VERTEX = 3;
//顶点数量,三角形 三个点
private final int vertexCount = triangle.length / COORDS_PER_VERTEX;
最后还需要颜色
//颜色:R,G,B,A
static float[] color = {
1.0f,0.0f,0f,1f
};