目前只有android系统中只有android 4.3或以上支持opengles 3.0,但目前很多运行android 4.3系统的硬件能支持opengles 3.0的也是非常少的。不过幸好,opengles 3.0是向后兼容的,当程序发现硬件不支持opengles 3.0时则会自动调用opengles 2.0的API。废话不多说了,开始进入正题,
实现过程:
1、在manifest中声明程序中使用opengles 3.0
如果程序中使用了纹理压缩的话,还需进行如下声明,以防止不支持这些压缩格式的设备尝试运行程序。
2、实现两个必不可少的类:GLSurfaceView和GLSurfaceView.Renderer
继承GLSurfaceView类的MySurfaceView.java
java代码
package com.gl.gl30_vbos02;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class MySurfaceView extends GLSurfaceView {
private final float TOUCH_SCALE_FACOTOR = 180.0f / 320;
private GLRender _render = new GLRender();
private float _preX = 0.0f;
private float _preY = 0.0f;
public MySurfaceView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
setEGLContextClientVersion(2);
this.setRenderer(_render);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
float dx = x - _preX;
float dy = y - _preY;
_render.zrot = dx * TOUCH_SCALE_FACOTOR;
_render.xrot = dy * TOUCH_SCALE_FACOTOR;
this.requestRender();
break;
default:
break;
}
_preX = x;
_preY = y;
return true;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
实现GLSurfaceView.Renderer的GLRender.java:
java代码
package com.gl.gl30_vbos02;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;
import android.util.Log;
//@TargetApi(18)
public class GLRender implements Renderer {
public float xrot, yrot, zrot;
private static final String TAG = "GLRender";
private final float[] mProjMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
// private volatile float mAngle;
private CirclePlane _circlePlane;
//定义环境光
private FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f, 0.5f,
0.5f, 1.0f});
//定义漫散射
private FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f, 1.0f,
1.0f, 1.0f});
//光源的位置
private FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,
0.0f, 2.0f, 1.0f});
public GLRender() {
// TODO Auto-generated constructor stub
}
@Override
public void onDrawFrame(GL10 gl_unused) {
// TODO Auto-generated method stub
//清楚屏幕和深度缓存
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT |
GLES30.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
this._circlePlane.Draw(mMVPMatrix);
}
@Override
public void onSurfaceChanged(GL10 gl_unused, int width, int height) {
// TODO Auto-generated method stub
float ratio = (float) width / height;
//设置OPENGL视口
GLES30.glViewport(0, 0, width, height);
//设置矩阵投影参数
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
//black background
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
this._circlePlane = new CirclePlane(10, 20, 1.0f);
}
public static int loadShader(int type, String shaderCode)
{
// create a shader type (GLES30.GL_VERTEX_SHADER)
// or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
int shader = GLES30.glCreateShader(type);
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
return shader;
}
public static void checkGLError(String glOperation)
{
int error;
while((error = GLES30.glGetError()) != (GLES30.GL_NO_ERROR))
{
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
要完成Opengl es工程,最重要是实现上面两个类。另外本程序为了绘制出图中的图案,还有四个类,可在附件中查看。:
CirclePlane.java //实现图案中顶点缓存,这个类有比较多的数学知识,不过只为了实现图案的话,不用理解其中数学算法问题也没关系。只要修改此类就可以绘制出不同的图案
Vertex3f.java //定义了顶点类型
Until.java //生成顶点缓存的公共工具类
OpenGLES30.java //工程的主类
附录
CirclePlane.java
java代码
package com.gl.gl30_vbos02;
import java.nio.FloatBuffer;
import android.opengl.GLES30;
//@TargetApi(18)
public class CirclePlane {
static final int COORDS_PRE_VERTEX = 3;
private final int vertexStride = COORDS_PRE_VERTEX * 4;
private int vertexCount = 0;
private int mRow = 10;
private int mColumn = 20;
private float mRadius = 1.0f;
private FloatBuffer mPlaneBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; //白色不透明
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main()" +
"{" +
" gl_Position = vPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main()" +
"{" +
" gl_FragColor = vColor;" +
"}";
public CirclePlane(int row, int column, float radius)
{
// TODO Auto-generated constructor stub
this.mRow = row;
this.mColumn = column;
this.mRadius = radius;
this.createGraphics();
int vertexShader = GLRender.loadShader(GLES30.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = GLRender.loadShader(GLES30.GL_FRAGMENT_SHADER,
fragmentShaderCode);
this.mProgram = GLES30.glCreateProgram(); // create empty OpenGL
Program
GLES30.glAttachShader(this.mProgram, vertexShader); // add the vertex
shader to program
GLES30.glAttachShader(this.mProgram, fragmentShader); // add the fragment
shader to program
GLES30.glLinkProgram(this.mProgram); // create OpenGL program
executables
}
private void createGraphics()
{
Vertex3f vertexs[][] = new Vertex3f[this.mRow][this.mColumn];
float intervalR = this.mRadius / this.mRow;
Vertex3f centralPos = new Vertex3f(0.0f, 0.0f, 0.0f);
for(int i=0;i
{
float tmpR = intervalR * i;
for(int j=0;j
{
double angle = 2 * j * Math.PI / (this.mColumn - 1);
vertexs[i][j] = new Vertex3f((float)(tmpR * Math.cos(angle)), (float)(tmpR
* Math.sin(angle)), centralPos.z);
}
}
//创建三角形顶点
int len = 2 * (this.mRow -1) * (this.mColumn - 1) * 3;
this.vertexCount = len;
Vertex3f tri[] = new Vertex3f[len];
int index = 0;
for(int i=0;i
{
for(int j=0;j
{
tri[index] = vertexs[i][j];
tri[index+1] = vertexs[i+1][j];
tri[index+2] = vertexs[i+1][j+1];
tri[index+3] = vertexs[i][j];
tri[index+4] = vertexs[i+1][j+1];
tri[index+5] = vertexs[i+1][j];
index += 6;
}
}
//设置顶点缓存
float[] plane = new float[len*3];
for(int i=0;i
{
int vertexI = 3 * i;
plane[vertexI] = tri[i].x;
plane[vertexI+1] = tri[i].y;
plane[vertexI+2] = tri[i].z;
}
this.mPlaneBuffer = Util.getFloatBuffer(plane);
// plane = null;
}
public void Draw(float[] mvpMatrix)
{
GLES30.glUseProgram(this.mProgram);
this.mPositionHandle = GLES30.glGetAttribLocation(this.mProgram,
"vPosition");
GLES30.glEnableVertexAttribArray(this.mPositionHandle);
GLES30.glVertexAttribPointer(this.mPositionHandle, COORDS_PRE_VERTEX,
GLES30.GL_FLOAT, false, this.vertexStride, this.mPlaneBuffer);
this.mColorHandle = GLES30.glGetUniformLocation(this.mProgram,
"vColor");
GLES30.glUniform4fv(this.mColorHandle, 1, this.color, 0);
this.mMVPMatrixHandle = GLES30.glGetUniformLocation(this.mProgram,
"uMVPMatrix");
GLRender.checkGLError("glGetUniformLocation");
GLES30.glUniformMatrix4fv(this.mMVPMatrixHandle, 1, false, mvpMatrix,
0);
GLRender.checkGLError("glUniformMatrix4fv");
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, this.vertexCount);
GLES30.glDisableVertexAttribArray(this.mPositionHandle);
// gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// gl.glVertexPointer(3, GL10.GL_FLOAT, 0, this.mPlaneBuffer);
// gl.glDrawArrays(GL10.GL_TRIANGLES, 0,
(this.mRow-1)*(this.mColumn-1)*2*3);
//
// gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// gl.glFinish();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
Vertex3f.java
java代码
package com.gl.gl30_vbos02;
public class Vertex3f {
public float x = 0.0f;
public float y = 0.0f;
public float z = 0.0f;
public Vertex3f(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
Until.java
java代码
package com.gl.gl30_vbos02;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class Util {
//获取整形缓冲数据
public static IntBuffer getIntBuffer(int[] vertexs)
{
IntBuffer buffer;
ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4);
qbb.order(ByteOrder.nativeOrder());
buffer = qbb.asIntBuffer();
buffer.put(vertexs);
buffer.position(0);
return buffer;
}
//获取浮点形缓冲数据
public static FloatBuffer getFloatBuffer(float[] vertexs)
{
FloatBuffer buffer;
ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4);
qbb.order(ByteOrder.nativeOrder());
buffer = qbb.asFloatBuffer();
buffer.put(vertexs);
buffer.position(0);
return buffer;
}
//获取字节型缓冲数据
public static ByteBuffer getByteBuffer(byte[] vertexs)
{
ByteBuffer buffer = null;
buffer = ByteBuffer.allocateDirect(vertexs.length);
buffer.put(vertexs);
buffer.position(0);
return buffer;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
OpenGLES30.java
java代码
package com.gl.gl30_vbos02;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class OpenGLES30 extends Activity {
private GLSurfaceView mGL30View;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGL30View = new MySurfaceView(this);
setContentView(mGL30View);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.open_gles30, menu);
return true;
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
this.mGL30View.onResume();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
this.mGL30View.onPause();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
原文:http://bbs.9ria.com/thread-260180-1-1.html