3D C/C++ tutorials -> OpenGL ES 2.0 -> OpenGL ES 2.0 on Android
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
Dependencies and prerequisites
Install
For more information read
OpenGLES20Android.java
package com.example.android.opengl;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.Matrix;
public class OpenGLES20Android extends Activity implements GLSurfaceView.Renderer
{
private GLSurfaceView SurfaceView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SurfaceView = new GLSurfaceView(this);
setContentView(SurfaceView);
SurfaceView.setEGLContextClientVersion(2);
SurfaceView.setRenderer(this);
}
@Override
protected void onPause()
{
super.onPause();
SurfaceView.onPause();
}
@Override
protected void onResume()
{
super.onResume();
SurfaceView.onResume();
}
private int Texture, Program, VertexBufferObject;
private int[] Location = new int[3];
private float[] Model = new float[16];
private float[] View = new float[16];
private float[] ModelView = new float[16];
private float[] Projection = new float[16];
private float[] ModelViewProjection = new float[16];
private static float Angle = 0.0f;
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config)
{
Texture = LoadTexture2D(R.raw.texture);
Program = CreateProgram(R.raw.texturing_vs, R.raw.texturing_fs);
Location[0] = GLES20.glGetUniformLocation(Program, "ModelViewProjection");
Location[1] = GLES20.glGetAttribLocation(Program, "vert_TexCoord");
Location[2] = GLES20.glGetAttribLocation(Program, "vert_Position");
float data[] = { // s, t, x, y, z
0.0f, 0.0f, -0.5f, -0.5f, -0.5f,
1.0f, 0.0f, -0.5f, -0.5f, 0.5f,
1.0f, 1.0f, -0.5f, 0.5f, 0.5f,
1.0f, 1.0f, -0.5f, 0.5f, 0.5f,
0.0f, 1.0f, -0.5f, 0.5f, -0.5f,
0.0f, 0.0f, -0.5f, -0.5f, -0.5f,
0.0f, 0.0f, 0.5f, -0.5f, 0.5f,
1.0f, 0.0f, 0.5f, -0.5f, -0.5f,
1.0f, 1.0f, 0.5f, 0.5f, -0.5f,
1.0f, 1.0f, 0.5f, 0.5f, -0.5f,
0.0f, 1.0f, 0.5f, 0.5f, 0.5f,
0.0f, 0.0f, 0.5f, -0.5f, 0.5f,
0.0f, 0.0f, -0.5f, -0.5f, -0.5f,
1.0f, 0.0f, 0.5f, -0.5f, -0.5f,
1.0f, 1.0f, 0.5f, -0.5f, 0.5f,
1.0f, 1.0f, 0.5f, -0.5f, 0.5f,
0.0f, 1.0f, -0.5f, -0.5f, 0.5f,
0.0f, 0.0f, -0.5f, -0.5f, -0.5f,
0.0f, 0.0f, -0.5f, 0.5f, 0.5f,
1.0f, 0.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 0.5f, 0.5f, -0.5f,
1.0f, 1.0f, 0.5f, 0.5f, -0.5f,
0.0f, 1.0f, -0.5f, 0.5f, -0.5f,
0.0f, 0.0f, -0.5f, 0.5f, 0.5f,
0.0f, 0.0f, 0.5f, -0.5f, -0.5f,
1.0f, 0.0f, -0.5f, -0.5f, -0.5f,
1.0f, 1.0f, -0.5f, 0.5f, -0.5f,
1.0f, 1.0f, -0.5f, 0.5f, -0.5f,
0.0f, 1.0f, 0.5f, 0.5f, -0.5f,
0.0f, 0.0f, 0.5f, -0.5f, -0.5f,
0.0f, 0.0f, -0.5f, -0.5f, 0.5f,
1.0f, 0.0f, 0.5f, -0.5f, 0.5f,
1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
0.0f, 1.0f, -0.5f, 0.5f, 0.5f,
0.0f, 0.0f, -0.5f, -0.5f, 0.5f,
};
VertexBufferObject = CreateVertexBufferObject(data);
Matrix.setLookAtM(View, 0, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
}
@Override
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setIdentityM(Model, 0);
Matrix.rotateM(Model, 0, Angle, 0.0f, 1.0f, 0.0f);
Matrix.rotateM(Model, 0, Angle, 1.0f, 0.0f, 0.0f);
Angle += 0.25f;
Matrix.multiplyMM(ModelView, 0, View, 0, Model, 0);
Matrix.multiplyMM(ModelViewProjection, 0, Projection, 0, ModelView, 0);
GLES20.glUseProgram(Program);
GLES20.glUniformMatrix4fv(Location[0], 1, false, ModelViewProjection, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VertexBufferObject);
GLES20.glEnableVertexAttribArray(Location[1]);
GLES20.glVertexAttribPointer(Location[1], 2, GLES20.GL_FLOAT, false, 20, 0);
GLES20.glEnableVertexAttribArray(Location[2]);
GLES20.glVertexAttribPointer(Location[2], 3, GLES20.GL_FLOAT, false, 20, 8);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, Texture);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glDisableVertexAttribArray(Location[2]);
GLES20.glDisableVertexAttribArray(Location[1]);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glUseProgram(0);
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
Matrix.perspectiveM(Projection, 0, 45.0f, (float)width / (float)height, 0.125f, 512.0f);
}
private int GetMaxAnisotropy()
{
int[] maxAnisotropy = new int[1];
GLES20.glGetIntegerv(GLES11Ext.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy, 0);
return maxAnisotropy[0];
}
private int LoadTexture2D(int resourceId)
{
int[] texture = new int[1];
GLES20.glGenTextures(1, texture, 0);
if(texture[0] == 0)
{
throw new RuntimeException("\nError creating texture (" + resourceId + ")!");
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resourceId, options);
if(bitmap == null)
{
throw new RuntimeException("\nError loading texture (" + resourceId + ")!");
}
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES11Ext.GL_TEXTURE_MAX_ANISOTROPY_EXT, GetMaxAnisotropy());
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
bitmap.recycle();
return texture[0];
}
private String LoadShaderSource(int resourceId)
{
InputStream inputStream = getResources().openRawResource(resourceId);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String string;
StringBuilder stringBuilder = new StringBuilder();
try
{
while((string = bufferedReader.readLine()) != null)
{
stringBuilder.append(string);
stringBuilder.append('\n');
}
}
catch(IOException e)
{
return null;
}
return stringBuilder.toString();
}
private int CreateShader(int type, int resourceId)
{
int shader = GLES20.glCreateShader(type);
if(shader == 0)
{
throw new RuntimeException("\nError creating shader (" + resourceId + ")!");
}
GLES20.glShaderSource(shader, LoadShaderSource(resourceId));
GLES20.glCompileShader(shader);
int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if(compileStatus[0] == GLES20.GL_FALSE)
{
String info = GLES20.glGetShaderInfoLog(shader);
GLES20.glDeleteShader(shader);
throw new RuntimeException("\nError compiling shader (" + resourceId + "):\n" + info);
}
return shader;
}
private int CreateProgram(int vertexShaderResourceId, int fragmentShaderResourceId)
{
int vertexShader = CreateShader(GLES20.GL_VERTEX_SHADER, vertexShaderResourceId);
int fragmentShader = CreateShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderResourceId);
int program = GLES20.glCreateProgram();
if(program == 0)
{
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);
throw new RuntimeException("\nError creating program (" + vertexShaderResourceId + ", " + fragmentShaderResourceId + ")!");
}
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if(linkStatus[0] == GLES20.GL_FALSE)
{
String info = GLES20.glGetProgramInfoLog(program);
GLES20.glDetachShader(program, vertexShader);
GLES20.glDetachShader(program, fragmentShader);
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);
GLES20.glDeleteProgram(program);
throw new RuntimeException("\nError linking program (" + vertexShaderResourceId + ", " + fragmentShaderResourceId + "):\n" + info);
}
return program;
}
private int CreateVertexBufferObject(float[] data)
{
int[] vertexBufferObject = new int[1];
GLES20.glGenBuffers(1, vertexBufferObject, 0);
if(vertexBufferObject[0] == 0)
{
throw new RuntimeException("\nError creating vertex buffer object!");
}
FloatBuffer buffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
buffer.put(data).position(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferObject[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * 4, buffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return vertexBufferObject[0];
}
}
texturing_vs
uniform mat4 ModelViewProjection;
attribute vec2 vert_TexCoord;
attribute vec3 vert_Position;
varying vec2 TexCoord;
void main()
{
TexCoord = vert_TexCoord;
gl_Position = ModelViewProjection * vec4(vert_Position, 1.0);
}
texturing_fs
precision mediump float;
uniform sampler2D Texture;
varying vec2 TexCoord;
void main()
{
gl_FragColor = texture2D(Texture, TexCoord);
}
Download
|