您的位置:首页 > 运维架构

OpenGL ES

2016-04-28 14:57 232 查看
原文地址:http://developer.android.com/intl/zh-cn/guide/topics/graphics/opengl.html

OpenGl 支持 2D和3D图形开源库。

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 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包

一旦你建立了一个容器视图使用OpenGL ES 
GLSurfaceView 
和 
GLSurfaceView.Renderer 
,你就可以开始
调用OpenGL api使用以下类:
OpenGL ES 1.0/1.1 API包
android.opengl 
——这个包提供了一个静态界面OpenGL
ES 类和更好的性能比1.0/1.1
javax.microedition.khronos 
包 接口。
GLES10

GLES10Ext

GLES11

GLES11Ext


javax.microedition.khronos.opengles 
这个包提供了标准
实现OpenGL ES的1.0/1.1。
GL10

GL10Ext

GL11

GL11Ext

GL11ExtensionPack


OpenGL ES 2.0 API类
android.opengl.GLES20 
这个包提供了
接口OpenGL ES 2.0和可以从Android 2.2(API级别8)。

OpenGL ES 3.0/3.1 API包
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需求

如果您的应用程序使用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" />

添加这个声明会导致谷歌应用市场限制 安装在设备不支持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假定一个正方形,统一的坐标系统,在默认情况下,幸福 吸引这些坐标到你通常方阵屏幕好像是完全平方。



图1所示。 默认的OpenGL坐标系(左)映射到一个典型的Android 设备的屏幕(右)。

上面的插图显示了一个OpenGL的统一坐标系统假设框架上 离开了,这些坐标如何映射到一个典型的设备在横向屏幕 在右边。 为了解决这个问题,您可以应用OpenGL投影模式和相机视图 坐标变换你的图形对象在任何显示正确的比例。

为了应用投影和相机视图,您创建一个投影矩阵和一个相机视图 矩阵并将它们应用于OpenGL渲染管道。 投影矩阵重新计算 你的坐标图形,使他们正确地映射到Android设备的屏幕。 相机视图 矩阵创建一个转换,它显示对象从一个特定的位置。


投影和OpenGL ES 1.0相机视图

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);
    ...
}



投影和OpenGL ES 2.0和更高版本的相机视图

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)有一个正面 和背面。 你怎么知道哪面是正面和背面? 好问题。 的 答案与绕组,或者你的方向定义的点的形状。



图1所示。 说明一个坐标转化为一个列表 逆时针画秩序。

在这个例子中,三角形的点定义在一个订单,这样绘制的 逆时针方向。 这些坐标的顺序绘制定义了绕组 方向的形状。 默认情况下,在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版本和设备兼容性

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功能)支持的吗 设备。 一些常见的支持纹理压缩格式如下:
ATITC(ATC) - ATI纹理压缩(ATITC或ATC)上可用 各种各样的设备和支持固定汇率压缩RGB纹理有或没有 一个alpha通道。 这种格式可能由几个OpenGL扩展名,例如:
GL_AMD_compressed_ATC_texture

GL_ATI_texture_compression_atitc


PVRTC ——PowerVR纹理压缩(PVRTC)可以在一个宽 各种各样的设备和支持2比特和4比特每像素纹理有或没有一个alpha通道。 这种格式是由以下OpenGL扩展名:
GL_IMG_texture_compression_pvrtc


S3TC(DXT n /
DXTC) 
- S3纹理压缩(S3TC)有几个 格式变化(DXT1 DXT5)和更广泛使用。 支持RGB格式的纹理 4比特α或8位alpha通道。 这些格式由以下OpenGL扩展 名称:
GL_EXT_texture_compression_s3tc

有些设备只支持DXT1格式变化,这是由有限的支持 OpenGL扩展名:
GL_EXT_texture_compression_dxt1


3直流 - 3 dc纹理压缩(3 dc)是一种广泛使用的格式 支持RGB纹理alpha通道。 这种格式是由以下OpenGL 扩展名:
GL_AMD_compressed_3DC_texture


警告: 这些纹理压缩格式 不 支持 在所有设备。 支持这些格式的大小变化和设备制造商。 为 如何确定纹理压缩格式是在一个特定的设备,看
下一节。

注意: 一旦你决定哪些纹理压缩格式 应用程序支持,确保你在清单使用声明它们 < supports-gl-texture > 。 使用这个宣言使过滤由外部服务,如谷歌玩,所以 应用程序安装在您的应用程序需要设备支持的格式。 有关详细信息,请参见 OpenGL清单声明 


确定OpenGL扩展

的实现OpenGL随Android设备的扩展OpenGL ES API 支持。 这些扩展包括纹理按压,但通常也包括其他 对OpenGL的特性集的扩展。

来确定纹理压缩格式,和其他OpenGL扩展,支持在一个 特定的设备:
目标设备上运行下面的代码来确定纹理压缩 支持格式:
String extensions = javax.microedition.khronos.opengles.GL10.glGetString(
        GL10.GL_EXTENSIONS);


警告: 这个调用的结果 随设备模型! 你 必须运行此呼吁几个目标设备来确定一般压缩类型是什么 支持。

评估该方法的输出来确定OpenGL扩展的支持 设备。


Android扩展包(AEP)

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版本

有几个版本的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。 你可以以两种方式之一:
尝试创建更高级的OpenGL ES上下文( 
EGLContext 
),
检查结果。
创建一个minimum-supported OpenGL ES上下文和检查版本的值。

下面的示例代码演示了如何通过创建检查可用的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 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开发:
性能 ——一般而言,OpenGL ES 2.0和3.0提供更快的图形 性能比ES 1.0/1.1 api。 然而,性能差异取决于 Android设备OpenGL应用程序上运行,由于硬件的差异 制造商的OpenGL ES图形管道的实现。
设备的兼容性 ——开发人员应该考虑类型的设备, 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