Android控制台程序利用GPU处理图像

1. 引言

最近工作比较忙,忙了2个多月,有一段时间没有写笔记了. 这段时间的工作内容接触到利用GPU处理图像,而我本身对数字图像处理一直比较感兴趣,顾借这次机会学习一些数字图像处理相关的技术.

2. 简单背景介绍

数字图像一般像素数据较大,CPU设计的目的是通用计算,更擅长的是逻辑控制. 目前智能设备中为了更流畅的显示,一般都配有GPU, GPU的运算单元非常多,且数字图像一般都是逐个逐个像素处理,天然能利用GPU的并发能力. Android平台,目前能利用GPU计算的开源库有OpenAL, opengles 2.0等. android平台使用openCL不是非常方便, 而利用opengles 2.0的可编程管线就方便多了. 我们可以自己写着色器(shader)来处理图像.当然,也可以把其他可以并行处理的任务伪装成图像处理,利用GPU加速.

3. 编写android控制台程序

我将运行在android系统上,但不是运行在Dailvk虚拟机上,不调用任何android framework api的无窗口的本地程序称为android控制台程序 (它和linux控制台程序类似, android 的 C 运行时库是bionic, 而linux是 glibc.它和linux控制台应用程序最大的区别是Makefile写法和格式不一样). 有时候,从运行效率,调试和平台兼容等方面考虑,控制台程序则更适合某些场景. Android控制台程序需要把Android.mk文件的最后一行改成

include $(BUILD_EXECUTABLE)

而我们平时编译成动态库的Android.mk是这样写的

include $(BUILD_SHARED_LIBRARY)

4. 开始使用opengl es 2.0

.c文件的main函数写好了,NDK中也有GLES2相关的头文件,一开始我满怀希望的开始调用opengles 2.0 的接口.发现运行结果没有啥效果.我猜测该手机是不是不支持opengles 2.0, 可能只支持opengl 1.0. 无奈,只好看看获取opengl 的版本,打印看看

const GLubyte* version = glGetString(GL_VERSION);
if (NULL != version) {
    Log("%s\n", version);
}
else {
    Log("version info: NULL \n");
}

发现每次取得都是NULL.感觉opengl接口都没有调用成功.

5. EGL闪亮登场

之所以不能获取opengles的版本信息,是因为opengles 没有初始化,也就是没有准备opengl运行环境.opengl是跨平台的3D图形接口,与具体的操作系统显示窗口无关,但是通过opengl绘制的图像,需要保存在存储空间 (注意:不一定是内存,也可能是显存) 或者在具体的操作系统窗口显示.这时需要EGL实现跨平台. EGL 是 OpenGL ES 和底层 Native 平台视窗系统之间的接口。EGL是有统一规范的. 只有初始化EGL, 为opengl创建存储空间和状态机环境,opengl才能运行. 初始化EGL的步骤一般是固定的:

1. 关联系统物理屏幕

该方法是和系统平台相关的.
相关函数 eglGetDisplay()

2. 初始化EGL,

该操作会进行一些内部初始化工作,并传回EGL的版本号.
相关函数 eglInitialize()

3. 选择配置 (Config),

所谓Config就是EGL的相关参数,Config有很多的Attribute, 这些 Attribute决定opengl的格式和能力.
相关函数
eglGetConfigs()
eglGetConfigAttrib()
eglChooseConfig()

4. 创建Surface

surface就是一块存储空间,供opengl存储处理后的数据.类型可以是在线渲染用于显示的framebuffer, 也可是内存的中的位图,也可以是用于离线渲染的显存.
相关函数: 

    eglCreateWindowSurface()     
    eglCreatePbufferSurface() 
    eglCreatePixmapSurface()
5. 创建Context

opengl的渲染管线从程序的角度来看就是一个状态机, context就是代表opengl的状态机.
相关函数 eglCreateContext()

6. 绑定 Surface和Context

相关函数
eglMakeCurrent()

至此EGL初始化完成, opengles运行环境准备好了.
这里只提到了相关的函数,具体参数和调用方法请参考相关文档.
其中选择配置很重要,不然可能会失败,我在这里花了很多时间.

6. 准备着色程序(shader)

处理图像的核心就是shader. shader成功编译链接后,会被GPU执行. shader主要分顶点shader和像素shader.关于shader的更多知识我需要持续学习.这里我只简单的记录如何创建shader.

1. 创建shader  

相关函数glCreateShaderObject() , glShaderSource()

2. 编译shader

相关函数glCompileShader()

3. 创建程序 (program)

相关函数glCreateProgram()

4. 链接program  

相关 glAttachShader() , glLinkProgram()

5. 应用shader

相关函数 glUseProgram()

7. 与shader变量交互

opengles提供了接口与shader中attribute 变量和uniform变量进行交互.
这些方法有: glGetAttribLocation() , glGetUniformLocation(), glVertexAttribPointer(), glUniform()等等函数.

8. 尾声

到这来整个流程都完成了,剩下的核心就是写shader处理图像了.opengles 2.0 和 shader 我也是学习阶段, 我在github上开了一个仓库学习shader,欢迎感兴趣的朋友一起讨论,互相学习.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值