Android图形编程篇--OpenGL绪论

1.1 OpenGL简介:

OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的,1.1完全兼容1.0。OpenGL ES 2.0 则是参照 OpenGL 2.0 规范定义的。简单的来说,OpenGL ES是OpenGL针对嵌入式应用的简化版,也就是android使用的标准。OpenGL ES 1.1强调api的硬件加速,OpenGL ES 2.0更强调3D能力。

1.2 OpenGL 一些概念:
渲染:是计算机根据模型创建图像的过程。最终完成了渲染的图像是由屏幕上绘制的像素组成的。
模型:根据几何图元创建的,也称为物体(object).几何图元包括点、直线和多边形等,它们是通过顶点(vertex)指定的。
像素:显示硬件可以在屏幕的最小可视元素。(在内存中,和像素有关的信息(ep:像素的颜色))组成位平面的形式。
位平面:是一块内存区域,保存了屏幕上每个像素的1个位的信息。(ep:它指定了一个特定像素的颜色中红色成分的强度)。
位平面又可以组织成帧缓冲区(framebuffer)的形式,后者保存了图像硬件为了控制屏幕上所有像素的颜色和强度所需要的全部信息。 

从应用的角度看,OpenGL是一套操作图形渲染的API。OpenGL应用通过这些API设置一系列状态并配置着色器程序,将输入的几何模型——点,线,三角形及patch通过OpenGL管线的每个阶段,最终渲染成一帧图像。OpenGL只负责渲染几何图元,不提供任何描述三维模型的功能。OpenGL独立于硬件,操作系统,窗口系统,由应用自身去使用窗口系统的功能;因此需要基于特定操作系统/窗口系统的辅助API完成外围/窗口相关的工作,例如为应用接收鼠标键盘的输入,以及将帧缓存中的图像显示到窗口中。

从实现的角度看,OpenGL是一个规范,由Khronos组织制定并维护,当前最新的是4.5版本。它详细规定了每个函数的功能及期望的执行效果等。OpenGL给出的是规范,对于细节则允许不同的实现,只要其结果遵从规格,不会使用户感觉差异即可。因此GPU制造商会权衡效率、性能、功耗等架构问题,较灵活地完成API的底层实现。一些特性则较为宽松,允许硬件自己的实现,因此这些特性在不同硬件上可能会表现出细微的差别。通常每一版新出的规范都会支持一些新特性。在新规范出来前,一些GPU厂商会开发属于自己的扩展特性,流行的新特性很可能被收入未来的规范中。

OpenGL是一个状态机,记住这一点能帮我们更好地理解它。管线中每个阶段的行为都由一系列状态控制,应用通过API设置一些选项或操作一些缓冲更改这些状态,从而操作渲染行为,例如设置图元类型为三角形时,将告诉光栅化逐次将三个顶点作为一个图元;将深度测试开启时,输出混合阶段会将深度值大于当前缓存的像素丢掉等等。

所有这些渲染相关的状态,称为OpengGL上下文(Context),从底层的角度看,上下文是在实际渲染前,驱动为硬件寄存器所做的配置。基于上下文,驱动进一步下达命令及顶点数据,GPU管线根据状态处理顶点数据。

对象则是OpenGL上下文的一个子集,把OpenGL上下文当做一个巨大结构体,则对象为该结构体的数据成员。

在应用中渲染不同的模型时,通常只需要切换部分对象而不是整个上下文。OpenGL提供了glGen*()/glBind*().类型的方法,实现对象的绑定与切换,以一个例子说明这种状态操作。假设OpenGL的上下文由结构体GL_Context表示,其中有一个viewport对象:

1.3 使用方法:

本系列博客志在分析OpenGL在Android客户端中的使用方法;对于OpenGL的C实现代码不会做过多阐述(太难了,实在不懂)Android现在支持1.X和2.X。
 android上opengs开发有两种方式,
1. 通过android framework 提供的接口开发(本系列博客主要的调用方式)
2. 通过android ndk 开发

framework提供的java接口开发方式主要是:android framework层通过两个类提供opengs es开发基础,类GLSurfaceView GLSurfaceView.Renderer接口,GLSurfaceView 是一个view,继承了surfaceview,surfaceview的一个重要用法是你可以单独开启线程在屏幕上渲染图像,而不像其他基于view的控件都属于ui线程。
GLSurfaceView 给opengls es 绘制线程提供surface,当创建一个glsurfaceview并绑定到到activity时需要注册在此surfaceview上渲染的Renderer对象, 通过调用setRenderer(Renderer) 完成注册,setRenderer调用时会创建绘制线程,此线程会根据ui事件及surface窗口的改变回调GLSurfaceView.Renderer 接口的回调方法,真正的绘制动作都在此接口的回调方法里实现,接口方法包括:

//绘制帧数据
abstract void onDrawFrame(GL10 gl)
//当surface大小改变时被调用
abstract void onSurfaceChanged(GL10 gl, int width, int height)
//当surface被创建时 调用,这里可以作初始化动作。
abstract void onSurfaceCreated(GL10 gl, EGLConfig config)

所以openggl es开发通常是实现这几个接口,然后 调用setRenderer(Renderer)把 此接口注册给GLSurfaceView。
调用setRenderer(Renderer)会把Renderer对象传给绘制线程,绘制线程操作此对象,当ui线程想和绘制线程通信时可以采用java提供的线程间通信方法,也可以用GLSurfaceView 提供的queueEvent(Runnable),因为输入事件都属于ui线程,所以如果想通过输入事件控制绘制线程queueEvent是个不错的选择。

猜你喜欢

转载自blog.csdn.net/s1120080286/article/details/86592868