概述
要在Android应用中使用OpenGL ES绘制图形就必须为它们创建一个视图容器,使用该容器这边就需要引入GLSurfaceView和GLSurfaceView.Renderer.GLSurfaceView是使用OpenGL和GLSurfaceView.Renderer绘制的图形的视图容器,用于控制在该视图中绘制内容.
下面就介绍如何使用GLSurfaceView和GLSurfceView.Renderer完成简单的三角形绘制.
清单文件中声明OpenGL的使用
如果我们的应用程序需要使用OpenGL ES2.0API,就需要在清单文件中进行声明1
2
3<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
创建activity
1 | public class OpenGlActivity extends AppCompatActivity { |
创建GLSurfaceView对象
GLSurfaceView是一个专门的视图,在上面可以绘制OpenGL ES图形,本身并没有太大的作用,实际的对象绘制是在GLSurfaceView.Renderer中进行控制的.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class MyGlSurfaceView extends GLSurfaceView implements View.OnTouchListener{
private final MyGLRender render;
public MyGlSurfaceView(Context context) {
super(context);
//设置openGL ES 版本
setEGLContextClientVersion(2);
render=new MyGLRender();
//设置渲染器
setRenderer(render);
//绘图数据发生更改时渲染视图
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
创建渲染器Renderer
Renderer控制在于其关联的SurfaceView上绘制内容,Renderer有三个方法供Android系统调用.
(1) onSurfaceCreated() 调用一次,设置OpenGL ES环境.
(2) onDrawFrame() 每次重绘进行时调用
(3) onSurfaceChange() 视图几何图形发生改变时进行调用(eg:设备的屏幕方向发生改变)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class MyRenerer implements GLSurfaceView.Renderer{
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig){
//设置背景颜色
GLES20.glClearColor(0f,0f,0f,1f);
}
@Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
//设置背景大小
GLES20.glViewport(0,0,i,i1);
}
@Override
public void onDrawFrame(GL10 gl10) {
//重绘背景颜色
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
}
定义三角形
OpenGL ES允许使用三维空间中的坐标定义绘制对象,所以在定义三角形之前,必须先定义其坐标.在OpenGL中,执行此操作的典型方法是为坐标定义浮点数的顶点数组。为了获得最大效率,可以将这些坐标写入ByteBuffer,并将其传递到OpenGL ES图形管道进行处理。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class Triangle{
private FloatBuffer vertexBuffer;
//数组中每个顶点的坐标
private static final int COOR_PER_VERTEX=3;
//按逆时针顺序
private static final float triangleCoords[]={
0.0f,0.5f,0.0f,//顶点
-0.5f,-0.5f,0.0f,//左顶点
0.5f,-0.5f,0f//右顶点
};
float color[]={0.0f,0.0f,0.0f,0.0f};
public Trangle(){
//为三角形坐标初始化顶点字节缓冲区
//(坐标值的数量*每一个浮点数4个字节)
ByteBuffer byteBuffer=ByteBuffer.allocateDirect(
trangleCoords.length*4);
//使用本机硬件的本机字节顺序
byteBuffer.order(ByteOrder.nativeOrder());
//从ByteBuffer创建一个浮点缓冲区
vertexBuffer = byteBuffer.asFloatBuffer();
//将坐标添加到FloatBuffer
vertexBuffer.put(triangleCoords);
//设置缓冲区读取第一个坐标
vertexBuffer.position(0);
}
}
初始化三角形
在进行绘图之前,必须初始化并加载计划绘制的形状,除非程序中使用的形状的结构(原始坐标)在执行过程中发生变化,否则应在渲染器的onSurfaceCreated()方法中初始化它们,以获得内存和处理效率1
2
3
4
5
6
7
8
9
10public class MyGLRender implements GLSurfaceView.Renderer{
private Triangle mTriangle;
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig){
//设置背景颜色
GLES20.glClearColor(0f,0f,0f,1f);
mTriangle=new Triangle();
}
}
绘制三角形
首先需要定义如下内容:
(1) Vertex Shader -顶点着色器,用于渲染形状顶点的OpenGL ES图形代码。
(2)Fragment Shader -OpenGL ES代码,用于渲染具有颜色或纹理的形状的面。
(3) Program -一个OpenGL ES对象,包含要用于绘制一个或多个形状的着色器。
我们需要至少一个顶点着色器来绘制形状,并使用一个片段着色器为该形状着色。必须编译这些着色器,然后将其添加到OpenGL ES程序中,然后使用该程序绘制形状。以下是如何定义可用于在Triangle类中绘制形状的基本着色器的示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Triangle{
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
}
着色器包含OpenGL着色语言(GLSL)代码,必须在OpenGL ES环境中使用它之前进行编译。要编译此代码,要Renderer类中创建以下该方法:1
2
3
4
5
6
7
8
9
10
11
12public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
创建Draw()方法绘制形状1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29private int mPositionHandle;
private int mColorHandle;
private static final int COORDS_PER_VERTEX = 3;
private final int vertexCount = triangleCoords.length /COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4;
public void draw(float[] mvpMatrix) {
//将程序添加到OpenGL ES环境
GLES20.glUseProgram(mProgram);
//获取顶点着色器位置成员的句柄
mPositionHandle=GLES20.glGetAttribLocation(mProgram, "vPosition");
//启用三角形顶点的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角坐标数据
GLES20.glVertexAttribPointer(mPositionHandle,COOR_PER_VERTEX,
GLES20.GL_FLOAT,false,vertexStride,vertexBuffer);
//获取片段着色器Color成员的句柄
mColorHandle=GLES20.glGetUniformLocation(mProgram,"vColor");
//设置绘制三角形的颜色
GLES20.glUniform4fv(mColorHandle,1,color,0);
//获得形状的变换矩阵的handle
mMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram,"uMVPMatrix");
//把变换矩阵传给着色器
GLES20.glUniformMatrix4fv(mMVPMatrixHandle,1,false,mvpMatrix,0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,vertexCount);
//禁用顶点数组
GLES20.glEnableVertexAttribArray(mPositionHandle);
}
最后在Renderer的onDrawFrame()方法中调用draw()方法.要想的三角形就出现啦!
小白一个后续更新!