This article teaches how to use OpenGL in Android phone.
There are two classes must be create and implement GLSurfaceView and Renderer.
The article
OpenGL explains classes do. I just focus the implement step.
Step1:Create a new project in the Eclipse. I supposed that you already known how.
Step2:.Modify the layout file "main.xml".
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/frameLayout1">
</FrameLayout>
Step3:Create a new class i named OpenGLRenderer.The class must implement the Renderer class.
package my.project.MyFirstOpenGL;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.widget.FrameLayout;
public class OpenGLRenderer implements Renderer
{
public OpenGLRenderer(Context context, FrameLayout mainLayout)
{
}
@Override
public void onDrawFrame(GL10 arg0)
{
// TODO Auto-generated method stub
}
@Override
public void onSurfaceChanged(GL10 arg0, int arg1, int arg2)
{
// TODO Auto-generated method stub
}
@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1)
{
// TODO Auto-generated method stub
}
}
Step4:In the OpenGLRenderer constructor, we need the Context and FrameLayout parameters.
And create the GLSurfaceView add to the frameLayout.
public OpenGLRenderer(Context context, FrameLayout mainLayout)
{
this.context = context;
//
// Create GLSurfaceView and set this class as the renderer.
//
GLSurfaceView glView = new GLSurfaceView(context);
glView.setRenderer(this);
//put to Main layout
mainLayout.addView(glView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
Step5:Put some basic OpenGL code to the other functions.
public void onDrawFrame(GL10 gl)
{
// Clear the whole screen and depth.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Setting the GL_MODELVIEW matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Load the Identity matrix
gl.glLoadIdentity();
}
public void onSurfaceChanged(GL10 gl, int width, int height)
{
// Set OpenGL viewport
gl.glViewport(0, 0, width, height);
// Setting the GL_PROJECTION matrix
gl.glMatrixMode(GL10.GL_PROJECTION);
// Load the Identity matrix
gl.glLoadIdentity();
float ratio = (float) width / height;
// Set the fovy to 45 degree. near depth is 0.1f and far depth is 100.f.
// And maintain the screen ratio.
GLU.gluPerspective(gl, 45, ratio, 0.1f, 100.f);
}
public void onSurfaceCreated(GL10 gl, EGLConfig arg1)
{
// Set the background to black
gl.glClearColor(0, 0, 0, 0);
}
Step6:And now we can add OpenGLRenderer class to the main code.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FrameLayout mainLayout = (FrameLayout) findViewById(R.id.frameLayout1);
//
// Create OpenGL surface and render
//
OpenGLRenderer gl3DView = new OpenGLRenderer(this, mainLayout);
}
Step7:OK, We put the necessarily code to the project.Now we can run this project on emulator.But there is nothing in the screen but the black.
Step8:At this stage, we create a OpenGL environment, but we did not put things in there.
I want load a picture and map to a plane , then rotate it.
//
// Load the Texture
//
private void LoadTexture(GL10 gl, Context cont)
{
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
InputStream istream = cont.getResources().openRawResource(R.drawable.guam);
Bitmap bitmap;
try{
bitmap = BitmapFactory.decodeStream(istream);
}
finally{
try{
istream.close();
}
catch(IOException e){}
}
gl.glGenTextures(MAX_TEXTURE, textureID, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID[0]);
GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bitmap, 0 );
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
bitmap.recycle();
mTextureBuffer = getNativeFloatBuffer(squTex);
mVerticesBuffer = getNativeFloatBuffer(squVtx);
mIndexBuffer = getNativeShortBuffer(squInx);
}
//
// Draw the scene
//
private void DrawTheScene(GL10 gl)
{
gl.glEnable( GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, mVerticesBuffer);
gl.glTexCoordPointer( 2, GL10.GL_FLOAT, 0, mTextureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID[0]);
gl.glDrawElements( GL10.GL_TRIANGLE_FAN,
squInx.length,
GL10.GL_UNSIGNED_SHORT,
mIndexBuffer);
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
Step9:We need some variables.
private float orientation = 0.0f;;
final int MAX_TEXTURE = 20;
private int[] textureID = new int[MAX_TEXTURE];
// UV Coordinates
// _________
// v0(0,0) | | v3(1,0)
// | |
// | |
// v1(0,1) |_________| v2(1,1)
//
//
// plane vertices
// _________
// p0 | | p3
// | |
// | |
// p1 |_________| p2
//
float squVtx[] = {
-1.0f, 1.0f, 0.0f, //p0 Left-Top corner
-1.0f, -1.0f, 0.0f, //p1 Left-bottom corner
1.0f, -1.0f, 0.0f, //p2 Right-bottom corner
1.0f, 1.0f, 0.0f };//p3 Right-top corner
// USE GL_TRIANGLE_FAN
short squInx[] = { 0, 1, 2, 3}; //0-1-2 first triangle
//0-2-3 second triangle
float squTex[] ={ 0.0f, 0.0f, //v0 Left-Top corner
0.0f, 1.0f, //v1 Left-bottom corner
1.0f, 1.0f, //v2 Right-top corner
1.0f, 0.0f };//v3 Right-bottom corner
// Our UV texture buffer.
private FloatBuffer mTextureBuffer;
private FloatBuffer mVerticesBuffer;
private ShortBuffer mIndexBuffer;
Step10:Add LoadTexture() and DrawTheScene() to the code.
public void onSurfaceCreated(GL10 gl, EGLConfig arg1)
{
// Set the background to black
gl.glClearColor(0, 0, 0, 0);
//Load the texture
LoadTexture(gl, context);
}
public void onDrawFrame(GL10 gl)
{
// Clear the whole screen and depth.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Setting the GL_MODELVIEW matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Load the Identity matrix
gl.glLoadIdentity();
// Move to Z = -10
gl.glTranslatef(0, 0, -10f);
// Rotate y-asix
gl.glRotatef(orientation, 0, 1.0f, 0);
//every time plus 1 defgee.
orientation += 1.0f;
if ( orientation >= 360 )
orientation = 0.0f;
// Draw the scene
DrawTheScene(gl);
}
Step11:Another functions.
private FloatBuffer getNativeFloatBuffer(float[] buffer)
{
ByteBuffer ibb = ByteBuffer.allocateDirect(buffer.length*4);
ibb.order(ByteOrder.nativeOrder());
FloatBuffer fbf = ibb.asFloatBuffer();
fbf.put(buffer);
fbf.position(0);
return fbf;
}
private ShortBuffer getNativeShortBuffer(short[] buffer)
{
ByteBuffer ibb = ByteBuffer.allocateDirect(buffer.length*2);
ibb.order(ByteOrder.nativeOrder());
ShortBuffer sbf = ibb.asShortBuffer();
sbf.put(buffer);
sbf.position(0);
return sbf;
}
Step12:Finally, we put the picture to the OpenGL texture resources and draw 2 triangles to show the picture. Then rotate it frame by fame.