Android OpenGL ES零基础系列(一):理解GLSurfaceView,GLSurfaceView.Render的基本用法
2016-07-12 19:17
1226 查看
转载请注明出处
因此OpenGL ES作为第三方库被应用在android中。
到目前为止,OpenGL ES已经发展有了3个版本,OpenGL ES 1.0 , OpenGL ES 2.0 , OpenGL ES 3.0。其中OpenGL ES 1.0 是以OpenGL 1.3规范为基础,OpenGL ES 2.0 是以OpenGL 2.0 为基础,OpenGL ES 3.0是移动设备专用,以OpenGL 4.3为标准。
本文我们选用后一种,eg:
onSurfaceCreated(GL10 glUnused,EGLConfig config);
onSurfaceChanged(GL10 glUnused,int width,int height);
onDrawFrame(GL10 glUnused);
以上三个方法回调的时机分别如下:
onSurfaceCreated:当GLSurfaceView 实例生成时回调;
onSurfaceChanged:当手机横/竖屏切换时回调;
onDrawFrame:是由系统自动回调的,它会以一定的帧频率来调用重绘View。
当设置GLSurfaceView的渲染模式o为GLSurfaceView.RENDERMODE_CONTINUOUSLY或不设置时,系统就会主动渲染,就会回调onDrawFrame()方法
SunnyGLRender类如下:
运行程序 就可以看到三角形了。
下一节
Android OpenGL ES 应用(二) 纹理
浅学OpenGLES2.0
google ApiDemo(这个自己看官方Demo就好了,就没有贴出下载地址了)
前言
OpenGL ES是OpenGL的一个子集,是针对手机、PDA和游戏主机等嵌入式设备而设计的。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。因此OpenGL ES作为第三方库被应用在android中。
到目前为止,OpenGL ES已经发展有了3个版本,OpenGL ES 1.0 , OpenGL ES 2.0 , OpenGL ES 3.0。其中OpenGL ES 1.0 是以OpenGL 1.3规范为基础,OpenGL ES 2.0 是以OpenGL 2.0 为基础,OpenGL ES 3.0是移动设备专用,以OpenGL 4.3为标准。
正文:利用OpenGL ES 2.0创建简单的三角图形
第一步:创建GLSurfaceView对象
生成GLSurfaceView的方法有2种,可以直接在xml中写,也可以在代码中new。本文我们选用后一种,eg:
public class SunnyOpenGLActivity extends FragmentActivity { private GLSurfaceView mGLSurfaceView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } private void initView() { mGLSurfaceView = new GLSurfaceView(this); }
第二步:自定义Render类实现GLSurfaceView.Render接口
这一步是最重要的一步,因为着色器的生成,矩阵的变换,纹理的加载等都是在这里实现的,GLSurfaceView.Render有三个重要的待实现的接口:onSurfaceCreated(GL10 glUnused,EGLConfig config);
onSurfaceChanged(GL10 glUnused,int width,int height);
onDrawFrame(GL10 glUnused);
以上三个方法回调的时机分别如下:
onSurfaceCreated:当GLSurfaceView 实例生成时回调;
onSurfaceChanged:当手机横/竖屏切换时回调;
onDrawFrame:是由系统自动回调的,它会以一定的帧频率来调用重绘View。
当设置GLSurfaceView的渲染模式o为GLSurfaceView.RENDERMODE_CONTINUOUSLY或不设置时,系统就会主动渲染,就会回调onDrawFrame()方法
SunnyGLRender类如下:
public class SunnyGLRender implements GLSurfaceView.Renderer { private int mProgram; private int maPostionHandle; private FloatBuffer mTriangleVB; //定义顶点(vertex)着色器命令语句 private final String vertexShaderCode = "uniform mat4 uMVPMatrix; \n" + "attribute vec4 vPosition; \n" + "void main(){ \n" + " gl_Position = vPosition; \n" + "} \n"; //片元着色器 private final String fragmentShaderCode = "precision mediump float;\n" + "void main(){ \n" + " gl_FragColor = vec4 (0.63671875,0.76953125,0.22265625,1.0);\n" + "}\n"; //应用投影与相机视图 private int muMVPMatrixHandle; //用于存储变换矩阵结果的总变换矩阵[4*4] private float[] mMVPMatrix = new float[16]; //[4*4]的视图变换矩阵 private float[] mVMatrix = new float[16]; //[4*4]的投影变换矩阵 private float[] mProjMatrix = new float[16]; //[4*4]的模型变换矩阵 private float[] mMMatrix = new float[16]; public float mAngle; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { //GLES20:为OpenGL ES2.0版本,相应的 //GLES30:OpenGL ES3.0 //黑色背景 GLES20.glClearColor(0.5f,0.5f,0.5f,1.0f); //glClear:清除缓冲区标志,这里为:清除颜色缓冲及深度缓冲,把整个窗口清除为黑色背景 GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); initShapes(); int vertextShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode); //申请特定的着色器,program != 0 申请成功 mProgram = GLES20.glCreateProgram(); if(mProgram != 0 ){ GLES20.glAttachShader(mProgram,vertextShader); GLES20.glAttachShader(mProgram,fragmentShader); //连接着色器 GLES20.glLinkProgram(mProgram); int[] linkStatus = new int[1]; //查看着色器连接情况 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] != GLES20.GL_TRUE) { //连接失败 Log.e(TAG, "Could not link program: "); Log.e(TAG, GLES20.glGetProgramInfoLog(program)); GLES20.glDeleteProgram(program); program = 0; } //获取着特定着色器vPosition参数。 maPostionHandle = GLES20.glGetAttribLocation(mProgram,"vPosition"); } } /** * 初始化三角形的一些参数 */ private void initShapes() { /** * X,Y,Z三轴坐标 * U,V也即S,T,是图片,视频等以纹理的形式加载到GLSurfaceView中时的坐标 * U,V是无方向的 */ float trianlgeCoords[] = { //X,Y,Z,U,V -1.0f, -0.5f, 0, -0.5f, 0.0f, 1.0f, -0.5f, 0, 1.5f, -0.0f, 0.0f, 1.11803399f, 0, 0.5f, 1.61803399f }; ByteBuffer vbb = ByteBuffer.allocateDirect(trianlgeCoords.length * 4); vbb.order(ByteOrder.nativeOrder()); mTriangleVB = vbb.asFloatBuffer(); mTriangleVB.put(trianlgeCoords); mTriangleVB.position(0); } /** * 加载指定着色器 * @param type * @param shaderCode * @return */ private int loadShader(int type,String shaderCode){ int shader = GLES20.glCreateShader(type); if(shader != 0 ){ //加载着色器脚本程序(即本例的String 变量命令语句) GLES20.glShaderSource(shader,shaderCode); //编译着色器脚本程序 GLES20.glCompileShader(shader); int[] compiled = new int[1]; //查看编译结果 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); if (compiled[0] == 0) { //编译失败,释放申请的着色器 GLES20.glDeleteShader(shader); shader = 0; } } return shader; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width/height; //调用此方法来计算生成透视投影矩阵 Matrix.frustumM(mProjMatrix,0,-ratio,ratio,-1,1,3,7); //当Sucrface改变时,获取指定着色器的uMVPMatrix参数 muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,"uMVPMatrix"); //设定相机的视角 //调用此方法产生摄像机9参数位置矩阵 Matrix.setLookAtM(mVMatrix,0, 0,0,-3, //相机的x,y,z坐标 0,0,0,//目标对应的x,y,z坐标 0,1.0f,1.0f//相机的视觉向量(upx,upy,upz,三个向量最终的合成向量的方向为相机的方向) ); } @Override public void onDrawFrame(GL10 gl) { // Redraw background color //把左矩阵投影矩阵与右矩阵视图矩阵变换后的结果存储在总矩阵mMVPMatrix中 Matrix.multiplyMM(mMVPMatrix,0,mProjMatrix,0,mVMatrix,0); // GLES20.glUniformMatrix4fv(muMVPMatrixHandle,1,false,mMVPMatrix,0); //为三角形创建一个旋转动作 /*long time = SystemClock.uptimeMillis() % 4000L; mAngle = 0.090f * ((int)time);*/ //创建一个绕x,y,z轴旋转一定角度的矩阵 Matrix.setRotateM(mMMatrix,0,mAngle,0,0,1.0f); Matrix.multiplyMM(mMVPMatrix,0,mVMatrix,0,mMMatrix,0); Matrix.multiplyMM(mMVPMatrix,0,mProjMatrix,0,mMVPMatrix,0); GLES20.glUniformMatrix4fv(muMVPMatrixHandle,1,false,mMVPMatrix,0); //把Program用到OpenGL环境中 GLES20.glUseProgram(mProgram); //准备画三角形的数据 //为指定着色器取出的参数赋值 GLES20.glVertexAttribPointer(maPostionHandle,3,GLES20.GL_FLOAT,false,12,mTriangleVB); //使用这个从指定着色器中取出的参数的值 GLES20.glEnableVertexAttribArray(maPostionHandle); //开始画 GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3); } }
第三步:权限声明
经过以上二步,程序还不能运行,得在AndroidManifest.xml中声明相应权限。<!-- Tell the system this app requires OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
运行程序 就可以看到三角形了。
下一节
参考资料
Android OpenGL ES2.0 开发文档Android OpenGL ES 应用(二) 纹理
浅学OpenGLES2.0
google ApiDemo(这个自己看官方Demo就好了,就没有贴出下载地址了)
相关文章推荐
- 用正确的姿势来说说Android上的内存泄漏问题
- Android线程池
- 【Android】随便写写
- Qt for Android自定义AndroidManifest.xml
- Android 获取内置和外置存储卡的路径及总共、可用空间
- AndroidStudio快捷键(一)
- android 常用控件的一些属性注
- 【已解决】Android Studio 为什么每次新建项目都很慢
- MPAndroidChart饼图属性及相关设置
- Android SDK下载
- xamarin+VS2015安装步骤和破解方法(android)
- Android打包的那些事
- bug-android之INSTALL_FAILED_NO_MATCHING_ABIS无法安装在虚拟机
- Android TextView文字中底部或者中间加横线
- bug-android之INSTALL_FAILED_NO_MATCHING_ABIS
- 【转载】Android RecyclerView Bug:IndexOutOfBoundsException: Inconsistency detected. Invalid item position
- Android:minSdkVersion,targetSdkVersion,compileSdkVersion
- Android追加写入文件的几种方法
- Android 浏览器开发调研
- Android配置ip地址