OpenGL ES
OpenGL 是一种应用程序编程接口,它是一种可以对图形硬件设备特性进行访问的软件库。
重点:OpenGL 是一种接口,既然是接口,那么就必然要有实现。
事实上,它的实现是由显示设备厂商提供的,而且依赖于厂商提供的硬件设备。
OpenGL 常用于 CAD、虚拟实境、科学可视化程序和电子游戏开发。
在 Android 上使用的是 OpenGL ES,它是 OpenGL 的子集,在 OpenGL 的基础之上裁剪掉了一些非必要的部分,主要是针对手机、PAD 和游戏主机等嵌入式设备设计的。
在 Android 上开发 OpenGL 既可以使用 Java 也可以使用 C ,话不多说,撸起袖子就是干!
渲染管线
渲染管线也称为渲染流水线
或像素流水线
或像素管线
,是GPU处理图形信号的相互独立的并行处理单元。
这张图展示了我们调用OpenGL的drawXXX()
方法后执行的流程,我们传递的顶点首先会经过顶点着色器vertex shader的处理,一般会在里面做顶点变换相关的逻辑,然后进行图元装配,再经过几何着色器geometry shader,这个着色器相对来说使用得少一些,可暂时先忽略,然后接下来就是光栅化,所谓光栅化就是把我们要渲染的图像打碎成屏幕上的像素,因为最终要显示到屏幕上,就必须将图形对应到像素上,光栅化完成后,我们就有了要渲染的图形对应的像素,此时像素还没有颜色,需要我们填上颜色,这时就到达到了片段着色器fragment shader,在fragment shader中我们通常进行颜色的计算,确定对应的像素显示什么颜色,fragment shader将在下篇文章中介绍。
在整个渲染管线中,vertex shader、geometry shader和fragment shader这三部分是可编程分部,可编写shader代码实现相应的功能,我们目前重点关注vertex shader和fragment shader。
这里特别注意一点,我们的shader代码并不是像普通程序那样,一次性输入所有顶点,然后再输出,例如对于vertex shader,我们传递了3个顶点,并不是3个顶点一起执行一次vertex shader,而是分别对这3个顶点执行一次,也就是执行了3次。对于fragment shader也是类似的,并不是执行一次为所有的像素填充颜色,而是对每个像素都执行一次。这个特点有时让初学者感到困惑。
坐标
下面是纹理坐标系统和位置坐标系统之间的对应关系:
内存拷贝
当我们定义好顶点坐标,那么就可以将顶点坐标传入渲染管线,进行一些列操作。但是我们如何传给Opengl呢?
OpenGL 的实现是由显示设备厂商提供的,它作为本地系统库直接运行在硬件上。而我们定义的顶点 Java 代码是运行在虚拟机上的,这就涉及到了如何把 Java 层的内存复制到 Native 层了。
一种方法是直接使用JNI
开发,直接调用本地系统库,也就是用 C++
来开发 OpenGL,这种实现肯定要学会的。
另一种方法就是在 Java 层把内存块复制到 Native 层。
使用ByteBuffer.allocateDirect()
方法就可以分配一块 Native 内存,这块内存不会被 Java 的垃圾回收器管理。
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * (Float.SIZE / 8));
vbb.order(ByteOrder.nativeOrder()); //设置字节顺序
FloatBuffer vertexBuf = vbb.asFloatBuffer(); //转换为Float型缓冲
vertexBuf.put(vertices); //向缓冲区中放入顶点坐标数据
vertexBuf.position(0); //设置缓冲区起始位置
在allocateDirect
方法分配了内存并指定了大小之后,下一步就是告诉 ByteBuffer 按照本地字节序
组织它的内容。本地字节序是指,当一个值占用多个字节时,比如 32 位整型数,字节按照从最重要位到最不重要位或者相反顺序排列。
接下来asFloatBuffer
方法可以得到一个反映底层字节的 FloatBuffer 类实例,避免直接操作单独的字节,而是使用浮点数。
最后,通过put
方法就可以把数据从 Java 层内存复制到 Native 层了,当进程结束时,这块内存就会被释放掉。
顶点着色器(Vertex Shader)
主要负责描绘图形,也就是根据顶点坐标,建立图形模型。
根据上图的渲染管线,顶点着色器到片段着色器之间,还要经过组装图元
和光栅化图元
。
片段着色器 (Fragment Shader)
片段着色器的主要目的就是告诉 GPU 每个片段的最终颜色应该是什么。
光栅化技术
移动设备的显示屏由成百上千个小的、独立的部件组成,他们称为像素
。每个像素通常由三个单独的子组件构成,它们发出红色、绿色和蓝色的光,因为每个像素都非常小,人的眼睛会把红色、绿色和蓝色的光混合在一起,从而创造出巨量的颜色范围