导航

Golang 开发移动应用的OpenGL(Android为例)的渲染管线

Posted on 2016-02-03 10:26  蝈蝈俊  阅读(1888)  评论(0编辑  收藏  举报

golang.org/x/mobile/gl 实现的是 OpenGL ES 2 的封装。

参考:https://godoc.org/golang.org/x/mobile/gl 

OpenGL ES(OpenGL for Embedded Systems)是OpenGL三维图形API的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。OpenGL ES 1.0针对固定管线硬件的,OpenGL ES 2.0针对可编程管线硬件,可以认为完全是两套API。最新3.0版本也在Android4.3得到了支持,从源码上看完全扩展自2.0。

OpenGL负责把三维空间中的对象通过投影、光栅化转换为二维图像,然后呈现到屏幕上。

管线这个术语描述了OpenGL渲染的整个过程。openGL采用cs模型:c是cpu,s是GPU,c给s的输入是vertex信息和Texture信息,s的输出是显示器上显示的图像。

参考: http://blog.csdn.net/myarrow/article/details/7692044

image

 

图形渲染管线(Pipeline)

渲染管线也称为渲染流水线,是显示芯片内部处理图形信号相互独立的的并行处理单元。大意就是在GPU中经过一系列的处理后生成显示在屏幕上的画面。OpenGL ES2.0与1.0最大的区别就是引入了可编程渲染管线,其中的顶点着色器和片元着色器代替了以前的变换,光照,纹理,颜色求和等,需要自己编程实现,大大提升灵活性。

顾名思义

  • 顶点着色器处理多边形的顶点,
  • 片元着色器则处理多边形内每个片元,类似于像素点。

着色器中使用的是着色语言GLSL,具有跨平台的特性,虽然OpenGL与OpenGL ES的着色语言有一点区别,但android,ios和web还是可以通用的。

 

参考:

http://www.zhouchengjian517.com/opengl-es2.0-for-android/

在OpenGL中任何事物都在3D空间中,但是屏幕和窗口是一个2D像素阵列,所以OpenGL的大部分工作都是关于如何把3D坐标转变为适应你屏幕的2D像素。3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(Pipeline,大多译为管线,实际上指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程)管理的。图形渲染管线可以被划分为两个主要部分:

  • 第一个部分把你的3D坐标转换为2D坐标,
  • 第二部分是把2D坐标转变为实际的有颜色的像素。

图形渲染管线接收一组3D坐标,然后把它们转变为你屏幕上的有色2D像素。图形渲染管线可以被划分为几个阶段,每个阶段需要把前一个阶段的输出作为输入。所有这些阶段都是高度专门化的(它们有一个特定的函数),它们能简单地并行执行。由于它们的并行执行特性,当今大多数显卡都有成千上万的小处理核心,在GPU上为每一个(渲染管线)阶段运行各自的小程序,从而在图形渲染管线中快速处理你的数据。这些小程序叫做 着色器(Shader)。

有些着色器允许开发者自己配置,我们可以用自己写的着色器替换默认的。这样我们就可以更细致地控制图形渲染管线中的特定部分了,因为它们运行在GPU上,所以它们会节约宝贵的CPU时间。OpenGL着色器是用OpenGL着色器语言(OpenGL Shading Language, GLSL)写成的。

在下面,你会看到一个图形渲染管线的每个阶段的抽象表达。要注意蓝色部分代表的是我们可以自定义的着色器。

image

如你所见,图形渲染管线包含很多部分,每个都是将你的顶点数据转变为最后渲染出来的像素这个大过程中的一个特定阶段。我们会概括性地解释渲染管线的每个部分,从而使你对图形渲染管线的工作方式有个大概了解。

 

顶点着色器(Vertex Shader)


我们以数组的形式传递3个3D坐标作为图形渲染管线的输入,它用来表示一个三角形,这个数组叫做顶点数据(Vertex Data);这里顶点数据是一些顶点的集合。一个顶点是一个3D坐标的集合(也就是x、y、z数据)。而顶点数据是用顶点属性(Vertex Attributes)表示的,它可以包含任何我们希望用的数据,但是简单起见,我们还是假定每个顶点只由一个3D位置和几个颜色值组成的吧。

图形渲染管线的第一个部分是顶点着色器(Vertex Shader),它把一个单独的顶点作为输入。顶点着色器主要的目的是把3D坐标转为另一种3D坐标,同时顶点着色器允许我们对顶点属性进行一些基本处理。

为了让OpenGL知道我们的坐标和颜色值构成的到底是什么,OpenGL需要你去提示你希望这些数据所表示的是什么类型。我们是希望把这些数据渲染成一系列的点?一系列的三角形?还是仅仅是一个长长的线?做出的这些提示叫做基本图形(Primitives),任何一个绘制命令的调用都必须把基本图形类型传递给OpenGL。这是其中的几个:GL_POINTS、GL_TRIANGLES、GL_LINE_STRIP。

基本图形装配(Primitive Assembly)阶段,图上叫 图元装配

基本图形装配(Primitive Assembly)阶段把顶点着色器的表示为基本图形的所有顶点作为输入(如果选择的是GL_POINTS,那么就是一个单独顶点),把所有点组装为特定的基本图形的形状;本节例子是一个三角形。

 

几何着色器(Geometry Shader)

基本图形装配阶段的输出会传递给几何着色器(Geometry Shader)。几何着色器把基本图形形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其他的)基本图形来生成其他形状。例子中,它生成了另一个三角形。

细分着色器(Tessellation Shaders)

细分着色器(Tessellation Shaders)拥有把给定基本图形细分为更多小基本图形的能力。这样我们就能在物体更接近玩家的时候通过创建更多的三角形的方式创建出更加平滑的视觉效果。

光栅化(Rasterization也译为像素化)阶段

细分着色器的输出会进入光栅化(Rasterization也译为像素化)阶段,这里它会把基本图形映射为屏幕上相应的像素,生成供片段着色器(Fragment Shader)使用的片段(Fragment)。在片段着色器运行之前,会执行裁切(Clipping)。裁切会丢弃超出你的视图以外的那些像素,来提升执行效率。

片段着色器(FRAGMENT SHADER)

片段着色器的主要目的是计算一个像素的最终颜色,这也是OpenGL高级效果产生的地方。通常,片段着色器包含用来计算像素最终颜色的3D场景的一些数据(比如光照、阴影、光的颜色等等)。

alpha测试混合(Blending)阶段

在所有相应颜色值确定以后,最终它会传到另一个阶段,我们叫做alpha测试混合(Blending)阶段。这个阶段检测像素的相应的深度(和Stencil)值,使用这些,来检查这个像素是否在另一个物体的前面或后面,如此做到相应取舍。这个阶段也会检查alpha值(alpha值是一个物体的透明度值)和物体之间的混合(Blend)。所以,即使在片段着色器中计算出来了一个像素所输出的颜色,最后的像素颜色在渲染多个三角形的时候也可能完全不同。

小结

正如你所见的那样,图形渲染管线非常复杂,它包含很多要配置的部分。然而,对于大多数场合,我们必须做的只是顶点和片段着色器。几何着色器和细分着色器是可选的,通常使用默认的着色器就行了。

在现代OpenGL中,我们必须定义至少一个顶点着色器和一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。出于这个原因,开始学习现代OpenGL的时候非常困难,因为在你能够渲染自己的第一个三角形之前需要一大堆知识。

以上内容参考:

http://learnopengl-cn.readthedocs.org/zh/latest/01%20Getting%20started/04%20Hello%20Triangle/#pipeline

 

下面几幅图也可以看到这个管道流程。

image

图来自: https://segmentfault.com/a/1190000004404224

image

图来自: http://blog.csdn.net/iispring/article/details/7649628

 

image

image

 

参考资料:

OpenGL ES2.0 for Android
http://www.zhouchengjian517.com/opengl-es2.0-for-android/#tocAnchor-1-1