Android---OpenGL ES之图形描画
本文译自:http://developer.android.com/training/graphics/opengl/draw.html
用OpenGL定义了要描画的图形之后,就可以来描画它们了。用OpenGL ES2.0来描画图形可能会比你想的要麻烦一些,因为它的API提供了很多基于图形渲染管道的控制。
本文会向你介绍如何绘制在《Android---OpenGL ES之形状定义》一文中定义的图形。
初始化图形
在进行任何绘制操作之前,必须初始化并加载你要绘制的图形。除非在绘制期间,程序中所使用的图形的结构体(原始坐标)发生改变,否则应该在渲染器的onSurfaceCreated()方法中初始化它们,以便提高内存和处理的效率。
publicvoidonSurfaceCreated(GL10 unused,EGLConfig config){
...
// initialize a triangle
mTriangle = new Triangle();
// initialize a square
mSquare = new Square();
}
描画图形
描画一个使用OpenGL ES2.0定义的图形,需要一些重要的代码,因为你必须给图形渲染管道提供很多绘图细节。特别是要提供以下定义:
1. 顶点着色器(Vertex Shader)---用于渲染图形顶点的OpenGL ES图形代码;
2. 片段着色器(Fragment Shader)---用于渲染带有颜色和纹理的图形表面的OpenGL ES代码
3. Program---它是一个OpenGL ES对象,其中包含了用于绘制图形所需的着色器。
你至少需要一个用于绘制图形的顶点着色器和一个给图形着色的片段着色器。这些着色器必须被编译,并要添加到OpenGL ES的Program对象中,然后使用Program对象来绘制图形。下例显示了如何定义用于绘制图形的基本的着色器:
privatefinalStringvertexShaderCode=
"attribute vec4vPosition;" +
"void main() {" +
" gl_Position =vPosition;" +
"}";
private final StringfragmentShaderCode =
"precision mediumpfloat;" +
"uniform vec4vColor;" +
"void main() {" +
" gl_FragColor= vColor;" +
"}";
着色器包含了OpenGL的着色语言代码(GLSL),在使用它之前,必须在OpenGL ES环境中编译它。你可以在你的渲染器类中创建一个实用的方法,来编译这些代码:
publicstaticintloadShader(int type,StringshaderCode){
// create a vertex shadertype (GLES20.GL_VERTEX_SHADER)
// or a fragment shadertype (GLES20.GL_FRAGMENT_SHADER)
intshader = GLES20.glCreateShader(type);
// add the source code tothe shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
为了绘制你的图形,你必须编译着色器代码、把着色器添加给OpenGL ES的Program对象中,并且要把Program对象连接到OpenGL ES引擎中。在要绘制的对象的构造器中做这件事,以便只做一次。
注意:编译OpenGL ES着色器和连接程序是非常消耗CPU的计算周期和处理时间的,因此要尽量避免多次处理。如果你要在运行时了解着色器的内容,那么就应该在运行时只创建一次并加以缓存,以便后续使用。
publicTriangle(){
...
intvertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
intfragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL ES programexecutables
}
至此,你已经添加了绘制图形的实际调用。用OpenGL ES绘制图形要求你指定一个参数,以便告诉渲染管道你所要会的内容,以及如何绘制它。因为绘制选项会因图形不同而有所差异,创建自己的图形类,并包含它们自己的绘图逻辑是一种好的做法。
给要绘制的图形创建一个draw()方法,这是给图形的顶点着色器和片段着色器设置位置和颜色值的地方,然后执行这个绘制函数。
publicvoid draw(){
// Add program to OpenGLES environment
GLES20.glUseProgram(mProgram);
// get handle to vertexshader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to thetriangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the trianglecoordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader'svColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawingthe triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
编写完成draw()方法后,绘制这个对象时只需在你的渲染器的onDrawFrame()方法中调用draw()方法即可。运行你的应用程序时,显示结果如下图所示:
图1.不使用投影或摄像视图所绘制的三角形