原文地址:http://developer.android.com/intl/zh-cn/guide/topics/graphics/opengl.html
OpenGl 支持 2D和3D图形开源库。
Android支持多个版本的OpenGL ES API:
有两个基本类Android框架,让你创建和操作 图形与OpenGL ES API:GLSurfaceView
和 GLSurfaceView.Renderer
。 如果在你的Android应用程序是使用OpenGL的, 那么理解这些类是你的首要目标。
GLSurfaceView
View
你可以画和操纵对象使用在哪里 OpenGL API调用,在功能相似
SurfaceView
。 您可以使用 这个类创建的实例
GLSurfaceView
并添加你 的Render
。 然而,如果你想捕获 触屏事件,你应该延长
GLSurfaceView
类 实现触摸事件,见OpenGL培训课, 响应触摸事件
。
GLSurfaceView.Renderer
GLSurfaceView
。 你必须提供该接口的一个实现 类,并将其附加到
GLSurfaceView
实例使用
GLSurfaceView.setRenderer()
。
的 GLSurfaceView.Renderer
界面要求您实现 下面的方法:
onSurfaceCreated()
:这个系统调用 方法一次,当创建 GLSurfaceView
。 使用这个方法来执行 只需要发生一次的行动,比如设置参数或OpenGL环境 初始化OpenGL图形对象。onDrawFrame()
:系统调用这个方法的重绘 GLSurfaceView
。 使用这种方法作为主要执行绘制(重新绘制)图形对象。onSurfaceChanged()
:系统调用这个方法的时候 GLSurfaceView
几何形状的变化,包括大小的变化GLSurfaceView
或定位设备的屏幕。 例如,系统调用 这种方法当设备从肖像到横向变化。 使用这种方法 响应的变化 GLSurfaceView
容器。 一旦你建立了一个容器视图使用OpenGL ES GLSurfaceView
和 GLSurfaceView.Renderer
,你就可以开始 调用OpenGL api使用以下类:
android.opengl
——这个包提供了一个静态界面OpenGL ES 类和更好的性能比1.0/1.1javax.microedition.khronos
包 接口。
GLES10
GLES10Ext
GLES11
GLES11Ext
javax.microedition.khronos.opengles
这个包提供了标准 实现OpenGL ES的1.0/1.1。
GL10
GL10Ext
GL11
GL11Ext
GL11ExtensionPack
android.opengl.GLES20
这个包提供了 接口OpenGL ES 2.0和可以从Android 2.2(API级别8)。android.opengl
——这包提供的接口OpenGL ES 3.0/3.1 类。 版本是3.0从Android 4.3(API级别18)。 版本是3.1 从Android 5.0(API级别21)。
GLES30
GLES31
GLES31Ext
( Android扩展包 )如果你想开始构建应用程序与OpenGL ES,遵循 显示图形与OpenGL ES 类。
如果您的应用程序使用OpenGL所有设备功能不可用,你必须包括 这些需求在你的 AndroidManifest.xml 文件。 这是最常见的OpenGL清单声明:
OpenGL ES 2.0:
<!-- Tell the system this app requires OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
添加这个声明会导致谷歌应用市场限制 安装在设备不支持OpenGL ES 2.0。 如果您的应用程序是专门为 设备支持OpenGL ES 3.0中,您还可以指定在你的清单:
OpenGL ES 3.0:
<!-- Tell the system this app requires OpenGL ES 3.0. --> <uses-feature android:glEsVersion="0x00030000" android:required="true" />
OpenGL ES 3.1:
<!-- Tell the system this app requires OpenGL ES 3.1. --> <uses-feature android:glEsVersion="0x00030001" android:required="true" />
注意: OpenGL ES 3。 x的API是向后兼容2.0的API,这意味着你可以更多 灵活的与你在应用程序中实现OpenGL ES。 通过声明的OpenGL ES 2.0 API要求在你的清单,你可以使用API版本作为违约,检查 可用性的3。 x在运行时API,然后使用OpenGL ES 3。 x功能如果 设备支持它。 关于检查的更多信息支持OpenGL ES版本 设备,看到 检查OpenGL ES版本 。
< supports-gl-texture >
。 有关可用的纹理压缩的更多信息 格式,请参阅 纹理压缩支持 。 宣布纹理压缩从用户需求清单中隐藏您的应用程序 与设备不支持至少一个声明的压缩类型。 更多的 谷歌如何过滤信息适用于纹理按压,看到 谷歌玩和纹理压缩过滤 部分的 < supports-gl-texture >
文档。
在Android设备上不同的大小和形状你如何展示。 OpenGL假定一个正方形,统一的坐标系统,在默认情况下,幸福 吸引这些坐标到你通常方阵屏幕好像是完全平方。
上面的插图显示了一个OpenGL的统一坐标系统假设框架上 离开了,这些坐标如何映射到一个典型的设备在横向屏幕 在右边。 为了解决这个问题,您可以应用OpenGL投影模式和相机视图 坐标变换你的图形对象在任何显示正确的比例。
为了应用投影和相机视图,您创建一个投影矩阵和一个相机视图 矩阵并将它们应用于OpenGL渲染管道。 投影矩阵重新计算 你的坐标图形,使他们正确地映射到Android设备的屏幕。 相机视图 矩阵创建一个转换,它显示对象从一个特定的位置。
ES 1.0 API,应用投影和通过创建每个矩阵,然后相机视图 将它们添加到OpenGL环境。
onSurfaceChanged()
的方法 GLSurfaceView.Renderer
实现创建一个基于屏幕的长宽比和投影矩阵应用它 OpenGL渲染环境。 public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); // make adjustments for screen ratio float ratio = (float) width / height; gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode gl.glLoadIdentity(); // reset the matrix to its default state gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix }
onDrawFrame()
的方法 GLSurfaceView.Renderer
实现应用模型视图,并使用 GLU.gluLookAt()
实用程序来创建一个查看映射 模拟摄像机的位置。 public void onDrawFrame(GL10 gl) { ... // Set GL_MODELVIEW transformation mode gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); // reset the matrix to its default state // When using GL_MODELVIEW, you must set the camera view GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); ... }
ES 2.0和3.0 api,应用投影和相机视图矩阵首先添加一个成员 图形的顶点着色器对象。 你可以用这个矩阵成员补充道 生成和投影和相机观察矩阵应用到你的对象。
uMVPMatrix
成员可以应用投影和相机查看 矩阵的坐标对象使用这种材质。 private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of objects that use this vertex shader. "uniform mat4 uMVPMatrix; \n" + "attribute vec4 vPosition; \n" + "void main(){ \n" + // The matrix must be included as part of gl_Position // Note that the uMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. " gl_Position = uMVPMatrix * vPosition; \n" + "} \n";
注意: 上面的例子定义了一个单一的变换矩阵 成员在顶点着色器中应用投影矩阵和相机视图 矩阵。 取决于您的应用程序需求,您可能需要定义单独的投影 矩阵和相机观察矩阵成员在你的顶点着色器,这样你就可以改变他们 独立。
onSurfaceCreated()
的方法 GLSurfaceView.Renderer
实现访问矩阵 顶点着色器中定义的变量。 public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); ... }
onSurfaceCreated()
和 onSurfaceChanged()
的方法 GLSurfaceView.Renderer
实现创建相机视图矩阵和 投影矩阵基于设备的屏幕宽高比。 public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... // Create a camera view matrix Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); } public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; // create a projection matrix from device screen geometry Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); }
onDrawFrame()
的方法 GLSurfaceView.Renderer
实现结合 投影矩阵和相机视图中创建上面的代码,然后把它应用到图形 对象被OpenGL渲染。 public void onDrawFrame(GL10 unused) { ... // Combine the projection and camera view matrices Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); // Apply the combined projection and camera view transformations GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); // Draw objects ... }
为一个完整的例子如何应用投影相机视图和OpenGL ES 2.0,看到 显示图形与OpenGL ES 类。
在OpenGL,面对一个形状是由三个或更多的点在三维表面定义 空间。 一组三个或更多三维点(称为顶点在OpenGL)有一个正面 和背面。 你怎么知道哪面是正面和背面? 好问题。 的 答案与绕组,或者你的方向定义的点的形状。
在这个例子中,三角形的点定义在一个订单,这样绘制的 逆时针方向。 这些坐标的顺序绘制定义了绕组 方向的形状。 默认情况下,在OpenGL,界面是逆时针的 前面的界面。 图1所示的三角形定义,这样你的正面 形状(如解释OpenGL),另一边是背面。
为什么它是重要的知道哪个界面的形状是正面的? 与一个答案 OpenGL的常用功能,叫做FaceCulling。 OpenGL的FaceCulling是一种选择 环境渲染管道可以忽略(不计算或画)的背面 形状、节省时间、内存和处理周期:
// enable face culling feature gl.glEnable(GL10.GL_CULL_FACE); // specify which faces to not draw gl.glCullFace(GL10.GL_BACK);
如果您尝试使用FaceCulling特性的形状是不知道 前后,OpenGL图形看起来有点瘦,或者根本不出现。 所以,总是定义你的OpenGL图形的坐标逆时针顺序。
注意: 可以设置一个OpenGL环境来治疗 顺时针为正面,但这样做需要更多的代码,可能会混淆 有经验的OpenGL开发人员当你向他们请求帮助。 所以不要这样做。
OpenGL ES 1.0和1.1 API规范以来一直支持Android 1.0。 从Android 2.2(API级别8)开始,该框架支持OpenGL ES 2.0 API 规范。 OpenGL ES 2.0支持大多数Android设备和新建议 与OpenGL应用程序开发。 OpenGL ES 3.0支持Android 4.3 (API级别18)越高,设备上,提供一个实现OpenGL ES 3.0 API。 信息相对数量的安卓设备 支持OpenGL ES的给定版本,查看 OpenGL ES版本仪表板 。
图形编程与OpenGL ES 1.0/1.1 API比使用2.0明显不同 和更高的版本。 1。 x版本的API提供了更方便的方法和一个固定的图形 管道,OpenGL ES 2.0和3.0 api提供更多的直接控制管道通过 使用OpenGL着色器。 你应该仔细考虑图形需求和选择API 版本最适合您的应用程序。 有关更多信息,请参见 选择一个OpenGL API版本 。
OpenGL ES 3.0 API提供了额外的功能和更好的性能比2.0 API 也向后兼容的。 这意味着您可以编写应用程序目标 OpenGL ES 2.0和条件包括OpenGL ES 3.0图形特性,如果他们是可用的。 为 检查的可用性3.0 API的更多信息,参见检查OpenGL ES版本
纹理压缩可以显著提高OpenGL应用程序的性能 减少内存需求和更有效的利用内存带宽。 安卓 框架提供了支持ETC1压缩格式作为标准功能,包括一个 ETC1Util
实用程序类和 etc1tool
(位于压缩工具 Android SDK在 < sdk > /工具/
)。 使用的Android应用程序的一个例子 纹理压缩,请参阅 CompressedTextureActivity
在Android SDK代码示例 ( < sdk > / / <版本> / ApiDemos / src /com/example/android/apis/graphics/样本
)。
警告: ETC1格式支持大多数的Android设备, 但是它不能保证是可用的。 检查设备是否支持ETC1格式,电话 的ETC1Util.isETC1Supported()
方法。
注意: ETC1纹理压缩格式不支持纹理的 透明度(alpha通道)。 如果您的应用程序需要与透明质地,你应该 调查其他纹理压缩格式可以在你的目标设备。
ETC2 / EAC纹理压缩格式是保证使用OpenGL ES时可用 3.0 API。 这个纹理格式提供了良好的视觉质量和压缩比高 格式还支持透明度(alpha通道)。
等格式之外,Android设备有不同的纹理压缩基于支持 他们的GPU芯片和OpenGL实现。 你应该调查纹理压缩支持 你目标的设备来确定您的应用程序应该压缩类型 支持。 为了确定纹理格式支持在一个给定的设备,你必须 查询设备和复习 OpenGL扩展名 , 找出纹理压缩格式(和其他OpenGL功能)支持的吗 设备。 一些常见的支持纹理压缩格式如下:
GL_AMD_compressed_ATC_texture
GL_ATI_texture_compression_atitc
GL_IMG_texture_compression_pvrtc
GL_EXT_texture_compression_s3tc
GL_EXT_texture_compression_dxt1
GL_AMD_compressed_3DC_texture
警告: 这些纹理压缩格式 不 支持 在所有设备。 支持这些格式的大小变化和设备制造商。 为 如何确定纹理压缩格式是在一个特定的设备,看 下一节。
注意: 一旦你决定哪些纹理压缩格式 应用程序支持,确保你在清单使用声明它们 < supports-gl-texture > 。 使用这个宣言使过滤由外部服务,如谷歌玩,所以 应用程序安装在您的应用程序需要设备支持的格式。 有关详细信息,请参见 OpenGL清单声明 。
的实现OpenGL随Android设备的扩展OpenGL ES API 支持。 这些扩展包括纹理按压,但通常也包括其他 对OpenGL的特性集的扩展。
来确定纹理压缩格式,和其他OpenGL扩展,支持在一个 特定的设备:
String extensions = javax.microedition.khronos.opengles.GL10.glGetString( GL10.GL_EXTENSIONS);
警告: 这个调用的结果 随设备模型! 你 必须运行此呼吁几个目标设备来确定一般压缩类型是什么 支持。
AEP确保您的应用程序支持一组标准化的OpenGL扩展 及以后 OpenGL 3.1规范中描述的核心。 这些扩展在一起包装 鼓励跨设备一套一致的功能,同时允许开发人员充分 利用最新的移动GPU设备。
AEP也提高了支持图片、材质存储缓冲区和原子计数器 片段着色器。
为您的应用程序能够使用AEP,AEP的应用程序的清单必须声明是必需的。 此外,平台必须支持版本。
声明AEP清单中的要求如下:
<uses feature android:name="android.hardware.opengles.aep" android:required="true" />
验证平台的版本支持AEP,使用 hasSystemFeature(字符串)
方法,传入 FEATURE_OPENGLES_EXTENSION_PACK
作为参数。 下面的代码片段 如何这样做显示了一个例子:
boolean deviceSupportsAEP = getPackageManager().hasSystemFeature (PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
如果方法返回true,AEP的支持。
AEP的更多信息,请访问页面 Khronos OpenGL ES注册表 。
有几个版本的OpenGL ES可以在Android设备。 您可以指定 最低版本的API应用程序需要在你 清单 ,但 您可能还想利用特征同时在一个更新的API。 例如, OpenGL ES 3.0与2.0版本的API是向后兼容的API,所以你可能想要 编写应用程序,以便它使用OpenGL ES 3.0特性,但如果回落到2.0 API 3.0 API是不可用的。
之前使用OpenGL ES特性从一个版本高于你的最低要求 应用程序清单文件,应用程序应该检查设备上的版本可用的API。 你可以以两种方式之一:
EGLContext
), 检查结果。 下面的示例代码演示了如何通过创建检查可用的OpenGL ES版本 一个 EGLContext
并检查结果。 这个例子展示了如何检查 OpenGL ES 3.0版本:
private static double glVersion = 3.0; private static class ContextFactory implements GLSurfaceView.EGLContextFactory { private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public EGLContext createContext( EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { Log.w(TAG, "creating OpenGL ES " + glVersion + " context"); int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) glVersion, EGL10.EGL_NONE }; // attempt to create a OpenGL ES 3.0 context EGLContext context = egl.eglCreateContext( display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); return context; // returns null if 3.0 is not supported; } }
如果 createContext()
方法上面显示返回null,您的代码应该创建一个OpenGL ES 2.0上下文而不是和落回只使用API。
下面的代码示例演示了如何检查OpenGL ES版本通过创建一个最小值 首先支持上下文,然后检查版本字符串:
// Create a minimum supported OpenGL ES context, then check: String version = javax.microedition.khronos.opengles.GL10.glGetString( GL10.GL_VERSION); Log.w(TAG, "Version: " + version ); // The version format is displayed as: "OpenGL ES <major>.<minor>" // followed by optional content provided by the implementation.
使用这种方法,如果发现设备支持更高级的API版本,你 必须摧毁的最低OpenGL ES上下文和创建一个新的上下文与高 可用的API版本。
OpenGL ES 1.0 API版本(1.1扩展),2.0版,3.0版都提供高 性能用于创建3 d游戏的图形界面,可视化和用户接口。 图形 本节目为OpenGL ES 2.0和3.0在很大程度上是相似的,与3.0版本代表一个超集 2.0 API的附加功能。 OpenGL ES 1.0/1.1 API的编程与OpenGL ES 2.0和3.0显著不同,因此开发人员应该仔细考虑以下 因素开始前与这些api开发: