1.为什么要不停地清空屏幕?
最新的GPU以不同的方式工作,使用特殊的渲染技术,如果屏幕是干净的,能工作得更快.
通过让GPU清空屏幕,可以节省拷贝浪费的时间.
2.GLSurfaceView和TextureView对比.
GLSurfaceView在幕后,实际上创建了一个窗口(Window),并在视图层次(View Hierachy)上穿了个"洞",让底层的OpenGL surface 显示出来.
但是GLSurfaceView与常规视图view不同,它没有动画或者变形特效,因为它是窗口(window)的一部分.
TextureView(纹理视图),从Android4.0开始,它可以渲染OpenGL而不用创建单独的窗口或打洞了,这就意味着,这个视图像一个常规窗口一样,可以被操作,且有动画和变形特效.
但是,TextureView类没有内置OpenGL初始化操作,要想使用TextrueView,一种方法是执行自定义的OpenGL初始化,并在TextureView上运行;
另外一种方法是把GLSurfaceView的源代码拿出来,把他适配到TextureView上.
3.GLSurfaceView在后台线程中渲染!
GLSurfaceView会在一个单独的线程中调用渲染器的方法.默认情况下,GLSurfaceView会以显示设备的刷新频率不断地渲染,当然,它也可以配置为按请求渲染,只需要用GLSurfaceView.RENDERMODE_WHEN_DIRTY作为参数调用GLSurfaceView.setRenderMode()即可.
后台线程和主UI线程之间的通信方法如下:在主线程中的GLSurfaceView实例可以调用queueEvent()方法传递一个Runnable给后台渲染线程,渲染线程可以调用Activity的runOnUIThread()来传递事件(event)给主线程.
4.定义顶点时 三角形的卷曲顺序
当我们定义三角形的时候,我们总是以逆时针的顺序排列顶点;这称为卷曲顺序(winding order).
因为在任何地方都使用这种一致的卷曲顺序,可以优化性能:
使用卷曲顺序可以指出一个三角形属于任何给定物体的前面或者后面,OpenGL可以忽略那些无论如何都无法被看到的后面的三角形.
** 无论何时,如果我们想表示一个OpenGL中的物体,都要考虑如何用点,直线及三角形把它组合出来 **
5.本地环境工作时,它并不期望内存块像GC一样,会被移来移去或者被自动释放.
OpenGL作为本地系统库直接运行在硬件上;没有虚拟机,也没有垃圾回收或内存压缩.
6.Android代码运行在虚拟机内部,与OpenGL通信有两种技术.
a.使用JNI,调用android.opengl.GLES20包里的方法时就是使用JNI调用本地系统库的.
b.改变内存分配的方式,java有一个特殊的类的集合,它们可以分配本地内存块,并且把java的数据复制到本地内存. 本地内存可以被本地环境存取,而不受垃圾回收器的管控.
7.字节序(Endianness)
字节序是描述一个硬件架构是如何组织位bit和字节byte的方式,它们在底层组成一个数字.
现实中,最常见的就是多字节数,既可以把它们按大头序(bit endian order) 排列,即把最重要的字节放在前面; 或者按小头序(little endian order) 排列, 即把最不重要的字节放前面.
大头序 二进制 十六进制 十进制
00100111 00010000 27 10 10000
小头序 二进制 十六进制 十进制
00010000 00100111 10 27 10000
8.为什么要使用着色器?
在着色器出现之前,OpenGL只能使用一个固定的方法集合控制很少而有限的事情,比如场景里有多少光线或者加多少雾;这些API易使用难扩展.
在GLES2.0,加入了可编程API,为了保持简洁,固定的API完全删除了,因此,必须使用着色器.
现在用着色器控制每个顶点赢该如何画到屏幕上,我们也控制所有点,直线和三角形上的每个片段应该如何绘制;
现在可以按每个像素实现光照和其他优美的效果,如卡通着色.
只要可以用着色器语言表达出来, 就可以加入任何理想的自定义效果.
** 作为OpenGL和着色器的参考,knronos.org提供了一个很好的快色参考卡片
https://www.khronos.org/opengles/sdk/docs
/reference_cards/OpenGL-ES-2_0-Reference-card.pdf
https://www.khronos.org/registry/OpenGL/specs/es
/2.0/GLSL_ES_Specification_1.00.pdf
**
9.光栅化(Rasterization)技术
OpenGL通过"光栅化"的过程把每个点,直线及三角形分解成大量的小片段,它们可以映射到移动设备显示屏的像素上,从而生成一副图像.
这些片段类似于显示屏上的像素,每一个都包含单一的纯色.RGBA.
OpenGL将多个顶点生成一条直线-->>创建片段-->>显示系统会把这些片段直接映射到屏幕上的像素,结果一个片段就对应一个像素;
然而并不总是这样的: 一个超高分辨率的设备可能需要使用较大的片段,以减少GPU的工作符合.
10.两种类型的着色器.
a.顶点着色器(vertex shader): 生成每个顶点的最终位置,针对每个顶点,它都会执行一次;一旦最终位置确定了,OpenGL就可以把这些可见顶点的集合组装成点,直线以及三角形.
b.片段着色器(fragment shader): 为组成点,直线或者三角形的每个片段生成最终的颜色,针对每个片段,它都会执行一次;一个片段是一个小的,单一颜色的长方形区域,类似于计算机屏幕上的一个像素.
** 精度限定符 ** start
在这个片段着色器中,文件顶部的第一行代码定义了所有符点数据类型的默认精度.类似java浮点数还是双精度浮点数一样.
可以选择lowp,mediump,highp. 然而只有某些硬件实现支持在片段着色器中使用highp.
为什么顶点着色器没有定义精度呢? 顶点着色器同样可以改变其默认的精度,但是,对于一个顶点的位置而言,精确度是最重要的,OpenGL设计者决定把顶点着色器的精度默认设置成最高级--highp.
高精度数据类型更加准确,但是这是以降低性能为代价的;对于片段着色器,出于最大兼容性的考虑,选择了mediump,这也是基于速度和质量的权衡.
** 精度限定符 ** end
11.OpenGL颜色模型
OpenGL使用累加RGB颜色模型.
它只用了三种基本颜色:红色,绿色和蓝色.
许多颜色都是通过把这三种基本颜色按不同比例混合在一起而创造的.
这个模型的工作原理与学校里学过的减色绘画模型不同: 在减色绘画模型里,加入蓝色和黄色制作出绿色,而加入很多颜色会产生黑棕色或者黑色. 这是因为颜料不发光,而是吸收光;画上使用的颜色越多,光被吸收得越多,这幅画就会表现得越暗.
累加RGB模型遵循光本身的属性,当两柱不同颜色的光线混合在一起时,不会看见更暗的颜色,而是更高的颜色.
**https://en.wikipedia.org/wiki/RGB_color_model**
12.为什么不直接使用库?
对Android来说,已经有很多合适的三维库了,从简单的开元封装---libgdx(),再到比较高级的商业化框架,比如Unity3D()。
这些库能帮助你提高生产率,但只有当你对OpenGL、三维渲染,以及底层是如何把这些东西拼在一起的有了基本的理解后才能体会到;否则这些库没有任何意义,也许感觉像使用黑箱魔法一样。
研究这些库有助于学习如何开发自己的组件。 Java3D和jMonkeyEngine是Java桌面版上广泛使用的框架,是很好的学习起点。
##
http://code.google.com/p/libgdx
http://unity3d.com
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-138252.html
http://jmonkeyengine.com
##
13.