12. Html5的局:WebGL跨平台的取与舍

紧接上文

在阅读WebKit源码中,讨论了Canvas在iOS平台使用的CoreGraphics框架作为渲染的工具,它运行在CPU上。WebGL是直接运行在GPU上的API,因此优化空间更大,对程序员要求更高。这次我们看看,WebGL如何对格式转换的,为我们后续three.js导入数据模型做铺设。

常见的纹理格式

OpenGL ES2.0在多终端的差异

在WebKit中,默认支持纹理格式,主要有:
12. Html5的局:WebGL跨平台的取与舍

现实却是很残酷,iOS设备以上格式都是支持的,Android设备差异化就不同了,简单的说,要想确认Android是否支持某种纹理,只需要在glext.h文件中查找宏定义即可.
比如,在Android的glext.h中,却无此定义,而在iOS的OpenGL ES2.0库中,我们可以找到

#define GL_RGB16F_EXT                                           0x881B

OpenGL ES2.0中纹理格式的扩展

区别于上图的主流的纹理格式,在OpenGL ES2.0中存在大量的扩展功能

Android独有的

Android作为通用平台为不同厂家的硬件做了支持,比如AMD系列有以下扩展

/*------------------------------------------------------------------------*
 * AMD extension tokens
 *------------------------------------------------------------------------*/

/* GL_AMD_compressed_3DC_texture */
#ifndef GL_AMD_compressed_3DC_texture
#define GL_3DC_X_AMD                                            0x87F9
#define GL_3DC_XY_AMD                                           0x87FA
#endif

/* GL_AMD_compressed_ATC_texture */
#ifndef GL_AMD_compressed_ATC_texture
#define GL_ATC_RGB_AMD                                          0x8C92
#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
#endif

······

iOS独有的

苹果为苹果自家的平台做了大量的高级扩展

/*------------------------------------------------------------------------*
 * APPLE extension tokens
 *------------------------------------------------------------------------*/
#if GL_APPLE_color_buffer_packed_float
#define GL_R11F_G11F_B10F_APPLE                                 0x8C3A
#define GL_RGB9_E5_APPLE                                        0x8C3D
#endif

#if GL_APPLE_clip_distance
#define GL_CLIP_DISTANCE0_APPLE           0x3000
#define GL_CLIP_DISTANCE1_APPLE           0x3001
#define GL_CLIP_DISTANCE2_APPLE           0x3002
#define GL_CLIP_DISTANCE3_APPLE           0x3003
#define GL_CLIP_DISTANCE4_APPLE           0x3004
#define GL_CLIP_DISTANCE5_APPLE           0x3005
#define GL_CLIP_DISTANCE6_APPLE           0x3006
#define GL_CLIP_DISTANCE7_APPLE           0x3007
#define GL_MAX_CLIP_DISTANCES_APPLE       0x0D32
#endif

······

Android与iOS都有,命名不同的

Android中定义为:

#define GL_BGRA_EXT                                             0x80E1

iOS中的定义:

#define GL_BGRA                                                 0x80E1

WebGL如何屏蔽底层硬件的差异

WebKit作为WebGL标准实现的程序,首先就要面临的是PC/Android/iOS/Linux等多平台,在硬件兼容上的差异。既然底层硬件无法统一,必然在标准的实现上就会有取舍。
我们先看看WebGL对应OpenGL ES2.0硬件支持的定义.

使用方式相似,数值是一样的

【类型变化了,先挖个坑,后续我们在讨论】
Native采用宏定义:

#define GL_RGBA                                          0x1908
glActiveTexture(tex);
typeof tex is unsigned int

JS使用成员变量:

var gl = canvas.getContext('webgl');
alert(gl.RGBA);
gl.activeTexture(tex);
typeof tex is WebGLTexture!

继承与兼容

OpenGL ES2.0的头文件有两个:一个是gl.h,一个是glext.h。为什么有两个,他们之间的关系是什么呢?
从表面上看,一个基本的功能包,一个扩展功能,就像打魔兽一样,等到程序员在不断的打怪升级,经验提升到6级以后,就可以开启大招了。
每个英雄就像我们的选择的GPU,基本属性都有力量、敏捷、智力、攻击力,这些功能都是大同小异的,可以完成日常的开发和bug修复。各个英雄都有自己独特的技能,就像上面我们提到的Android与iOS的差异。

gl.h是通用的

gl.h中的定义与函数,在WebGL中都可以找到,用法完全相同【暂时这么讲,先挖坑】。

定义参数 300+
定义函数 150+
都要背会哦

glext.h是各个平台的扩展

这个头文件里的内容,大不相同,为了满足部分高级程序员更高的渲染特效、性能优化,采用了各个平台的支持,比如:深度测试、蒙版测试、多种纹理格式、多线程支持、离屏渲染、管道操作、纹理压缩、视频流等等,包罗万象。
这里告诉大家一个好消息和一个坏消息。
好消息是:

WebGL对这个文件的大部分API都不支持~~

坏消息是:

该支持的API,还是要支持滴~~

兼容glext.h

实在无法统一的API,WebGL直接屏蔽掉,主要考虑两个问题:

  1. WebGL的目标是跨平台,兼容就要有牺牲
  2. 有些功能不常用,也不是行业标注

第一步,就是统一多平台的参数命名:

#define GL_DEPTH_STENCIL                        0x84F9
#define GL_DEPTH_STENCIL_ATTACHMENT             0x821A

······

第二步,增加平台无关的自定义参数

#define GL_UNPACK_FLIP_Y_WEBGL                  0x9240
#define GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL       0x9241
#define GL_CONTEXT_LOST_WEBGL                   0x9242
#define GL_UNPACK_COLORSPACE_CONVERSION_WEBGL   0x9243
#define GL_BROWSER_DEFAULT_WEBGL                0x9244

第三步,采用C/C++补全硬件平台的缺陷
例如,常见纹理格式的转换,在Android平台增加:

#define GL_RGB16F_EXT               0x881B
#define GL_RGBA16F_EXT              0x881A

#define GL_RGB32F_EXT               0x8815
#define GL_RGBA32F_EXT              0x8814

#define GL_BGRA                     GL_BGRA_EXT
#define GL_SRGB_EXT                 0x8C40
#define GL_SRGB_ALPHA_EXT           0x8C42

#define GL_ALPHA16F_EXT             0x881C
#define GL_LUMINANCE16F_EXT         0x881E
#define GL_LUMINANCE_ALPHA32F_EXT   0x8819

#define GL_ALPHA32F_EXT             0x8816
#define GL_LUMINANCE32F_EXT         0x8818
#define GL_LUMINANCE_ALPHA16F_EXT   0x881F

······

下回再见

下一章,我们继续今天的话题。

看了这么多代码,也没明白讲什么~~我也不知道该怎么讲,这可能就是OpenGL的难懂的原因吧。
众所周知,WebGL是基于OpenGL ES2.0版本的标准,而OpenGL ES2.0只是OpenGL的子集。目前所有的Mobile设备通常采用OpenGL ES2.0的硬件,以达到成本、节能、性能最大化。
但,如果是在PC上呢?PC拥有强大的GPU和完整的OpenGL能力,要自废武功来实现这个憋足的OpenGL ES2.0嘛。

上一篇:Centos 6.4下 MySQL配置主从服务(集群)


下一篇:他爱你就一定会来找你