Android OpenGL ES 开发
OpenGL(Open Graphics Library) 是开放图形库,是一个跨平台的图形 API。OpenGL ES(OpenGL for Embedded System)是专为移动端提供的一个子集。目前主要版本有1.0/1.1/2.0/3.0/3.1:
- 1.0:Android 1.0和更高的版本支持这个API规范
- 2.0:不兼容 OpenGL ES 1.x。Android 2.2(API 8)和更高的版本支持这个API规范
- 3.0:向下兼容 OpenGL ES 2.x。Android 4.3(API 18)及更高的版本支持这个API规范
- 3.1:向下兼容 OpenGL ES3.0/2.0。Android 5.0(API 21)和更高的版本支持这个API规范
先了解一下 OpenGl 几个相关的概念
相关概念
管线
也称渲染管线,因为 OpenGL ES 在渲染处理过程中会顺序执行一系列操作,这一系列相关的处理阶段就被称为 OpenGL ES 渲染管线。OpenGL ES 渲染过程就如流水线作业一样,这样的实现极大地提高了渲染的效率。如图就是 OpenGL ES 的管线图,学习OpenGL ES 就是学习这张图中的每一个部分。

图中阴影部分的 Vertex Shader(顶点着色器) 和 Fragment Shader(片元着色器) 是可编程管线 。
顶点
OpenGl 物体图形都由点、线、多边形组成,组成他们的关键就在于顶点数据。绘制时需要准备绘制的位置,这些位置就是顶点,顶点组合起来就是顶点坐标。
坐标系
OpenGl 使用右手坐标系,手机屏幕中心坐标系(0,0,0),左上角坐标(-1, 1, 0),依此类推。

着色器语言
着色器的编程语言是基于 C 语言开发的,被称为 GLSL(OpenGL Shading Language),和 C 语言最大的区别是它新增了许多适合图形处理的东西,比如定义了向量和矩阵两个数据类型,另外 GLSL 也对高并发进行了特殊优化。
GLSL 详细语法可见:GLSL 中文手册
顶点着色器(Vertex Shader)
顶点着色器分为输入和输出两部分,负责的功能是把输入的数据进行矩阵变换位置,计算光照公式生成逐顶点颜⾊,⽣成/变换纹理坐标。并且把位置和纹理坐标这样的参数发送到片段着色器。
顶点着色器的输入数据由下面组成:
- Attributes:使用顶点数组封装每个顶点的数据,一般用于每个顶点都各不相同的变量,如顶点位置、颜色等。
- Uniforms:顶点着色器使用的常量数据,不能被着色器修改,一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的变量,如当前光源的位置。
- Samplers:这个是可选的,一种特殊的 uniforms,表示顶点着色器使用的纹理。
- Shader program:顶点着色器的源码或可执行文件,描述了将对顶点执行的操作。

顶点着色器对于 3D 模型网格的每个顶点执行一次,确定顶点的最终位置。顶点着色器取得一个位置及相关的颜色数据作为输入属性,用一个 4x4 矩阵变换位置,并输出变换后的位置和颜色。
顶点着色器是可编程渲染管道,例如一个简单的顶点着色器:
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
}
上面例子里的 gl_Position 是顶点着色器的内建输出变量。
gl_Position: 顶点坐标
gl_PositionSize:点的大小,默认值是 1
图元装配
图元指的是点、直线和三角形。该过程还有两个重要操作:裁剪和淘汰。对不在屏幕可见的 3D 区域内的图元进行裁剪,根据图元面向前方或后方选择抛弃它们(比如物体内部的点)。
光栅化
将图元转为片段的过程称为光栅化。片段可以理解为带有深度信息的像素点。屏幕上的一个像素点可能对应多个片段。
片段着色器(Fragment Shader)
片段着色器用于对片段进行处理,例如纹理采样、颜色汇总等,将每个片段的颜色等属性计算出来并向后传输。编写片元着色器可以实现滤镜、美颜、图片处理、类似抖音的一些特效等效果。片段着色器对光栅化之后 2D 图像中的每个像素处理一次,3D 物体的表面最终显示成什么样子由片段着色器决定。

片段着色器也是可编程的,例如:
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0)
}
gl_FragColor 是片段着色器的内建输出变量,指当前片元的颜色。
GLSurfaceView
我们都知道 SurfaveView 最大的特点是可以在子线程中绘制图象,GLSurfaceView 继承自 SurfaceView,其实是对 SurfaceView 再做了一次封装,方便在 Android 中使用 OpenGL。
GLSurfaceView 的渲染被委托给渲染器在独立的渲染线程里进行,通过 setRender(Render) 设置渲染器。
HelloWorld
了解相关概念后,先动手编写个简单的 Demo 实操一下。Android 上使用 OpenGl ES 流程如下:
- 在 AndroidMenifest 中设置 OpenGL 版本:
如果应用不指定 android:glEsVersion 属性,则系统默认使用 OpenGL ES 1.0,即所有 Android 设备都支持的版本。
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
- 自定义渲染器
新建类实现 GLSurfaceView.Renderer 接口,并在三个回调方法中做相应操作。
- 在 Surface 创建时,设置设置清除后的颜色预设值
- 在 Surface 变化时,更新视口矩形宽高、窗口位置
- 在每次绘制帧时,清空颜色缓冲并置为预设颜色
class CustomRender: GLSurfaceView.Renderer {
override fun onDrawFrame(gl: GL10?) {
//绘制当前帧
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
//surface 变化时的回调,包括尺寸变化、设备屏幕方向变化等
GLES20.glViewport(0, 0, width, height);
}
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
//surface 创建时的回调
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f)
}
}
- 自定义 GLSurfaceView
新建类继承自 GLSurfaceView,并在初始化时设置渲染器
class CustomGLSurfaceView(context: Context?) : GLSurfaceView(context) {
init {
setRenderer(CustomRender())
}
}
- 展示 GLSurfaceView
将 GLSurfaceView 添加到布局
class KotlinActivity : AppCompatActivity() {
private val glSurfaceView by lazy { CustomGLSurfaceView(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(glSurfaceView)
}
}
运行之后,页面会显示蓝色背景,这是 GLSurfaceView 最简单的运用,简单到我都不好意思放效果图。但千里之行始于足下,下一次我们接着深入 GLSurfaceView 的使用,动手编写着色器来实现图形绘制。
Comming soon
Android OpenGL ES 开发的更多相关文章
- Android OpenGL ES 开发教程 从入门到精通
感谢,摘自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ...
- Android OpenGL ES 开发(三): OpenGL ES 定义形状
在上篇文章,我们能够配置好基本的Android OpenGL 使用的环境.但是如果我们不了解OpenGL ES如何定义图像的一些基本知识就使用OpenGL ES进行绘图还是有点棘手的.所以能够在Ope ...
- Android OpenGL ES 开发(N): OpenGL ES 2.0 机型兼容问题整理
在使用OpenGL ES做开发的时候,发现不是所有机型对OpenGL的代码都兼容的那么好,同样的代码在某些机型上总是会出现问题,但是在其他手机上就是好的.下面是本人总结的OpengGL 兼容问题: 一 ...
- Android OpenGL ES 开发(一): OpenGL ES 介绍
简介OpenGL ES 谈到OpenGL ES,首先我们应该先去了解一下Android的基本架构,基本架构下图: 在这里我们可以找到Libraries里面有我们目前要接触的库,即OpenGL ES. ...
- Android OpenGL ES 开发(二): OpenGL ES 环境搭建
零:环境搭建目的 为了在Android应用程序中使用OpenGL ES绘制图形,必须要为他们创建一个视图容器.其中最直接或者最常用的方式就是实现一个GLSurfaceView和一个GLSurfaceV ...
- Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL
前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍.通过之前的文章,我们基本上可以完成的基本的形状的绘制. 这是本人做的整理笔记: https://github.com/re ...
- Android OpenGL ES 开发(六): OpenGL ES 添加运动效果
在屏幕上绘制图形只是OpenGL的相当基础的特点,你也可以用其他的Android图形框架类来实现这些,包括Canvas和Drawable对象.OpenGL ES为在三维空间中移动和变换提供了额外的功能 ...
- Android OpenGL ES 开发(九): OpenGL ES 纹理贴图
一.概念 一般说来,纹理是表示物体表面的一幅或几幅二维图形,也称纹理贴图(texture).当把纹理按照特定的方式映射到物体表面上的时候,能使物体看上去更加真实.当前流行的图形系统中,纹理绘制已经成为 ...
- Android OpenGL ES 开发(四): OpenGL ES 绘制形状
在上文中,我们使用OpenGL定义了能够被绘制出来的形状了,现在我们想绘制出来它们.使用OpenGLES 2.0来绘制形状会比你想象的需要更多的代码.因为OpenGL的API提供了大量的对渲染管线的控 ...
随机推荐
- zuul1.x和gateway的区别
阻塞与非阻塞: 1.实际上是Spring mvc与Spring webflux的区别 转载:https://www.cnblogs.com/lixinjie/p/a-brother-of-spring ...
- Spark存储Parquet数据到Hive,对map、array、struct字段类型的处理
利用Spark往Hive中存储parquet数据,针对一些复杂数据类型如map.array.struct的处理遇到的问题? 为了更好的说明导致问题的原因.现象以及解决方案,首先看下述示例: -- 创建 ...
- 老猿学5G:融合计费的Nchf和Nchf‘服务化接口消息Nchf_ConvergedCharging_Create、Update、Release和Notify
☞ ░ 老猿Python博文目录░ 一.引言 在<老猿学5G扫盲贴:中国移动的5G计费架构解读>介绍了5G融合计费的服务化接口包括: CHF提供给CTF使用的Nchf接口 OCF提供给CH ...
- 老猿学5G扫盲贴:中移动的5G计费架构中Nchf'服务化接口以及CHF中的AGF
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.关于Nchf' 在中移动企标中出现了在3GPP ...
- PyQt学习随笔:QStandardItemModel使用注意事项
老猿Python博文目录 老猿Python博客地址 在使用QStandardItemModel或其派生类作为view对象的数据存储时,有如下几点需要注意: 1.如果是多行多列的数据存储,对应视图如果没 ...
- JAVA课堂作业(2019.10.14)
一. (1)代码 package class20191014; import java.util.Scanner; public class ClassHomework { public static ...
- Redis数据库简介
最近的项目需要用到Redis数据库和MySQL,恶补学习. Redis的使用手册可以看: https://redis.io/ https://www.runoob.com/redis/redis-tu ...
- 当你在浏览器输入一个网址(如http://www.taobao.com),按回车之后发生了什么?
首先你输入了一个网址并按下了回车,这个时候浏览器会根据这个URL去查找其对应的IP,具体过程如下: 首先是查找浏览器缓存,浏览器会保存一段时间你之前访问过的一些网址的DNS信息,不同浏览器保存的时常不 ...
- Jmeter(三十二) - 从入门到精通 - Jmeter Http协议录制脚本工具-Badboy5(详解教程)
1.简介 这一篇文章,宏哥主要想讲解一下,录制完脚本不是就完事了,我们有时候还需要断言,看结果是否和我们预期的结果一致.这在测试中都是很重要的.用句老话说:只看结果不看过程. 2.录制脚本 想要断言, ...
- 对 精致码农大佬 说的 Task.Run 会存在 内存泄漏 的思考
一:背景 1. 讲故事 这段时间项目延期,加班比较厉害,博客就稍微停了停,不过还是得持续的技术输出呀! 园子里最近挺热闹的,精致码农大佬分享了三篇文章: 为什么要小心使用 Task.Run [http ...