最近在学习Android Opengles,第一步先从Android官网开始学习基础教程,了解开发Opengles的相关概念和开发步骤,因此Google翻译了一下官网文档,在此做个记录。英语好的可以直接看官网。
Android 通过开放图形库 (OpenGL®),特别是 OpenGL ES API,支持高性能 2D 和 3D 图形。 OpenGL 是一个跨平台的图形 API,它为 3D 图形处理硬件指定了一个标准的软件接口。 OpenGL ES 是一种用于嵌入式设备的 OpenGL 规范。 Android 支持多个版本的 OpenGL ES API:
- OpenGL ES 1.0 和 1.1 - 此 API 规范受 Android 1.0 及更高版本支持。
- OpenGL ES 2.0 - 此 API 规范受 Android 2.2(API 级别 8)及更高版本支持。
- OpenGL ES 3.0 - 此 API 规范受 Android 4.3(API 级别 18)及更高版本支持。
- OpenGL ES 3.1 - 此 API 规范受 Android 5.0(API 级别 21)及更高版本支持。
注意:无论 Android 平台版本如何,设备都不能支持 OpenGL ES 3.0 API,除非设备制造商提供此图形管道的实现。如果您在清单中指定需要 OpenGL ES 3.0,则可以确定该版本将出现在设备上。如果您指定需要较低级别的版本,但您想要使用 3.0 功能(如果它们可用),您应该在运行时检查设备支持的 OpenGL 版本。有关如何执行此操作的信息,请参阅检查 OpenGL ES 版本。
注:Android框架提供的具体API与J2ME JSR239 OpenGL ES API类似,但不完全相同。如果您熟悉 J2ME JSR239 规范,请注意变体。
Also see
- Displaying graphics with OpenGL ES
- OpenGL ES
- OpenGL ES 1.x Specification
- OpenGL ES 2.x specification
- OpenGL ES 3.x specification
基础
Android 通过其框架 API 和本地开发工具包 (NDK) 支持 OpenGL。本主题重点介绍 Android 框架接口。有关 NDK 的更多信息,请参阅 Android NDK。
Android 框架中有两个基础类可让您使用 OpenGL ES API 创建和操作图形:GLSurfaceView 和 GLSurfaceView.Renderer。如果您的目标是在 Android 应用程序中使用 OpenGL,那么了解如何在 Activity 中实现这些类应该是您的首要目标。
GLSurfaceView
此类是一个视图,您可以在其中使用 OpenGL API 调用绘制和操作对象,并且在功能上类似于 SurfaceView。您可以通过创建 GLSurfaceView 的实例并将渲染器添加到它来使用此类。然而,如果你想捕捉触摸屏事件,你应该扩展 GLSurfaceView 类来实现触摸监听器,如 OpenGL 培训课程响应触摸事件所示。
GLSurfaceView.Renderer
该接口定义了在 GLSurfaceView 中绘制图形所需的方法。您必须将此接口的实现作为单独的类提供,并使用 GLSurfaceView.setRenderer() 将其附加到您的 GLSurfaceView 实例。 GLSurfaceView.Renderer 接口要求您实现以下方法:
- onSurfaceCreated():系统在创建GLSurfaceView时调用一次该方法。使用此方法执行只需要发生一次的操作,例如设置 OpenGL 环境参数或初始化 OpenGL 图形对象。
- onDrawFrame():系统在每次重绘 GLSurfaceView 时调用此方法。使用此方法作为绘制(和重新绘制)图形对象的主要执行点。
- onSurfaceChanged():当 GLSurfaceView 的几何形状发生变化时,系统会调用此方法,包括 GLSurfaceView 的大小或设备屏幕方向的变化。例如,当设备从纵向变为横向时,系统会调用此方法。使用此方法响应 GLSurfaceView 容器中的更改。
OpenGL ES 包
使用 GLSurfaceView 和 GLSurfaceView.Renderer 为 OpenGL ES 建立容器视图后,您可以开始使用以下类调用 OpenGL API:
- OpenGL ES 1.0/1.1 API Packages
-
- android.opengl - 这个包提供了一个 OpenGL ES 1.0/1.1 类的静态接口和比 javax.microedition.khronos 包接口更好的性能。
-
- javax.microedition.khronos.opengles - 这个包提供了 OpenGL ES 1.0/1.1 的标准实现。
- OpenGL ES 2.0 API Class
-
- android.opengl.GLES20 - 该包提供了 OpenGL ES 2.0 的接口,从 Android 2.2(API 级别 8)开始可用。
- OpenGL ES 3.0/3.1 API Packages
-
- android.opengl - 这个包提供了 OpenGL ES 3.0/3.1 类的接口。 3.0 版从 Android 4.3(API 级别 18)开始可用。版本 3.1 从 Android 5.0(API 级别 21)开始可用。
声明 OpenGL 要求
如果您的应用程序使用并非在所有设备上都可用的 OpenGL 功能,您必须在 AndroidManifest.xml 文件中包含这些要求。以下是最常见的 OpenGL 清单声明:
- OpenGL ES 版本要求 - 如果您的应用程序需要特定版本的 OpenGL ES,您必须通过将以下设置添加到您的清单来声明该要求,如下所示。 对于 OpenGL ES 2.0:
<!-- Tell the system this app requires OpenGL ES 2.0. -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
添加此声明会导致 Google Play 限制您的应用程序安装在不支持 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 版本。
- 纹理压缩要求:如果您的应用程序使用纹理压缩格式,您必须使用 在清单文件中声明您的应用程序支持的格式。有关可用纹理压缩格式的更多信息,请参阅纹理压缩支持。 在您的清单中声明纹理压缩要求会向使用不支持至少一种您声明的压缩类型的设备的用户隐藏您的应用程序。有关 Google Play 过滤如何处理纹理压缩的更多信息,请参阅 文档的 Google Play 和纹理压缩过滤部分。
绘制对象的映射坐标
在 Android 设备上显示图形的基本问题之一是它们的屏幕大小和形状可能不同。 OpenGL 假定一个正方形、统一的坐标系,默认情况下,它会愉快地将这些坐标绘制到您通常的非正方形屏幕上,就好像它是完美的正方形一样。
默认 OpenGL 坐标系(左)映射到典型的 Android 设备屏幕(右)。
上图左侧显示了为 OpenGL 帧假定的统一坐标系,右侧显示了这些坐标如何实际映射到典型的横向设备屏幕。要解决此问题,您可以应用 OpenGL 投影模式和相机视图来转换坐标,以便您的图形对象在任何显示器上都具有正确的比例。 为了应用投影和相机视图,您创建一个投影矩阵和一个相机视图矩阵并将它们应用到 OpenGL 渲染管道。投影矩阵重新计算图形的坐标,以便它们正确映射到 Android 设备屏幕。相机视图矩阵创建一个从特定眼睛位置渲染对象的变换。
OpenGL ES 1.0 中的投影和相机视图
在 ES 1.0 API 中,您通过创建每个矩阵然后将它们添加到 OpenGL 环境来应用投影和相机视图。
- 投影矩阵 - 使用设备屏幕的几何形状创建投影矩阵,以便重新计算对象坐标,以便以正确的比例绘制它们。以下示例代码演示了如何修改 GLSurfaceView.Renderer 实现的 onSurfaceChanged() 方法,以根据屏幕的纵横比创建投影矩阵并将其应用于 OpenGL 渲染环境。
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
gl.apply {
glViewport(0, 0, width, height)
//调整屏幕比例
val ratio: Float = width.toFloat() / height.toFloat()
glMatrixMode(GL10.GL_PROJECTION) // 将矩阵设置为投影模式
glLoadIdentity() // 将矩阵重置为其默认值
glFrustumf(-ratio, ratio, -1f, 1f, 3f, 7f) // 应用投影矩阵
}
}
- 相机变换矩阵 - 使用投影矩阵调整坐标系后,还必须应用相机视图。以下示例代码显示如何修改 GLSurfaceView.Renderer 实现的 onDrawFrame() 方法以应用模型视图并使用 GLU.gluLookAt() 实用程序创建模拟相机位置的查看转换。
override fun onDrawFrame(gl: GL10) {
...
gl.apply {
// 设置 GL_MODELVIEW 变换模式
glMatrixMode(GL10.GL_MODELVIEW)
glLoadIdentity() // 将矩阵重置为默认状态
}
// 使用GL_MODELVIEW时,必须设置camera view
GLU.gluLookAt(gl, 0f, 0f, -5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
...
}
OpenGL ES 2.0 及更高版本中的投影和相机视图
在 ES 2.0 和 3.0 API 中,您可以通过首先将矩阵成员添加到图形对象的顶点着色器来应用投影和相机视图。添加此矩阵成员后,您就可以生成投影和相机观察矩阵并将其应用于您的对象。
- 1、将矩阵添加到顶点着色器
为视图投影矩阵创建一个变量并将其包含为着色器位置的乘数。在下面的示例顶点着色器代码中,包含的 uMVPMatrix 成员允许您将投影和相机观察矩阵应用于使用此着色器的对象的坐标。
private val vertexShaderCode =
// 这个矩阵成员变量提供了一个钩子来操纵使用这个顶点着色器的对象的坐标。
"uniform mat4 uMVPMatrix; \n" +
"attribute vec4 vPosition; \n" +
"void main(){ \n" +
// 矩阵必须作为 g_l_Position 的一部分包含在内。
// 请注意,uMVPMatrix 因子必须位于第一个以便矩阵乘积正确。
" gl_Position = uMVPMatrix * vPosition; \n" +
"} \n"
注意:上面的示例在顶点着色器中定义了一个变换矩阵成员,您可以在其中应用组合的投影矩阵和相机视图矩阵。根据您的应用程序要求,您可能希望在顶点着色器中定义单独的投影矩阵和相机观察矩阵成员,以便您可以独立更改它们。
- 2、访问着色器矩阵
在顶点着色器中创建一个挂钩以应用投影和相机视图后,您可以访问该变量以应用投影和相机视图矩阵。以下代码显示如何修改 GLSurfaceView.Renderer 实现的 onSurfaceCreated() 方法以访问上面顶点着色器中定义的矩阵变量。
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
...
muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix")
...
}
- 3、创建投影和相机观察矩阵
生成要应用于图形对象的投影和观察矩阵。以下示例代码显示了如何修改 GLSurfaceView.Renderer 实现的 onSurfaceCreated() 和 onSurfaceChanged() 方法,以根据设备的屏幕纵横比创建相机视图矩阵和投影矩阵。
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
...
// 创建相机视图矩阵
Matrix.setLookAtM(vMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
}
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height)
val ratio: Float = width.toFloat() / height.toFloat()
// 从设备屏幕几何形状创建投影矩阵
Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
}
- 4、应用投影和相机视图矩阵
要应用投影和相机视图变换,将矩阵相乘,然后将它们设置到顶点着色器中。下面的示例代码显示了如何修改 GLSurfaceView.Renderer 实现的 onDrawFrame() 方法以组合在上面的代码中创建的投影矩阵和相机视图,然后将其应用于要由 OpenGL 渲染的图形对象。
override fun onDrawFrame(gl: GL10) {
...
// 结合投影和相机视图矩阵
Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0)
// 应用组合投影和相机视图变换
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0)
// Draw objects
...
}
形状面和缠绕
在 OpenGL 中,形状的面是由三维空间中的三个或更多点定义的表面。一组三个或更多的三维点(在 OpenGL 中称为顶点)具有正面和背面。你怎么知道哪张脸是正面,哪一张是背面?好问题。答案与缠绕或定义形状点的方向有关。
转换为逆时针绘图顺序的坐标列表的插图。
在此示例中,三角形的点按逆时针方向绘制的顺序定义。这些坐标的绘制顺序定义了形状的缠绕方向。默认情况下,在 OpenGL 中,逆时针绘制的面是正面。图 1 中所示的三角形被定义为您可以看到形状的正面(由 OpenGL 解释),而另一侧是背面。 为什么知道形状的哪个面是正面很重要?答案与 OpenGL 的一个常用功能有关,称为面部剔除。面剔除是 OpenGL 环境的一个选项,它允许渲染管道忽略(不计算或绘制)形状的背面,从而节省时间、内存和处理周期:
gl.apply {
// 启用面部剔除功能
glEnable(GL10.GL_CULL_FACE)
// 指定不绘制哪些面
glCullFace(GL10.GL_BACK)
}
如果您在不知道形状的哪一侧是正面和背面的情况下尝试使用面部剔除功能,您的 OpenGL 图形将看起来有点薄,或者可能根本不显示。因此,始终以逆时针绘制顺序定义 OpenGL 形状的坐标。
OpenGL 版本和设备兼容性
从 Android 1.0 开始支持 OpenGL ES 1.0 和 1.1 API 规范。从 Android 2.2(API 级别 8)开始,该框架支持 OpenGL ES 2.0 API 规范。大多数 Android 设备都支持 OpenGL ES 2.0,建议将其用于使用 OpenGL 开发的新应用程序。在提供 OpenGL ES 3.0 API 实现的设备上,Android 4.3(API 级别 18)及更高版本支持 OpenGL ES 3.0。有关支持给定 OpenGL ES 版本的 Android 设备的相对数量的信息,请参阅 OpenGL ES 版本仪表板。
使用 OpenGL ES 1.0/1.1 API 进行图形编程与使用 2.0 及更高版本有很大不同。 API 的 1.x 版本具有更多便利方法和固定图形管道,而 OpenGL ES 2.0 和 3.0 API 通过使用 OpenGL 着色器提供对管道的更直接控制。您应该仔细考虑图形要求并选择最适合您的应用程序的 API 版本。有关详细信息,请参阅选择 OpenGL API 版本。
与 2.0 API 相比,OpenGL ES 3.0 API 提供了额外的功能和更好的性能,并且还向后兼容。这意味着您可以编写面向 OpenGL ES 2.0 的应用程序,并有条件地包含 OpenGL ES 3.0 图形功能(如果它们可用)。有关检查 3.0 API 可用性的更多信息,请参阅检查 OpenGL ES 版本。
纹理压缩支持
纹理压缩可以减少内存需求和更有效地使用内存带宽来显着提高 OpenGL 应用程序的性能。 Android 框架作为标准功能提供对 ETC1 压缩格式的支持,包括 ETC1Util 实用程序类和 etc1tool 压缩工具(位于 Android SDK 中的 /tools/)。有关使用纹理压缩的 Android 应用程序示例,请参阅 Android SDK (/samples//ApiDemos/src/com/example/android/apis/graphics/) 中的 CompressedTextureActivity 代码示例。
注意:大多数 Android 设备都支持 ETC1 格式,但不保证可用。要检查设备是否支持 ETC1 格式,请调用 ETC1Util.isETC1Supported() 方法。
注意:ETC1 纹理压缩格式不支持具有透明度(alpha 通道)的纹理。如果您的应用程序需要具有透明度的纹理,您应该研究目标设备上可用的其他纹理压缩格式。
ETC2/EAC 纹理压缩格式保证在使用 OpenGL ES 3.0 API 时可用。这种纹理格式提供出色的压缩比和高视觉质量,并且该格式还支持透明度(alpha 通道)。
除了 ETC 格式之外,Android 设备还根据其 GPU 芯片组和 OpenGL 实现对纹理压缩提供了多种支持。您应该调查目标设备上的纹理压缩支持,以确定您的应用程序应支持的压缩类型。为了确定给定设备支持哪些纹理格式,您必须查询设备并查看 OpenGL 扩展名称,这些名称标识设备支持哪些纹理压缩格式(和其他 OpenGL 功能)。一些常用的支持的纹理压缩格式如下:
- ATITC (ATC)
ATI 纹理压缩(ATITC 或 ATC)可用于各种设备,并支持对带和不带 Alpha 通道的 RGB 纹理进行固定速率压缩。这种格式可以用几个 OpenGL 扩展名来表示,例如:
-
- GL_AMD_compressed_ATC_texture
- GL_ATI_texture_compression_atitc
- PVRTC
PowerVR 纹理压缩 (PVRTC) 可用于多种设备,支持每像素 2 位和 4 位纹理,带或不带 alpha 通道。此格式由以下 OpenGL 扩展名称表示:
-
- GL_IMG_texture_compression_pvrtc
- S3TC (DXTn/DXTC)
S3 纹理压缩 (S3TC) 有多种格式变体(DXT1 到 DXT5)并且不太广泛使用。该格式支持具有 4 位 alpha 或 8 位 alpha 通道的 RGB 纹理。这些格式由以下 OpenGL 扩展名称表示:
-
- GL_EXT_texture_compression_s3tc
有些设备只支持 DXT1 格式变体;这种有限的支持由以下 OpenGL 扩展名称表示:
-
- GL_EXT_texture_compression_dxt1
- 3DC
3DC 纹理压缩 (3DC) 是一种不太广泛使用的格式,它支持具有 alpha 通道的 RGB 纹理。此格式由以下 OpenGL 扩展名称表示:
-
- GL_AMD_compressed_3DC_texture
警告:并非所有设备都支持这些纹理压缩格式。对这些格式的支持可能因制造商和设备而异。有关如何确定特定设备上的纹理压缩格式的信息,请参阅下一节。
注意:一旦您决定了您的应用程序将支持哪些纹理压缩格式,请确保您使用 在您的清单中声明它们。使用此声明可以通过外部服务(例如 Google Play)进行过滤,以便您的应用程序仅安装在支持您的应用程序所需格式的设备上。有关详细信息,请参阅 OpenGL 清单声明。
确定 OpenGL 扩展
就支持的 OpenGL ES API 扩展而言,OpenGL 的实现因 Android 设备而异。这些扩展包括纹理压缩,但通常还包括对 OpenGL 功能集的其他扩展。 要确定特定设备支持哪些纹理压缩格式和其他 OpenGL 扩展:
1、在您的目标设备上运行以下代码以确定支持哪些纹理压缩格式
var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
警告:此调用的结果因设备型号而异!您必须在多个目标设备上运行此调用以确定通常支持哪些压缩类型。
2、查看此方法的输出以确定设备支持哪些 OpenGL 扩展。
Android Extension Pack (AEP)
AEP 确保您的应用程序支持一组标准化的 OpenGL 扩展,超出 OpenGL 3.1 规范中描述的核心集。将这些扩展打包在一起鼓励跨设备的一组一致的功能,同时允许开发人员充分利用最新的移动 GPU 设备。 AEP 还改进了对片段着色器中的图像、着色器存储缓冲区和原子计数器的支持。
为了让您的应用能够使用 AEP,应用的清单必须声明 AEP 是必需的。另外,平台版本必须支持。
在manifest中声明AEP要求如下:
<uses-feature android:name="android.hardware.opengles.aep"
android:required="true" />
要验证平台版本是否支持 AEP,请使用 hasSystemFeature(String) 方法,将 FEATURE_OPENGLES_EXTENSION_PACK 作为参数传入。以下代码片段显示了如何执行此操作的示例:
var deviceSupportsAEP: Boolean =
packageManager.hasSystemFeature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK)
如果该方法返回 true,则支持 AEP。 有关 AEP 的更多信息,请访问其在 Khronos OpenGL ES Registry 的页面。
检查 OpenGL ES 版本
Android 设备上有多个可用的 OpenGL ES 版本。您可以在清单中指定您的应用程序所需的最低 API 版本,但您可能还想同时利用较新 API 中的功能。例如,OpenGL ES 3.0 API 向后兼容 API 的 2.0 版本,因此您可能希望编写应用程序以使其使用 OpenGL ES 3.0 功能,但如果 3.0 API 不可用,则回退到 2.0 API可用的。
在使用高于应用程序清单中最低要求的版本的 OpenGL ES 功能之前,您的应用程序应检查设备上可用的 API 版本。您可以通过以下两种方式之一执行此操作:
- 尝试创建更高级别的 OpenGL ES 上下文 (EGLContext) 并检查结果。
- 创建最低支持的 OpenGL ES 上下文并检查版本值。
以下示例代码演示了如何通过创建 EGLContext 并检查结果来检查可用的 OpenGL ES 版本。此示例显示如何检查 OpenGL ES 3.0 版本:
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
private class ContextFactory : GLSurfaceView.EGLContextFactory {
override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig): EGLContext {
Log.w(TAG, "creating OpenGL ES $glVersion context")
return egl.eglCreateContext(
display,
eglConfig,
EGL10.EGL_NO_CONTEXT,
intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
) // returns null if 3.0 is not supported
}
}
如果上面显示的 createContext() 方法返回 null,您的代码应该创建一个 OpenGL ES 2.0 上下文,然后回退到仅使用该 API。 下面的代码示例演示了如何通过首先创建一个最小支持上下文来检查 OpenGL ES 版本,然后检查版本字符串:
// 创建支持的最小 OpenGL ES 上下文,然后检查:
gl.glGetString(GL10.GL_VERSION).also {
Log.w(TAG, "Version: $it")
}
// 版本格式显示为:“OpenGL ES <major>.<minor>”后跟实现提供的可选内容。
使用这种方法,如果您发现设备支持更高级别的 API 版本,则必须销毁最小的 OpenGL ES 上下文并创建具有更高可用 API 版本的新上下文。
选择 OpenGL API 版本
OpenGL ES 1.0 API 版本(和 1.1 扩展)、2.0 版和 3.0 版都提供了用于创建 3D 游戏、可视化和用户界面的高性能图形接口。 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 开始开发之前应仔细考虑以下因素:
- 性能
通常,OpenGL ES 2.0 和 3.0 提供比 ES 1.0/1.1 API 更快的图形性能。但是,由于硬件制造商对 OpenGL ES 图形管道的实现存在差异,因此性能差异可能会因运行 OpenGL 应用程序的 Android 设备而异。
- 设备兼容性
开发人员应考虑可供客户使用的设备类型、Android 版本和 OpenGL ES 版本。有关跨设备的 OpenGL 兼容性的更多信息,请参阅 OpenGL 版本和设备兼容性部分。
- 编码便利
OpenGL ES 1.0/1.1 API 提供固定功能管道和便利功能,这些功能在 OpenGL ES 2.0 或 3.0 API 中不可用。刚接触 OpenGL ES 的开发人员可能会发现 1.0/1.1 版本的编码更快、更方便。
- 图形控制
OpenGL ES 2.0 和 3.0 API 通过使用着色器提供完全可编程的管道,从而提供更高程度的控制。通过更直接地控制图形处理管道,开发人员可以创建使用 1.0/1.1 API 很难生成的效果。
- 纹理支持
- OpenGL ES 3.0 API 对纹理压缩提供了最好的支持,因为它保证了支持透明度的 ETC2 压缩格式的可用性。 1.x 和 2.0 API 实现通常包括对 ETC1 的支持,但是这种纹理格式不支持透明度,因此您通常必须以目标设备支持的其他压缩格式提供资源。有关详细信息,请参阅纹理压缩支持。
虽然性能、兼容性、便利性、控制和其他因素可能会影响您的决定,但您应该根据您认为能为用户提供最佳体验的内容来选择 OpenGL API 版本。