Android OpenGL ES向导学习笔记(扫盲专用)

Android 目前支持下面几个版本的OpenGL ES API :

OpenGL ES 1.0 和 1.1 :Android 1.0和更高的版本支持这个API规范。

OpenGL ES 2.0 : Android 2.2(API 8)和更高的版本支持这个API规范。

OpenGL ES 3.0 : Android 4.3(API 18)和更高的版本支持这个API规范。

OpenGL ES 3.1 :  Android 5.0(API 21)和更高的版本支持这个API规范。

支持OpenGL ES 3.0的API需要实现设备生产厂家提供的图形管道,所以一个Android4.3或者更高版本的设备可能并不支持OpenGL ES 3.0.

Android在framework API和NDK都提供了对OpenGL的支持

OpenGL ES包:

1、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

2 . OpenGL ES 2.0的API类

    • android.opengl.GLES20 -- 这个包提供了OpenGLES 2.0的接口,在Android2.2及以上版本可以使用。

3. OpenGL ES 3.0/3/1的API包

android.opengl -- 这个包提供了OpenGL ES 3.0/3.1的类接口。

    • GLES30
    • GLES31
    • GLES31Ext (Android Extension Pack)

为绘制对象映射坐标(Mapping Coordinates for Drawn Objects)

在Android设备上面展示图形的一个基本问题是屏幕的尺寸和形状都不同,OpenGL假设默认有一个统一的正方形坐标系,并将这些坐标绘制到通常不是正方形的屏幕上面,就像它是一个完美的正方形。

图1 默认的OpenGL坐标系统(左) 映射到通常的Android设备屏幕(右)

上面的图片现实了OpenGL帧假设的统一坐标系统(左),和这些坐标是怎么映射到一个通常的设备横屏上的(右)。为了解决这个问题,你可以应用OpenGL投影模式和相机视图来变换坐标,使你的图形对象在任何屏幕上面都有正确的比例。

为了应用投影和相机视图,创建一个投影矩阵和相机视图矩阵,并将它们应用到OpenGL渲染管道,投影矩阵重新计算图形的坐标,使它们在设备屏幕上面正确映射。相机视图矩阵从一个特定的视图位置给渲染对象创建一个变换。

OpenGL ES 1.0的投影和相机视图

在ES 1.0 API,通过为投影和相机视图创建相应的矩阵,然后把它们添加到OpenGL环境中。

1.投影矩阵 - 使用设备屏幕的几何参数创建投影矩阵,来重新计算对象的坐标,使它们以正确的比例绘制。下面的示例代码展示了在onSurfaceChanged()方法中以屏幕的宽高比创建投影矩阵,并把它应用到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

}

2.相机变换矩阵 - 当你使用投影矩阵适应了坐标系统后,你必须应用一个相机视图。下面的代码展示了使用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里面,应用投影和相机视图时,首先要向图形对象的顶点着色器添加一个矩阵成员对象,当矩阵对象添加后,就可以向对象生成和应用投影和相机视图矩阵。

1.  向顶点着色器中添加矩阵 - 为view的投影矩阵创建一个变量,然后将它与着色器的position相乘。下面的着色器代码,包含的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";

注意:上面的示例在顶点着色器中定义了一个矩阵变换成员,你可以给这个矩阵应用一个投影和相机视图的结合矩阵。根据你的需求,可能会需要定义分开的投影矩阵和相机视图矩阵成员,以方便分开自由的改变它们。

2.  访问着色器矩阵 - 当你在顶点着色器中创建了hook之后,你可以访问这个变量来应用投影和相机视图矩阵。下面的代码显示了如何访问顶点着色器中定义的矩阵变量:

public void onSurfaceCreated(GL10 unused, EGLConfig config) {

...

muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

...

}

3.   创建投影和相机视图矩阵 - 生成可应用到图形对象的投影和视图矩阵。下面的代码根据设备屏幕的宽高比创建了投影矩阵和相机视图矩阵。

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

}

4.  应用投影和相机视图矩阵 - 应用投影和相机视图变换,将两个矩阵相乘,然后将它们设置到顶点着色器。下面的代码显示了如何将矩阵应用到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 1.0/1.1API与2.0或者更高的版本是明显不同的,1.x版本有更多方便的方法和固定的管线,而2.0和3.0API通过OpenGL着色器提供了更多对管线的直接控制。你应该仔细考虑绘制图形的需求,并且选择最适合应用的api。

OpenGL ES 3.0 API比2.0提供跟多的特性和更好的性能,同时也向下兼容。这意味着你可以将应用的OpenGL ES的版本设置为2.0,并选择性地包含一些有效的3.0图形特性。

纹理压缩支持

纹理压缩可以通过减少内存来显著地提高OpenGL的性能,使内存使用的效率更高。Android framework提供了ETC1压缩格式作为标准特性,包含了ETC1Util工具类和etctool压缩工具(位于Android SDK下的<sdk>/tools/目录)。

大部分的Android设备都支持ETC1格式,但是不保证它一定支持。检查设备是否支持ETC1格式,调用 ETC1Util.isETC1Supported()方法。ETC1纹理压缩格式不支持有透明度的纹理(alpha通道),如果应用需要有透明度的纹理,你应该选择目标设备支持的其他纹理压缩格式。

当使用OpenGL ES3.0时,ETC2/EAC纹理压缩格式是确保可用的,这种纹理格式有优秀的压缩比率,高质量的视觉效果,并且也支持透明度。

除了ETC格式,Android设备支持很多其他格式的纹理压缩,根据GPU芯片和OpenGL实现的不同略有差异。你应该调查目标设备所支持的压缩格式,然后再确定应用支持哪些压缩格式。为了确定设备支持哪些纹理格式,你必须查询设备,检查OpenGL的扩展名,它们标记了哪些纹理压缩格式可以被支持。一些常见的纹理压缩格式有以下几种:

ATITC (ATC) - ATI纹理压缩在许多设备上面都支持,它支持RGB纹理压缩但不包含alpha通道,一些OpenGL扩展名可以代表这种格式,比如:

GL_AMD_compressed_ATC_texture

GL_ATI_texture_compression_atitc

PVRTC-PVRTC纹理压缩在许多设备上面都支持,支持每个像素2位或者4位的纹理,包含或者不包含alpha通道都可以。下面的OpenGL扩展名可以代表这种格式,比如:

GL_IMG_texture_compression_pvrtc

S3TC (DXTn/DXTC)-S3有一些格式变化(从DXT1到DXT5),使用并不是很广泛。它支持包含4位或者8位alpha通道的RGB纹理。下面的OpenGL扩展名可以代表这种格式,比如:

GL_OES_texture_compression_S3TC

GL_EXT_texture_compression_s3tc

GL_EXT_texture_compression_dxt1

GL_EXT_texture_compression_dxt3

GL_EXT_texture_compression_dxt5

3DC - 3DC纹理压缩是比较少使用的支持包含alpha通道的RGB纹理,下面的OpenGL扩展名可以代表这种格式:

GL_AMD_compressed_3DC_texture

这些纹理压缩格式并不是在所有的设备上面都支持,不同的制造商和设备支持的格式不同,一旦你决定应用哪种纹理压缩格式,一定要在manifest文件中使用 <supports-gl-texture> 进行声明,使用这个声明可以被Google Play过滤掉不支持这些格式的设备。

确定OpenGL扩展

OpenGL实现根据OpenGL ES API所支持的扩展而不同,这些扩展包含了纹理压缩,但通常还包括其他OpenGL功能集的扩展。

通过下面方法可以确定特定的一个设备上面支持哪些纹理压缩格式和OpenGL扩展:

1.在目标设备上面执行下面的代码来确定设备支持哪些纹理压缩格式,不同的机型上面结果不一样,所以你应该在多个机型上面运行这个代码,来确定哪些压缩格式是被广泛支持的:

String extensions = javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);

2.查看这个方法的输出,来确定设备支持哪些OpenGL扩展

Android扩展包(AEP)

AEP确保了应用支持标准化的OpenGL扩展集,它超出了OpenGL 3.1规范描述的核心集,将这些扩展打包促进了不同设备上面功能的一致,同时允许开发者充分利用手机GPU设备的最新功能。

AEP还提高了对图像、着色器存储缓存和片元着色器原子计数器的支持。

app使用AEP时,比如在manifest里进行声明,另外,平台版本必须支持它

<uses feature android:name="android.hardware.opengles.aep"   android:required="true" />

使用 hasSystemFeature(String)方法来验证是否支持AEP,传递FEATURE_OPENGLES_EXTENSION_PACK作为参数:

boolean deviceSupportsAEP = getPackageManager().hasSystemFeature (PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);

时间: 2024-10-10 09:38:16

Android OpenGL ES向导学习笔记(扫盲专用)的相关文章

Android OpenGL ES零基础系列(三):OpenGL ES的渲染管道及VertexShader与FragmentShader

前言 在前2篇文章中,我们都说到着色器,且在第二篇中正式说到,这着色器只能用在OpenGL ES2.x等可编程管道里面,而在OpenGL ES1.x是不能用的.但我们一直没有说这是为什么,两者有什么区别.那这篇我们就一起来学习下OpenGL ES中的渲染管道. 正文 管道,英文名叫Pipeline,相信用过FaceBook图片加载库的同学对这个管道并不陌生,因为SimpleImageDrawee里面也是用的管道来对图片进行的一个处理.由于其底层也是C,因此我可以大胆的猜想,FaceBook图片加

Android OpenGL ES零基础系列(一):理解GLSurfaceView,GLSurfaceView.Render的基本用法

转载请注明出处 前言 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

Android OpenGL ES 画球体

最近因为兴趣所向,开始学习OpenGL绘图.本文以"画球体"为点,小结一下最近所学. > 初识OpenGL ES 接触OpenGL是从Android开始的.众所周知,Android View 是线程不安全的,于是只允许在主线程中对View进行操作.然而假如我们需要实现复杂的界面,特别是开发游戏,在主线程中画大量图像,会耗费比较长的时间,使得主线程没能及时响应用户输入,甚至出现ANR.于是Android提供了一个 SurfaceView类,通过双缓冲机制(两块画布?三块画布?),允

Android OpenGL ES(十二):三维坐标系及坐标变换初步 .

OpenGL ES图形库最终的结果是在二维平面上显示3D物体(常称作模型Model)这是因为目前的打部分显示器还只能显示二维图形.但我们在构造3D模型时必须要有空间现象能力,所有对模型的描述还是使用三维坐标.也就是使用3D建模,而有OpenGL ES库来完成从3D模型到二维屏幕上的显示. 这个过程可以分成三个部分: 坐标变换,坐标变换通过使用变换矩阵来描述,因此学习3D绘图需要了解一些空间几何,矩阵运算的知识.三维坐标通常使用齐次坐标来定义.变换矩阵操作可以分为视角(Viewing),模型(Mo

Android OpenGL ES

1.Android OpenGL ES 简明开发教程3D 坐标变换: http://www.linuxidc.com/Linux/2011-10/45756p4.htm

[工作记录] Android OpenGL ES: non-square texture - continue

previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found that it is the mipmap of a non-square texture that cause the black texture problem: http://stackoverflow.com/questions/5052762/using-mipmaps-results-

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

[工作记录] Android OpenGL ES 2.0: square texture not supported on some device

npot texture: non-power-of-two texture.rectangle texture: non-square (height != wdith) 在测试Samsumg Galaxy S4的时候, 发现rectangle texture支持不好, 虽然创建成功, 但是绘制有问题. 不同的模块出现类似的情况: 纹理采样出的颜色是(0,0,0,1). 在排除了所有可能的runtime问题以后, 尝试性改了纹理格式无果, 又尝试性的改了下尺寸, 竟然好了. 我擦... 而Ga

[转载]Android Bitmap和Canvas学习笔记

http://blog.chinaunix.net/uid-20771867-id-3053339.html [转载]Android Bitmap和Canvas学习笔记,布布扣,bubuko.com