212 lines
7.2 KiB
Java

package com.homelinux.holtrop.opengltest;
import android.opengl.GLSurfaceView;
import android.opengl.GLES20;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ByteOrder;
import android.util.Log;
import android.content.res.AssetManager;
import android.content.res.Resources;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.opengl.GLUtils;
public class MyRenderer implements GLSurfaceView.Renderer
{
private int m_program;
private final String DBGTAG = "JoshsOpenGL";
private FloatBuffer m_quad_attrib_buffer;
private AssetManager m_asset_manager;
private Resources m_resources;
private float m_proj_matrix[] = new float[16];
private float m_modelview[] = new float[16];
private int m_width;
private int m_height;
private float m_aspect = 1.0f;
private float m_x = 0.0f;
private float m_y = 0.0f;
public MyRenderer(AssetManager am, Resources resources)
{
m_asset_manager = am;
m_resources = resources;
}
public void checkGLError(String glOperation)
{
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
{
Log.e(DBGTAG, glOperation + ": glError " + error);
}
}
private String read_asset(String fname)
{
String result = "";
try
{
InputStream is = m_asset_manager.open(fname);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null)
{
result += line + "\n";
}
}
catch (IOException ioe)
{
}
return result;
}
private int load_shader(int type, String source)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
IntBuffer ib = IntBuffer.allocate(1);
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, ib);
if (ib.get(0) != 1)
{
String info_log = GLES20.glGetShaderInfoLog(shader);
Log.e(DBGTAG, "Error compiling shader: " + info_log);
}
return shader;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config)
{
final float attribs[] = {
1, 1, 0, 1, 1,
-1, 1, 0, 0, 1,
-1, -1, 0, 0, 0,
1, -1, 0, 1, 0,
};
checkGLError("onSurfaceCreated");
ByteBuffer bb = ByteBuffer.allocateDirect(attribs.length * 4);
bb.order(ByteOrder.nativeOrder());
m_quad_attrib_buffer = bb.asFloatBuffer();
m_quad_attrib_buffer.put(attribs);
m_quad_attrib_buffer.position(0);
final String v_shader_src = read_asset("shaders/vertex.glsl");
final String f_shader_src = read_asset("shaders/fragment.glsl");
int v_shader = load_shader(GLES20.GL_VERTEX_SHADER, v_shader_src);
int f_shader = load_shader(GLES20.GL_FRAGMENT_SHADER, f_shader_src);
m_program = GLES20.glCreateProgram();
GLES20.glAttachShader(m_program, v_shader);
GLES20.glAttachShader(m_program, f_shader);
GLES20.glLinkProgram(m_program);
checkGLError("glLinkProgram");
IntBuffer ib = IntBuffer.allocate(1);
GLES20.glGetProgramiv(m_program, GLES20.GL_LINK_STATUS, ib);
if (ib.get(0) != 1)
{
String info_log = GLES20.glGetProgramInfoLog(m_program);
Log.e(DBGTAG, "Program log: " + info_log);
}
Bitmap texture = BitmapFactory.decodeResource(m_resources,
R.drawable.texture);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
checkGLError("glGenTextures");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
checkGLError("glBindTexture");
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
checkGLError("glTexParameterf");
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, texture, 0);
checkGLError("GLUtils.texImage2D");
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
checkGLError("glGenerateMipmap");
texture.recycle();
GLES20.glClearColor(1.0f, 0.6f, 0.1f, 1.0f);
}
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
Matrix.setIdentityM(m_modelview, 0);
Matrix.translateM(m_modelview, 0, m_x, m_y, 0);
Matrix.rotateM(m_modelview, 0, angle, 0, 0, 1);
Matrix.scaleM(m_modelview, 0, 0.2f, 0.2f, 0.2f);
GLES20.glUniformMatrix4fv(
GLES20.glGetUniformLocation(m_program, "modelview"),
1, false, m_modelview, 0);
int attr_pos = GLES20.glGetAttribLocation(m_program, "pos");
int attr_tex_coord = GLES20.glGetAttribLocation(m_program, "tex_coord");
checkGLError("glGetAttribLocation");
GLES20.glEnableVertexAttribArray(attr_pos);
GLES20.glEnableVertexAttribArray(attr_tex_coord);
checkGLError("glEnableVertexAttribArray");
m_quad_attrib_buffer.position(0);
GLES20.glVertexAttribPointer(attr_pos, 3, GLES20.GL_FLOAT, false,
5 * 4, m_quad_attrib_buffer);
m_quad_attrib_buffer.position(3);
GLES20.glVertexAttribPointer(attr_tex_coord, 2, GLES20.GL_FLOAT, false,
5 * 4, m_quad_attrib_buffer);
checkGLError("glVertexAttribPointer");
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
checkGLError("glDrawArrays");
GLES20.glDisableVertexAttribArray(attr_pos);
GLES20.glDisableVertexAttribArray(attr_tex_coord);
checkGLError("glDisableVertexAttribArray");
}
public void onSurfaceChanged(GL10 unused, int width, int height)
{
m_width = width;
m_height = height;
m_aspect = width / (float) height;
GLES20.glViewport(0, 0, width, height);
Matrix.orthoM(m_proj_matrix, 0,
-m_aspect, m_aspect,
-1, 1, 1, -1);
GLES20.glUseProgram(m_program);
GLES20.glUniformMatrix4fv(
GLES20.glGetUniformLocation(m_program, "projection"),
1, false, m_proj_matrix, 0);
}
public boolean onTouchEvent(MotionEvent e)
{
if (e.getAction() == MotionEvent.ACTION_DOWN)
{
float x = m_aspect * ((e.getX() / (float) m_width) * 2.0f - 1.0f);
float y = -((e.getY() / (float) m_height) * 2.0f - 1.0f);
m_x = x;
m_y = y;
}
return false;
}
}