android gles,Android OpenGLes 3.0学习:顶点绘制法 VBOs

目前只有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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值