- BufferUtils
- TextureUtils
- Shader
- GLSurfaceView
- Renderer
- Model
- GLBitmap
- GLUnfoldBitmap
BufferUtils
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
public class BufferUtils {
public static FloatBuffer newFloatBuffer (int numFloats) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
buffer.order(ByteOrder.nativeOrder());
return buffer.asFloatBuffer();
}
public static DoubleBuffer newDoubleBuffer (int numDoubles) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
buffer.order(ByteOrder.nativeOrder());
return buffer.asDoubleBuffer();
}
public static ByteBuffer newByteBuffer (int numBytes) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
buffer.order(ByteOrder.nativeOrder());
return buffer;
}
public static ShortBuffer newShortBuffer (int numShorts) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
buffer.order(ByteOrder.nativeOrder());
return buffer.asShortBuffer();
}
public static CharBuffer newCharBuffer (int numChars) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
buffer.order(ByteOrder.nativeOrder());
return buffer.asCharBuffer();
}
public static IntBuffer newIntBuffer(int numInts) {
ByteBuffer buffer = ByteBuffer.allocate(numInts * 4);
buffer.order(ByteOrder.nativeOrder());
return buffer.asIntBuffer();
}
public static LongBuffer newLongBuffer(int numLongs) {
ByteBuffer buffer = ByteBuffer.allocate(numLongs * 8);
buffer.order(ByteOrder.nativeOrder());
return buffer.asLongBuffer();
}
}
TextureUtils
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
public class TextureUtils {
public static int loadTexture(Context context, int drawableID) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableID);
int textureName = loadTexture(bitmap);
bitmap.recycle();
return textureName;
}
public static int loadTexture(Bitmap bitmap) {
int textureName[] = new int[1];
GLES20.glGenTextures(1, textureName, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
return textureName[0];
}
}
Shader
import android.content.Context;
import android.content.res.AssetManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class ShaderUtils {
public static String readShaderFileFromRawResource(final Context context, final int resourceId)
{
final InputStream inputStream = context.getResources().openRawResource(resourceId);
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String nextLine;
final StringBuilder body = new StringBuilder();
try
{
while ((nextLine = bufferedReader.readLine()) != null)
{
body.append(nextLine);
body.append("\n");
}
}
catch(IOException e)
{
return null;
}
return body.toString();
}
public static String readShaderFileFromFilePath(final Context context, final String filePath)
{
try
{
AssetManager assetManager = context.getAssets();
InputStream ims = assetManager.open(filePath);
String re = convertStreamToString(ims);
}
catch (Exception e)
{
e.printStackTrace();
}
return "";
}
public static String convertStreamToString(InputStream is)
{
Scanner s = new Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
import android.graphics.Color;
import android.graphics.PointF;
import android.opengl.GLES20;
import android.renderscript.Float2;
import android.renderscript.Float3;
import android.renderscript.Float4;
import android.renderscript.Matrix3f;
import android.renderscript.Matrix4f;
import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
public class ShaderProgram {
private String vertexShaderSource;
private String fragmentShaderSource;
private int vertexShaderHandle;
private int fragmentShaderHandle;
private int programHandle;
private String log = "";
private boolean isCompiled;
private HashMap<String, Integer> uniforms = new HashMap<>();
private HashMap<String, Integer> attributes = new HashMap<>();
public ShaderProgram(String vertexShader, String fragmentShader) {
if(vertexShader == null) throw new IllegalArgumentException("vertex shader must not be null");
if(fragmentShader == null) throw new IllegalArgumentException("fragment shader must not be null");
vertexShaderSource = vertexShader;
fragmentShaderSource = fragmentShader;
compileShaders(vertexShader, fragmentShader);
if(isCompiled()) {
fetchAttributes();
fetchUniforms();
}
}
// is this valid shader program?
public boolean isValid() {
return isCompiled;
}
// start to use shader program
public void begin() {
GLES20.glUseProgram(programHandle);
}
// end of using shader program
public void end() {
GLES20.glUseProgram(0);
}
// destory the shader program
public void destroy() {
GLES20.glUseProgram(0);
GLES20.glDeleteShader(vertexShaderHandle);
GLES20.glDeleteShader(fragmentShaderHandle);
GLES20.glDeleteProgram(programHandle);
}
private void compileShaders(String vertexShader, String fragmentShader) {
vertexShaderHandle = loadShader(GLES20.GL_VERTEX_SHADER, vertexShader);
fragmentShaderHandle = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
if(vertexShaderHandle == -1 || fragmentShaderHandle == -1) {
isCompiled = false;
return;
}
programHandle = linkProgram(createProgram());
if(programHandle == -1) {
isCompiled = false;
return;
}
isCompiled = true;
}
private int createProgram() {
int program = GLES20.glCreateProgram();
return program != 0 ? program : -1;
}
private int linkProgram(int program) {
if(program == -1)
return -1;
GLES20.glAttachShader(program, vertexShaderHandle);
GLES20.glAttachShader(program, fragmentShaderHandle);
GLES20.glLinkProgram(program);
int[] linked = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linked, 0);
if(linked[0] == GLES20.GL_FALSE) {
String infoLog = GLES20.glGetProgramInfoLog(program);
log += infoLog;
GLES20.glDeleteProgram(program);
return -1;
}
return program;
}
private int loadShader(int shaderType, String shaderCode) {
int shader = GLES20.glCreateShader(shaderType);
if(shader == 0)
return -1;
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if(compiled[0] == GLES20.GL_FALSE) {
String infoLog = GLES20.glGetShaderInfoLog(shader);
log += infoLog;
GLES20.glDeleteShader(shader);
return -1;
}
return shader;
}
public String getLog() {
if(isCompiled) {
log = GLES20.glGetProgramInfoLog(programHandle);
return log;
} else {
return log;
}
}
public boolean isCompiled() {
return isCompiled;
}
private int fetchAttributeLocation(String name) {
int location = attributes.get(name);
if(location == -1) {
location = GLES20.glGetAttribLocation(programHandle, name);
if(location != -1) {
attributes.put(name, location);
}
}
return location;
}
private int fetchUniformLocation(String name) {
int location = uniforms.get(name);
if(location == -1) {
location = GLES20.glGetUniformLocation(programHandle, name);
if(location != -1) {
uniforms.put(name, location);
}
}
return location;
}
private void fetchAttributes() {
attributes.clear();
IntBuffer params = IntBuffer.allocate(1);
IntBuffer type = IntBuffer.allocate(1);
GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_ATTRIBUTES, params);
int numAttributes = params.get(0);
for(int i=0; i<numAttributes; i++) {
params.compact();
params.put(0, 1);
type.clear();
String name = GLES20.glGetActiveAttrib(programHandle, i, params, type);
int location = GLES20.glGetAttribLocation(programHandle, name);
attributes.put(name, location);
}
}
private void fetchUniforms() {
uniforms.clear();
IntBuffer params = IntBuffer.allocate(1);
IntBuffer type = IntBuffer.allocate(1);
GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_UNIFORMS, params);
int numUniform = params.get(0);
for(int i=0; i<numUniform; i++) {
params.compact();
params.put(0, 1);
type.clear();
String name = GLES20.glGetActiveUniform(programHandle, i, params, type);
int location = GLES20.glGetUniformLocation(programHandle, name);
uniforms.put(name, location);
}
}
/**
* @param name name the name of the uniform
* @return the location of the uniform or -1.
*/
public int getUniformLocation(String name) {
return uniforms.get(name) == null ? -1 : uniforms.get(name);
}
/**
* @param name the name of the attribute
* @return the location of the attribute or -1.
*/
public int getAttributeLocation(String name) {
return attributes.get(name) == null ? -1 : attributes.get(name);
}
/** @param name the name of the uniform
* @return whether the uniform is available in the shader */
public boolean hasUniform(String name) {
return uniforms.containsKey(name);
}
/** @param name the name of the attribute
* @return whether the attribute is available in the shader */
public boolean hasAttribute(String name) {
return attributes.containsKey(name);
}
/***********************************************************************************************
* Set Uniforms and Attributes
***********************************************************************************************/
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value the value */
public void setUniformi(String name, int value) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform1i(location, value);
}
public void setUniformi(int location, int value) {
if(location == -1) return;
GLES20.glUniform1i(location, value);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value */
public void setUniformi (String name, int value1, int value2) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform2i(location, value1, value2);
}
public void setUniformi (int location, int value1, int value2) {
if(location == -1) return;
GLES20.glUniform2i(location, value1, value2);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value
* @param value3 the third value */
public void setUniformi (String name, int value1, int value2, int value3) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform3i(location, value1, value2, value3);
}
public void setUniformi (int location, int value1, int value2, int value3) {
if(location != -1)
GLES20.glUniform3i(location, value1, value2, value3);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value
* @param value3 the third value
* @param value4 the fourth value */
public void setUniformi (String name, int value1, int value2, int value3, int value4) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform4i(location, value1, value2, value3, value4);
}
public void setUniformi (int location, int value1, int value2, int value3, int value4) {
if(location == -1) return;
GLES20.glUniform4i(location, value1, value2, value3, value4);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value the value */
public void setUniformf (String name, float value) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform1f(location, value);
}
public void setUniformf (int location, float value) {
if(location == -1) return;
GLES20.glUniform1f(location, value);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value */
public void setUniformf (String name, float value1, float value2) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform2f(location, value1, value2);
}
public void setUniformf (int location, float value1, float value2) {
if(location == -1) return;
GLES20.glUniform2f(location, value1, value2);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value
* @param value3 the third value */
public void setUniformf (String name, float value1, float value2, float value3) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform3f(location, value1, value2, value3);
}
public void setUniformf (int location, float value1, float value2, float value3) {
if(location == -1) return;
GLES20.glUniform3f(location, value1, value2, value3);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param value1 the first value
* @param value2 the second value
* @param value3 the third value
* @param value4 the fourth value */
public void setUniformf (String name, float value1, float value2, float value3, float value4) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform4f(location, value1, value2, value3, value4);
}
public void setUniformf (int location, float value1, float value2, float value3, float value4) {
if(location == -1) return;
GLES20.glUniform4f(location, value1, value2, value3, value4);
}
public void setUniform1fv (String name, float[] values, int offset, int length) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform1fv(location, length, values, offset);
}
public void setUniform1fv (int location, float[] values, int offset, int length) {
if(location == -1) return;
GLES20.glUniform1fv(location, length, values, offset);
}
public void setUniform2fv (String name, float[] values, int offset, int length) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform2fv(location, length / 2, values, offset);
}
public void setUniform2fv (int location, float[] values, int offset, int length) {
if(location == -1) return;
GLES20.glUniform2fv(location, length / 2, values, offset);
}
public void setUniform3fv (String name, float[] values, int offset, int length) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform3fv(location, length / 3, values, offset);
}
public void setUniform3fv (int location, float[] values, int offset, int length) {
if(location == -1) return;
GLES20.glUniform3fv(location, length / 3, values, offset);
}
public void setUniform4fv (String name, float[] values, int offset, int length) {
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniform4fv(location, length / 4, values, offset);
}
public void setUniform4fv (int location, float[] values, int offset, int length) {
if(location == -1) return;
GLES20.glUniform4fv(location, length / 4, values, offset);
}
/** Sets the uniform matrix with the given name.
*
* @param name the name of the uniform
* @param matrix the matrix */
public void setUniformMatrix (String name, Matrix4f matrix) {
setUniformMatrix(name, matrix, false);
}
/** Sets the uniform matrix with the given name.
*
* @param name the name of the uniform
* @param matrix the matrix
* @param transpose whether the matrix should be transposed */
public void setUniformMatrix (String name, Matrix4f matrix, boolean transpose) {
setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
}
public void setUniformMatrix (int location, Matrix4f matrix) {
setUniformMatrix(location, matrix, false);
}
public void setUniformMatrix (int location, Matrix4f matrix, boolean transpose) {
if(location == -1) return;
GLES20.glUniformMatrix4fv(location, 1, transpose, matrix.getArray(), 0);
}
/** Sets the uniform matrix with the given name.
*
* @param name the name of the uniform
* @param matrix the matrix */
public void setUniformMatrix (String name, Matrix3f matrix) {
setUniformMatrix(name, matrix, false);
}
/** Sets the uniform matrix with the given name.
*
* @param name the name of the uniform
* @param matrix the matrix
* @param transpose whether the uniform matrix should be transposed */
public void setUniformMatrix (String name, Matrix3f matrix, boolean transpose) {
setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
}
public void setUniformMatrix (int location, Matrix3f matrix) {
setUniformMatrix(location, matrix, false);
}
public void setUniformMatrix (int location, Matrix3f matrix, boolean transpose) {
if(location == -1) return;
GLES20.glUniformMatrix3fv(location, 1, transpose, matrix.getArray(), 0);
}
/** Sets an array of uniform matrices with the given name.
*
* @param name the name of the uniform
* @param buffer buffer containing the matrix data
* @param transpose whether the uniform matrix should be transposed */
public void setUniformMatrix3fv (String name, FloatBuffer buffer, int count, boolean transpose) {
buffer.position(0);
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniformMatrix3fv(location, count, transpose, buffer);
}
/** Sets an array of uniform matrices with the given name.
*
* @param name the name of the uniform
* @param buffer buffer containing the matrix data
* @param transpose whether the uniform matrix should be transposed */
public void setUniformMatrix4fv (String name, FloatBuffer buffer, int count, boolean transpose) {
buffer.position(0);
int location = fetchUniformLocation(name);
if(location == -1) return;
GLES20.glUniformMatrix4fv(location, count, transpose, buffer);
}
public void setUniformMatrix4fv (int location, float[] values, int offset, int length) {
if(location == -1) return;
GLES20.glUniformMatrix4fv(location, length / 16, false, values, offset);
}
public void setUniformMatrix4fv (String name, float[] values, int offset, int length) {
setUniformMatrix4fv(fetchUniformLocation(name), values, offset, length);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param vector x and y as the first and second values respectively */
public void setUniformf (String name, Float2 vector) {
setUniformf(name, vector.x, vector.y);
}
public void setUniformf (int location, Float2 vector) {
setUniformf(location, vector.x, vector.y);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param vector x, y and z as the first, second and third values respectively */
public void setUniformf (String name, Float3 vector) {
setUniformf(name, vector.x, vector.y, vector.z);
}
public void setUniformf (int location, Float3 vector) {
setUniformf(location, vector.x, vector.y, vector.z);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param vector x, y, z and w as the first, second, third and forth values respectively */
public void setUniformf (String name, Float4 vector) {
setUniformf(name, vector.x, vector.y, vector.z, vector.w);
}
public void setUniformf (int location, Float4 vector) {
setUniformf(location, vector.x, vector.y, vector.z, vector.w);
}
/** Sets the uniform with the given name.
*
* @param name the name of the uniform
* @param color r, g, b and a as the first through fourth values respectively */
public void setUniformColor (String name, int color) {
setUniformf(name, Color.red(color) / 255.0f, Color.green(color) / 255.0f, Color.blue(color) / 255.0f, Color.alpha(color) / 255.0f);
}
public void setUniformf (int location, int color) {
setUniformf(location, Color.red(color) / 255.0f, Color.green(color) / 255.0f, Color.blue(color) / 255.0f, Color.alpha(color) / 255.0f);
}
/** Sets the vertex attribute with the given name.
*
* @param name the attribute name
* @param size the number of components, must be >= 1 and <= 4
* @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
* GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
* @param normalize whether fixed point data should be normalized. Will not work on the desktop
* @param stride the stride in bytes between successive attributes
* @param buffer the buffer containing the vertex attributes. */
public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, Buffer buffer) {
int location = fetchAttributeLocation(name);
if (location == -1) return;
GLES20.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
}
public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, Buffer buffer) {
if(location == -1) return;
GLES20.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
}
/** Sets the vertex attribute with the given name.
*
* @param name the attribute name
* @param size the number of components, must be >= 1 and <= 4
* @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
* GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
* @param normalize whether fixed point data should be normalized. Will not work on the desktop
* @param stride the stride in bytes between successive attributes
* @param offset byte offset into the vertex buffer object bound to GL20.GL_ARRAY_BUFFER. */
public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, int offset) {
int location = fetchAttributeLocation(name);
if (location == -1)
return;
GLES20.glVertexAttribPointer(location, size, type, normalize, stride, offset);
}
public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, int offset) {
if(location == -1) return;
GLES20.glVertexAttribPointer(location, size, type, normalize, stride, offset);
}
/** Disables the vertex attribute with the given name
*
* @param name the vertex attribute name */
public void disableVertexAttribute (String name) {
int location = fetchAttributeLocation(name);
if (location == -1) return;
GLES20.glDisableVertexAttribArray(location);
}
public void disableVertexAttribute (int location) {
if(location == -1) return;
GLES20.glDisableVertexAttribArray(location);
}
/** Enables the vertex attribute with the given name
*
* @param name the vertex attribute name */
public void enableVertexAttribute (String name) {
int location = fetchAttributeLocation(name);
if (location == -1) return;
GLES20.glEnableVertexAttribArray(location);
}
public void enableVertexAttribute (int location) {
if(location == -1) return;
GLES20.glEnableVertexAttribArray(location);
}
/** Sets the given attribute
*
* @param name the name of the attribute
* @param value1 the first value
* @param value2 the second value
* @param value3 the third value
* @param value4 the fourth value */
public void setAttributef (String name, float value1, float value2, float value3, float value4) {
int location = fetchAttributeLocation(name);
if(location == -1) return;
GLES20.glVertexAttrib4f(location, value1, value2, value3, value4);
}
public void setAttributef (String name, float value1, float value2, float value3) {
int location = fetchAttributeLocation(name);
if(location == -1) return;
GLES20.glVertexAttrib3f(location, value1, value2, value3);
}
public void setAttributef (String name, float value1, float value2) {
int location = fetchAttributeLocation(name);
if(location == -1) return;
GLES20.glVertexAttrib2f(location, value1, value2);
}
}
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
public class OGLView extends GLSurfaceView {
public OGLView(Context context) {
super(context);
init();
}
public OGLView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// use opengl es 2.0
setEGLContextClientVersion(2);
// store opengl context
setPreserveEGLContextOnPause(true);
// set renderer
setRenderer(new OGLRenderer(getContext()));
}
}
public class Square extends Model {
static final float squareCoords[] = {
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top left
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,// bottom left
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,// bottom right
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,// top right
};
static final short indices[] = {
0, 1, 2,
2, 3, 0
};
public Square(ShaderProgram shader) {
super("square", shader, squareCoords, indices);
}
}
Renderer
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.renderscript.Float3;
import android.renderscript.Matrix4f;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import kr.pe.burt.android.projectiontransformation.glkit.ShaderProgram;
import kr.pe.burt.android.projectiontransformation.glkit.ShaderUtils;
public class OGLRenderer implements GLSurfaceView.Renderer {
private static final float ONE_SEC = 1000.0f; // 1 second
private Context context;
private Square square;
private long lastTimeMillis = 0L;
public OGLRenderer(Context context) {
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
ShaderProgram shader = new ShaderProgram(
ShaderUtils.readShaderFileFromRawResource(context, R.raw.simple_vertex_shader),
ShaderUtils.readShaderFileFromRawResource(context, R.raw.simple_fragment_shader)
);
square = new Square(shader);
square.setPosition(new Float3(0.0f, 0.0f, 0.0f));
lastTimeMillis = System.currentTimeMillis();
}
@Override
public void onSurfaceChanged(GL10 gl10, int w, int h) {
GLES20.glViewport(0, 0, w, h);
if(square != null) {
Matrix4f perspective = new Matrix4f();
perspective.loadPerspective(85.0f, (float)w / (float)h, 1.0f, -150.0f);
square.setProjection(perspective);
}
}
@Override
public void onDrawFrame(GL10 gl10) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
long currentTimeMillis = System.currentTimeMillis();
updateWithDelta(currentTimeMillis - lastTimeMillis);
lastTimeMillis = currentTimeMillis;
}
public void updateWithDelta(long dt) {
final float secsPerMove = 2.0f * ONE_SEC;
float movement = (float)(Math.sin(System.currentTimeMillis() * 2 * Math.PI / secsPerMove));
// move camera
Matrix4f camera = new Matrix4f();
camera.translate(0.0f, -1.0f * movement, -15.0f);
camera.rotate(360.0f * movement, 0.0f, 0.0f, 1.0f);
camera.scale(movement, movement, movement);
square.setCamera(camera);
square.draw(dt);
}
}
Model
import android.opengl.GLES20;
import android.renderscript.Float3;
import android.renderscript.Matrix4f;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;
import kr.pe.burt.android.projectiontransformation.glkit.BufferUtils;
import kr.pe.burt.android.projectiontransformation.glkit.ShaderProgram;
/**
* Created by burt on 2016. 6. 22..
*/
public class Model {
private static final int COORDS_PER_VERTEX = 3;
private static final int COLORS_PER_VERTEX = 4;
private static final int SIZE_OF_FLOAT = 4;
private static final int SIZE_OF_SHORT = 2;
private ShaderProgram shader;
private String name;
private float vertices[];
private short indices[];
private FloatBuffer vertexBuffer;
private int vertexBufferId;
private int vertexStride;
private ShortBuffer indexBuffer;
private int indexBufferId;
// ModelView Transformation
protected Float3 position = new Float3(0f, 0f, 0f);
protected float rotationX = 0.0f;
protected float rotationY = 0.0f;
protected float rotationZ = 0.0f;
protected float scale = 1.0f;
protected Matrix4f camera = new Matrix4f();
protected Matrix4f projection = new Matrix4f();
public Model(String name, ShaderProgram shader, float[] vertices, short[] indices) {
this.name = name;
this.shader = shader;
this.vertices = Arrays.copyOfRange(vertices, 0, vertices.length);
this.indices = Arrays.copyOfRange(indices, 0, indices.length);
setupVertexBuffer();
setupIndexBuffer();
}
public void setPosition(Float3 position) {
this.position = position;
}
public void setRotationX(float rotationX) {
this.rotationX = rotationX;
}
public void setRotationY(float rotationY) {
this.rotationY = rotationY;
}
public void setRotationZ(float rotationZ) {
this.rotationZ = rotationZ;
}
public void setScale(float scale) {
this.scale = scale;
}
private void setupVertexBuffer() {
vertexBuffer = BufferUtils.newFloatBuffer(vertices.length);
vertexBuffer.put(vertices);
vertexBuffer.position(0);
IntBuffer buffer = IntBuffer.allocate(1);
GLES20.glGenBuffers(1, buffer);
vertexBufferId = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.length * SIZE_OF_FLOAT, vertexBuffer, GLES20.GL_STATIC_DRAW);
vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * SIZE_OF_FLOAT; // 4 bytes per vertex
}
private void setupIndexBuffer() {
// initialize index short buffer for index
indexBuffer = BufferUtils.newShortBuffer(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
IntBuffer buffer = IntBuffer.allocate(1);
GLES20.glGenBuffers(1, buffer);
indexBufferId = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length * SIZE_OF_SHORT, indexBuffer, GLES20.GL_STATIC_DRAW);
}
public Matrix4f modelMatrix() {
Matrix4f mat = new Matrix4f(); // make a new identitiy 4x4 matrix
mat.translate(position.x, position.y, position.z);
mat.rotate(rotationX, 1.0f, 0.0f, 0.0f);
mat.rotate(rotationY, 0.0f, 1.0f, 0.0f);
mat.rotate(rotationZ, 0.0f, 0.0f, 1.0f);
mat.scale(scale, scale, scale);
return mat;
}
public void setCamera(Matrix4f mat) {
camera.load(mat);
}
public void setProjection(Matrix4f mat) {
projection.load(mat);
}
public void draw(long dt) {
shader.begin();
camera.multiply(modelMatrix());
shader.setUniformMatrix("u_ProjectionMatrix", projection);
shader.setUniformMatrix("u_ModelViewMatrix", camera);
shader.enableVertexAttribute("a_Position");
shader.setVertexAttribute("a_Position", COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);
shader.enableVertexAttribute("a_Color");
shader.setVertexAttribute("a_Color", COLORS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, COORDS_PER_VERTEX * SIZE_OF_FLOAT);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, // mode
indices.length, // count
GLES20.GL_UNSIGNED_SHORT, // type
0); // offset
shader.disableVertexAttribute("a_Position");
shader.disableVertexAttribute("a_Color");
shader.end();
}
}
GLBitmap:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
/**
* 参考:
* http://blog.csdn.net/nupt123456789/article/details/40375731
* http://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
* Created by Administrator on 2016/9/23.
*/
public class GLBitmap {
//程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器。
private final int mProgram;
//顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码。
private final String vertexShaderCode =
// This matrix member variable (uMVPMatrix) provides a hook to manipulate the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 a_texCoord;" +//外部传入
"varying vec2 v_texCoord;" +//传到片段着色器中
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order for the matrix multiplication product to be correct.uMVPMatrix左乘才是对的
" gl_Position = uMVPMatrix * vPosition;" +
" v_texCoord = a_texCoord;" +
"}";
// Use to access and set the view transformation 顶点着色器中的mMVPMatrix
private int mMVPMatrixHandle;
private int mPositionHandle;
private int mTexCoordHandle;
//片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"void main() {" +
" gl_FragColor =texture2D( s_texture, v_texCoord );" +
"}";
private int mTexSamplerHandle;
private FloatBuffer vertexBuffer; // buffer holding the vertexes
private float vertexes[] = { // in counterclockwise order:
1.0f, 1.0f, 0.0f, // top right
-1.0f, 1.0f, 0.0f, // top left
-1.0f, -1.0f, 0.0f, // bottom left
1.0f, -1.0f, 0.0f // bottom right
};
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private ShortBuffer drawListBuffer;
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertexes
//指定截取纹理的哪一部分绘制到图形上:
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertexes
1.0f, 0.0f, // bottom right (V3)
0.0f, 0.0f, // bottom left (V1)
0.0f, 1.0f, // top left (V2)
1.0f, 1.0f // top right (V4)
};
public GLBitmap() {
// initialize vertexBuffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertexes.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertexes);
vertexBuffer.position(0);
//textureBuffer
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
/** The texture pointer */
private int[] textures = new int[1];
public void loadGLTexture(GL10 unused, Context context) {
// 我们需要先通过 glGenTextures 创建纹理,再通过 glActiveTexture 激活指定编号的纹理,再通过 glBindTexture 将新建的纹理和编号绑定起来。我们可以对图片纹理设置一系列参数,例如裁剪策略、缩放策略,这部分更详细的介绍,建议看看《OpenGL ES 2 for Android A Quick - Start Guide (2013)》这本书,里面有很详细的讲解。最后,我们通过 texImage2D 把图片数据拷贝到纹理中。
// loading texture
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.pic3);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// ...and bind it to our array
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// create GL_LINEAR filtered texture
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
public void draw(float[] mvpMatrix) {
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "s_texture");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride,vertexBuffer);
GLES20.glEnableVertexAttribArray(mTexCoordHandle);
GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0,textureBuffer);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniform1i(mTexSamplerHandle, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordHandle);
}
}
GLUnfoldBitmap
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
/**
* 参考:
* http://blog.csdn.net/nupt123456789/article/details/40375731
* http://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
* Created by Administrator on 2016/9/23.
*/
public class GLUnfoldBitmap {
//程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器。
private final int mProgram;
//顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码。
private final String vertexShaderCode =
// This matrix member variable (uMVPMatrix) provides a hook to manipulate the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 a_texCoord;" +//外部传入
"varying vec2 v_texCoord;" +//传到片段着色器中
"varying vec4 Position;" +//传到片段着色器中
"varying vec4 rotFai;"+
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order for the matrix multiplication product to be correct.uMVPMatrix左乘才是对的
// " gl_Position = vPosition;" +
" gl_Position = uMVPMatrix * vPosition ;" +
" v_texCoord = a_texCoord;" +
" Position = vPosition;" +
"}";
// Use to access and set the view transformation 顶点着色器中的mMVPMatrix
private int mMVPMatrixHandle;
private int mPositionHandle;
private int mTexCoordHandle;
private int mRotFaiHandle;
//片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
private final String fragmentShaderCode =
"precision mediump float;" +
// "precision mediump int;" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"varying vec4 Position;" +//从上方获取坐标
"varying vec4 rotFai;"+
"void main() {" +
"float PI= 3.14159265359;" +
// "int degree=210;" +
"float F0 = radians(210.0);" +
"float f = 0.5/2.0/sin(F0/4.0);" +//焦距
// "float f = 1.0;" +//焦距
// "float R = 2.0* f * sin(radians(90.0));" +
"float R = 1.0;" +
"float i = Position.x;" +
"float j = Position.y;" +
"float faiP = PI * i / R ;" +
"float citaP = PI * j / R ;" +
"float rotFai=-90.0;"+
"faiP -= radians(rotFai);"+
"float x1p=R*sin(citaP)*cos(faiP);" +
"float y1p=R*sin(citaP)*sin(faiP);" +
"float z1p = R * cos(citaP);" +
"float rotSita=90.0;" +
"float rotSitaRad=radians(rotSita);" +
"float x1pp=x1p;" +
"float y1pp=y1p*cos(rotSitaRad)-z1p*sin(rotSitaRad);" +
"float z1pp=y1p*sin(rotSitaRad)+z1p*cos(rotSitaRad);" +
"float rotGamma=0.0;"+
"float rotGammaRad=radians(rotGamma);" +
"float x1=z1pp*sin(rotGammaRad)+x1pp*cos(rotGammaRad);" +
"float y1=y1pp;" +
"float z1=z1pp*cos(rotGammaRad)-x1pp*sin(rotGammaRad);" +
"float cita=acos(z1/R);"+
"float fai=atan(y1,x1);"+
"float a;"+
"a=2.0*f*sin(cita/2.0);"+
"float xp=a*cos(fai);"+
"float yp=a*sin(fai);"+
"float x,y;"+
"x = xp+0.5;"+
"y = -yp+0.5;"+
"vec2 test;" +
"test=vec2(x,y);" +
" gl_FragColor =texture2D( s_texture, test );" +
// " gl_FragColor =texture2D( s_texture, v_texCoord );" +
"}";
private int mTexSamplerHandle;
private FloatBuffer vertexBuffer; // buffer holding the vertexes
private float vertexes[] = { // in counterclockwise order:
1.0f, 1.0f, 0.0f, // top right
-1.0f, 1.0f, 0.0f, // top left
-1.0f, -1.0f, 0.0f, // bottom left
1.0f, -1.0f, 0.0f // bottom right
};
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private ShortBuffer drawListBuffer;
private short drawOrder[] = {0, 1, 2, 0, 2, 3}; // order to draw vertexes
//指定截取纹理的哪一部分绘制到图形上:
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertexes
1.0f, 0.0f, // bottom right (V3)
0.0f, 0.0f, // bottom left (V1)
0.0f, 1.0f, // top left (V2)
1.0f, 1.0f // top right (V4)
};
public GLUnfoldBitmap() {
// initialize vertexBuffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertexes.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertexes);
vertexBuffer.position(0);
//textureBuffer
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
/**
* The texture pointer
*/
private int[] textures = new int[1];
public void loadGLTexture(GL10 unused, Context context) {
// 我们需要先通过 glGenTextures 创建纹理,再通过 glActiveTexture 激活指定编号的纹理,再通过 glBindTexture 将新建的纹理和编号绑定起来。我们可以对图片纹理设置一系列参数,例如裁剪策略、缩放策略,这部分更详细的介绍,建议看看《OpenGL ES 2 for Android A Quick - Start Guide (2013)》这本书,里面有很详细的讲解。最后,我们通过 texImage2D 把图片数据拷贝到纹理中。
// loading texture
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.pic1);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// ...and bind it to our array
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// create GL_LINEAR filtered texture
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
public void draw(float[] mvpMatrix) {
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "s_texture");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GLES20.glEnableVertexAttribArray(mTexCoordHandle);
GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniform1i(mTexSamplerHandle, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordHandle);
}
}