目前只有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代码
packagecom.gl.gl30_vbos02;
importandroid.content.Context;
importandroid.opengl.GLSurfaceView;
importandroid.util.AttributeSet;
importandroid.view.MotionEvent;
publicclassMySurfaceViewextendsGLSurfaceView {
privatefinalfloatTOUCH_SCALE_FACOTOR =180.0f /320;
privateGLRender _render =newGLRender();
privatefloat_preX =0.0f;
privatefloat_preY =0.0f;
publicMySurfaceView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
setEGLContextClientVersion(2);
this.setRenderer(_render);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
publicMySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
publicbooleanonTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
floatx = event.getX();
floaty = event.getY();
switch(event.getAction())
{
caseMotionEvent.ACTION_MOVE:
floatdx = x - _preX;
floatdy = y - _preY;
_render.zrot = dx * TOUCH_SCALE_FACOTOR;
_render.xrot = dy * TOUCH_SCALE_FACOTOR;
this.requestRender();
break;
default:
break;
}
_preX = x;
_preY = y;
returntrue;
}
}
实现GLSurfaceView.Renderer的GLRender.java:
java代码
packagecom.gl.gl30_vbos02;
importjava.nio.FloatBuffer;
importjavax.microedition.khronos.egl.EGLConfig;
importjavax.microedition.khronos.opengles.GL10;
importandroid.opengl.GLES30;
importandroid.opengl.GLSurfaceView.Renderer;
importandroid.opengl.Matrix;
importandroid.util.Log;
//@TargetApi(18)
publicclassGLRenderimplementsRenderer {
publicfloatxrot, yrot, zrot;
privatestaticfinalString TAG ="GLRender";
privatefinalfloat[] mProjMatrix =newfloat[16];
privatefinalfloat[] mVMatrix =newfloat[16];
privatefinalfloat[] mMVPMatrix =newfloat[16];
privatefinalfloat[] mRotationMatrix =newfloat[16];
// private volatile float mAngle;
privateCirclePlane _circlePlane;
//定义环境光
privateFloatBuffer lightAmbient = FloatBuffer.wrap(newfloat[]{0.5f,0.5f,
0.5f,1.0f});
//定义漫散射
privateFloatBuffer lightDiffuse = FloatBuffer.wrap(newfloat[]{1.0f,1.0f,
1.0f,1.0f});
//光源的位置
privateFloatBuffer lightPosition = FloatBuffer.wrap(newfloat[]{0.0f,
0.0f,2.0f,1.0f});
publicGLRender() {
// TODO Auto-generated constructor stub
}
@Override
publicvoidonDrawFrame(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
publicvoidonSurfaceChanged(GL10 gl_unused,intwidth,intheight) {
// TODO Auto-generated method stub
floatratio = (float) width / height;
//设置OPENGL视口
GLES30.glViewport(0,0, width, height);
//设置矩阵投影参数
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1,1,3,7);
}
@Override
publicvoidonSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
//black background
GLES30.glClearColor(0.0f,0.0f,0.0f,0.0f);
this._circlePlane =newCirclePlane(10,20,1.0f);
}
publicstaticintloadShader(inttype, String shaderCode)
{
// create a shader type (GLES30.GL_VERTEX_SHADER)
// or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
intshader = GLES30.glCreateShader(type);
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
returnshader;
}
publicstaticvoidcheckGLError(String glOperation)
{
interror;
while((error = GLES30.glGetError()) != (GLES30.GL_NO_ERROR))
{
Log.e(TAG, glOperation + ": glError "+ error);
thrownewRuntimeException(glOperation +": glError "+ error);
}
}
}
要完成Opengl es工程,最重要是实现上面两个类。另外本程序为了绘制出图中的图案,还有四个类,可在附件中查看。:
CirclePlane.java //实现图案中顶点缓存,这个类有比较多的数学知识,不过只为了实现图案的话,不用理解其中数学算法问题也没关系。只要修改此类就可以绘制出不同的图案
Vertex3f.java //定义了顶点类型
Until.java //生成顶点缓存的公共工具类
OpenGLES30.java //工程的主类
附录
CirclePlane.java
java代码
packagecom.gl.gl30_vbos02;
importjava.nio.FloatBuffer;
importandroid.opengl.GLES30;
//@TargetApi(18)
publicclassCirclePlane {
staticfinalintCOORDS_PRE_VERTEX =3;
privatefinalintvertexStride = COORDS_PRE_VERTEX *4;
privateintvertexCount =0;
privateintmRow =10;
privateintmColumn =20;
privatefloatmRadius =1.0f;
privateFloatBuffer mPlaneBuffer;
privatefinalintmProgram;
privateintmPositionHandle;
privateintmColorHandle;
privateintmMVPMatrixHandle;
// Set color with red, green, blue and alpha (opacity) values
floatcolor[] = {1.0f,1.0f,1.0f,1.0f };//白色不透明
privatefinalString vertexShaderCode =
"uniform mat4 uMVPMatrix;"+
"attribute vec4 vPosition;"+
"void main()"+
"{"+
" gl_Position = vPosition * uMVPMatrix;"+
"}";
privatefinalString fragmentShaderCode =
"precision mediump float;"+
"uniform vec4 vColor;"+
"void main()"+
"{"+
" gl_FragColor = vColor;"+
"}";
publicCirclePlane(introw,intcolumn,floatradius)
{
// TODO Auto-generated constructor stub
this.mRow = row;
this.mColumn = column;
this.mRadius = radius;
this.createGraphics();
intvertexShader = GLRender.loadShader(GLES30.GL_VERTEX_SHADER,
vertexShaderCode);
intfragmentShader = 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
}
privatevoidcreateGraphics()
{
Vertex3f vertexs[][] = newVertex3f[this.mRow][this.mColumn];
floatintervalR =this.mRadius /this.mRow;
Vertex3f centralPos = newVertex3f(0.0f,0.0f,0.0f);
for(inti=0;i
{
floattmpR = intervalR * i;
for(intj=0;j
{
doubleangle =2* j * Math.PI / (this.mColumn -1);
vertexs[i][j] = newVertex3f((float)(tmpR * Math.cos(angle)), (float)(tmpR
* Math.sin(angle)), centralPos.z);
}
}
//创建三角形顶点
intlen =2* (this.mRow -1) * (this.mColumn -1) *3;
this.vertexCount = len;
Vertex3f tri[] = newVertex3f[len];
intindex =0;
for(inti=0;i
{
for(intj=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 =newfloat[len*3];
for(inti=0;i
{
intvertexI =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;
}
publicvoidDraw(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();
}
}
Vertex3f.java
java代码
packagecom.gl.gl30_vbos02;
publicclassVertex3f {
publicfloatx =0.0f;
publicfloaty =0.0f;
publicfloatz =0.0f;
publicVertex3f(floatx,floaty,floatz)
{
this.x = x;
this.y = y;
this.z = z;
}
}
Until.java
java代码
packagecom.gl.gl30_vbos02;
importjava.nio.ByteBuffer;
importjava.nio.ByteOrder;
importjava.nio.FloatBuffer;
importjava.nio.IntBuffer;
publicclassUtil {
//获取整形缓冲数据
publicstaticIntBuffer 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);
returnbuffer;
}
//获取浮点形缓冲数据
publicstaticFloatBuffer 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);
returnbuffer;
}
//获取字节型缓冲数据
publicstaticByteBuffer getByteBuffer(byte[] vertexs)
{
ByteBuffer buffer = null;
buffer = ByteBuffer.allocateDirect(vertexs.length);
buffer.put(vertexs);
buffer.position(0);
returnbuffer;
}
}
OpenGLES30.java
java代码
packagecom.gl.gl30_vbos02;
importandroid.opengl.GLSurfaceView;
importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.view.Menu;
publicclassOpenGLES30extendsActivity {
privateGLSurfaceView mGL30View;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGL30View = newMySurfaceView(this);
setContentView(mGL30View);
}
@Override
publicbooleanonCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.open_gles30, menu);
returntrue;
}
@Override
protectedvoidonResume() {
// TODO Auto-generated method stub
super.onResume();
this.mGL30View.onResume();
}
@Override
protectedvoidonPause() {
// TODO Auto-generated method stub
super.onPause();
this.mGL30View.onPause();
}
}
原文:http://bbs.9ria.com/thread-260180-1-1.html
【编辑推荐】
【责任编辑:闫佳明 TEL:(010)68476606】
点赞 0