Axis.java
package com.Diamond.gl02;
import android.opengl.GLES32;
import java.nio.FloatBuffer;
import com.Diamond.gl02.Program;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import android.renderscript.Float4;
import android.opengl.Matrix;
import android.renderscript.Matrix4f;
public class Axis {
public FloatBuffer vfb;
public GLES32 gl;
public Matrix4f model;
public Axis() {
float[] ver = new float[]{
-100,0,0,
100,0,0,
0,-100,0,
0,100,0,
0,0,-100,
0,0,100
};
ByteBuffer vbb = ByteBuffer.allocateDirect(ver.length * 4);
vbb.order(ByteOrder.nativeOrder());
vfb = vbb.asFloatBuffer();
vfb.put(ver);
vfb.position(0);
model = new Matrix4f();
model.loadIdentity();
}
public void draw(Program program) {
program.setUniform("u_model",model.getArray());
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0,3,gl.GL_FLOAT,false,0,vfb);
program.setUniform("u_color",1,0,0,1);
gl.glDrawArrays(gl.GL_LINES,0,2);
program.setUniform("u_color",0,1,0,1);
gl.glDrawArrays(gl.GL_LINES,2,2);
program.setUniform("u_color",0,0,1,1);
gl.glDrawArrays(gl.GL_LINES,4,2);
}
}
Camera.java
package com.Diamond.gl02;
import android.opengl.Matrix;
import android.renderscript.Matrix4f;
import android.renderscript.Float3;
public class Camera {
private Float3 mPosition;
private Float3 mCenter;
private Float3 mUp;
private Matrix4f mProjection;
public Camera(Float3 position,Float3 center,Float3 up) {
mPosition = position;
mCenter = center;
mUp = up;
mProjection = new Matrix4f();
}
public Camera setPosition(Float3 position) {
mPosition = position;
return this;
}
public Camera move(Float3 distance) {
mPosition.x += distance.x;
mPosition.y += distance.y;
mPosition.z += distance.z;
return this;
}
public Camera moveX(float distance) {
mPosition.x += distance;
return this;
}
public Camera moveY(float distance) {
mPosition.y += distance;
return this;
}
public Camera moveZ(float distance) {
mPosition.z += distance;
return this;
}
public Camera setCenter(Float3 center) {
mCenter = center;
return this;
}
public Camera setUp(Float3 up) {
mUp = up;
return this;
}
public Camera setPerspective(float fovy,float aspect,float near,float far) {
mProjection.loadPerspective(fovy,aspect,near,far);
return this;
}
public Camera setOrtho(float l,float r,float b,float t,float n,float f) {
mProjection.loadOrtho(l,r,b,t,n,f);
return this;
}
public float[] getProjectionMatrix() {
return mProjection.getArray();
}
public float[] getViewMatrix() {
float[] view = new float[16];
Matrix.setLookAtM(
view,0,
mPosition.x,mPosition.y,mPosition.z,
mCenter.x,mCenter.y,mCenter.z,
mUp.x,mUp.y,mUp.z
);
return view;
}
}
MainActivity.java
package com.Diamond.gl02;
import android.app.Activity;
import android.os.Bundle;
import com.Diamond.gl02.MySurfaceView;
import android.widget.RelativeLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.renderscript.Float3;
import android.view.View;
import android.view.MotionEvent;
import android.util.Log;
import android.content.pm.ActivityInfo;
import android.view.WindowManager;
import android.view.Window;
public class MainActivity extends Activity {
public MySurfaceView surfaceView;
public RelativeLayout relativeLayout1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
relativeLayout1 = (RelativeLayout)findViewById(R.id.activitymainRelativeLayout1);
surfaceView = new MySurfaceView(this);
surfaceView.requestFocus();
surfaceView.setFocusableInTouchMode(true);
surfaceView.setClickable(true);
relativeLayout1.addView(surfaceView);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
protected void onResume() {
super.onResume();
surfaceView.onResume();
}
@Override
protected void onPause() {
super.onPause();
surfaceView.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "前进");
menu.add(0, 1, 0, "后退");
menu.add(0, 2, 0, "左移");
menu.add(0, 3, 0, "右移");
menu.add(0, 4, 0, "向上");
menu.add(0, 5, 0, "向下");
menu.add(0, 6, 0, "更新三角形");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
surfaceView.renderer.camera.moveX(0.5f);
break;
case 1:
surfaceView.renderer.camera.moveX(-0.5f);
break;
case 2:
surfaceView.renderer.camera.moveZ(0.5f);
break;
case 3:
surfaceView.renderer.camera.moveZ(-0.5f);
break;
case 4:
surfaceView.renderer.camera.moveY(0.5f);
break;
case 5:
surfaceView.renderer.camera.moveY(-0.5f);
break;
case 6:
surfaceView.renderer.initTriangles();
break;
}
return super.onOptionsItemSelected(item);
}
}
MySurfaceView.java
package com.Diamond.gl02;
import android.opengl.*;
import android.opengl.GLES32;
import android.opengl.GLSurfaceView;
import android.content.Context;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;
import com.Diamond.gl02.Triangle;
import android.renderscript.Float3;
import android.content.res.Resources;
import com.Diamond.gl02.Camera;
import android.renderscript.Float4;
import android.view.MotionEvent;
import android.util.Log;
import com.Diamond.gl02.Axis;
public class MySurfaceView extends GLSurfaceView {
public class MyRenderer implements GLSurfaceView.Renderer {
public Triangle[] triangles;
public Resources resources;
public GLES32 gl;
public Camera camera;
public Program program;
public float lastX,lastY,x,y;
public double yaw;
public Axis axis;
public MyRenderer() {
x = 0;
y = 0;
yaw = 0;
}
@Override
public void onSurfaceCreated(GL10 p1, EGLConfig p2) {
String vString = Program.loadFromAssetsFile("v.vert", getResources());
String fString = Program.loadFromAssetsFile("f.frag", getResources());
program = new Program(vString, fString);
camera = new Camera(new Float3(1.0f, 1.0f, 1.0f), new Float3(0, 0, 0), new Float3(0, 1, 0));
camera.setPerspective(120.0f, 2.0f, 0.1f, 100.0f);
axis = new Axis();
gl.glEnable(gl.GL_DEPTH_TEST);
initTriangles();
}
public void initTriangles() {
triangles = new Triangle[1000];
for(int i = 0;i < triangles.length;i++) {
float x = (float)Math.random() * 10 - 5;
float y = (float)Math.random() * 10 - 5;
float z = (float)Math.random() * 10 - 5;
float r = (float)Math.random();
float g = (float)Math.random();
float b = (float)Math.random();
float rx = (float)Math.random() * 360;
float ry = (float)Math.random() * 360;
float rz = (float)Math.random() * 360;
Triangle t = new Triangle(new Float4(r,g,b,1));
t.model.translate(x,y,z);
t.model.scale(0.5f,0.5f,0.5f);
t.model.rotate(rx,1,0,0);
t.model.rotate(ry,0,1,0);
t.model.rotate(rz,0,0,1);
triangles[i] = t;
}
}
@Override
public void onSurfaceChanged(GL10 p1, int p2, int p3) {
}
@Override
public void onDrawframe(GL10 p1) {
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
program.useProgram();
program.setUniform("u_projection",camera.getProjectionMatrix());
program.setUniform("u_view",camera.getViewMatrix());
axis.draw(program);
for(Triangle i : triangles) {
i.draw(program);
}
}
}
public MyRenderer renderer;
public MySurfaceView(Context context) {
super(context);
this.setEGLContextClientVersion(3);
renderer = new MyRenderer();
this.setRenderer(renderer);
this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
}
Program.java
package com.Diamond.gl02;
import android.opengl.GLES32;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import android.renderscript.Float2;
import android.renderscript.Float3;
import android.renderscript.Float4;
import java.io.InputStream;
import android.content.res.Resources;
import java.io.ByteArrayOutputStream;
public class Program {
public class Shader {
private int program;
private int type;
public final String tag = "failed to load shader";
private void loadShader(String resource) {
program = GLES32.glCreateShader(type);
if (program == 0) {
Log.e(tag, "shader program type:" + type);
Log.e(tag, "error:" + GLES32.glGetError());
return;
}
GLES32.glShaderSource(program, resource);
GLES32.glCompileShader(program);
int[] compiled = new int[1];
GLES32.glGetShaderiv(program, GLES32.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.e(tag, GLES32.glGetShaderInfoLog(program));
GLES32.glDeleteShader(program);
program = 0;
}
}
public Shader(int programType) {
program = 0;
type = programType;
}
public Shader(int programType, String resource) {
type = programType;
loadShader(resource);
}
public int getProgram() {
return program;
}
}
private Shader vShader;
private Shader fShader;
private Shader gShader;
private int program;
private final String tag = "failed to create program";
private void linkProgram() {
int vp = vShader.getProgram();
int fp = fShader.getProgram();
int gp = gShader.getProgram();
program = GLES32.glCreateProgram();
if (program == 0) {
Log.e(tag, "" + GLES32.glGetError());
return;
}
GLES32.glAttachShader(program, vp);
GLES32.glAttachShader(program, fp);
if (gp != 0) {
GLES32.glAttachShader(program, gp);
}
GLES32.gllinkProgram(program);
int[] linkStatus = new int[1];
GLES32.glGetProgramiv(program, GLES32.GL_link_STATUS, linkStatus, 0);
if (linkStatus[0] == GLES32.GL_FALSE) {
Log.e(tag, GLES32.glGetProgramInfoLog(program));
GLES32.glDeleteProgram(program);
program = 0;
}
}
public Program() {
vShader = new Shader(GLES32.GL_VERTEX_SHADER);
fShader = new Shader(GLES32.GL_FRAGMENT_SHADER);
gShader = new Shader(GLES32.GL_GEOMETRY_SHADER);
linkProgram();
}
public Program(String vResource, String fResource) {
vShader = new Shader(GLES32.GL_VERTEX_SHADER, vResource);
fShader = new Shader(GLES32.GL_FRAGMENT_SHADER, fResource);
gShader = new Shader(GLES32.GL_GEOMETRY_SHADER);
linkProgram();
}
public Program(String vResource, String fResource, String gResource) {
vShader = new Shader(GLES32.GL_VERTEX_SHADER, vResource);
fShader = new Shader(GLES32.GL_FRAGMENT_SHADER, fResource);
gShader = new Shader(GLES32.GL_GEOMETRY_SHADER, gResource);
linkProgram();
}
public int getProgram() {
return program;
}
public void useProgram() {
GLES32.glUseProgram(program);
}
public static String loadFromAssetsFile(String fname, Resources resources) {
String result=null;
try {
InputStream in=resources.getAssets().open(fname);
int ch=0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((ch = in.read()) != -1) {
baos.write(ch);
}
byte[] buff=baos.toByteArray();
baos.close();
in.close();
result = new String(buff, "UTF-8");
result = result.replaceAll("\r\n", "n");
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public int getUniformLocation(String name) {
return GLES32.glGetUniformLocation(program, name);
}
public void setUniform(String name, float value) {
int location = getUniformLocation(name);
GLES32.glUniform1f(location, value);
}
public void setUniform(String name, int value) {
int location = getUniformLocation(name);
GLES32.glUniform1i(location, value);
}
public void setUniform(String name, float value1, float value2) {
int location = getUniformLocation(name);
GLES32.glUniform2f(location, value1, value2);
}
public void setUniform(String name, Float2 value) {
setUniform(name, value.x, value.y);
}
public void setUniform(String name, float value1, float value2, float value3) {
int location = getUniformLocation(name);
GLES32.glUniform3f(location, value1, value2, value3);
}
public void setUniform(String name, Float3 value) {
setUniform(name, value.x, value.y, value.z);
}
public void setUniform(String name, float value1, float value2, float value3, float value4) {
int location = getUniformLocation(name);
GLES32.glUniform4f(location, value1, value2, value3, value4);
}
public void setUniform(String name, Float4 value) {
setUniform(name, value.x, value.y, value.z, value.w);
}
public void setUniform(String name, float[] matrix) {
int location = getUniformLocation(name);
GLES32.glUniformMatrix4fv(location, 1, false, matrix, 0);
}
}
Triangle.java
package com.Diamond.gl02;
import com.Diamond.gl02.Program;
import android.opengl.GLES32;
import android.content.res.Resources;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.Diamond.gl02.Camera;
import android.renderscript.Matrix4f;
import android.renderscript.Float3;
import android.renderscript.Float4;
public class Triangle{
public FloatBuffer vfb;
public GLES32 gl;
public Matrix4f model;
public Float4 color;
public Triangle(Float4 c) {
color = c;
float[] ver = new float[]{
0.0f,0.5f,0.0f,
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f
};
ByteBuffer vbb = ByteBuffer.allocateDirect(ver.length * 4);
vbb.order(ByteOrder.nativeOrder());
vfb = vbb.asFloatBuffer();
vfb.put(ver);
vfb.position(0);
model = new Matrix4f();
}
public void draw(Program program) {
program.setUniform("u_model",model.getArray());
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0,3,gl.GL_FLOAT,false,3 * 4,vfb);
program.setUniform("u_color",color);
gl.glDrawArrays(gl.GL_TRIANGLES,0,3);
}
}
v.vert
#version 320 es
layout(location=0)in vec3 a_position;
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position,1.0f);
}
f.frag
效果#version 320 es
precision mediump float;
uniform vec4 u_color;
out vec4 o_color;
void main()
{
o_color = u_color;
}
如果没有问题,最后的结果应该如图所示


![[java] [OpenGL ES 3.2] 一群三角形 [java] [OpenGL ES 3.2] 一群三角形](http://www.mshxw.com/aiimages/31/707304.png)
