紧接上文
在阅读WebKit源码中,讨论了Canvas在iOS平台使用的CoreGraphics框架作为渲染的工具,它运行在CPU上。WebGL是直接运行在GPU上的API,因此优化空间更大,对程序员要求更高。这次我们看看,WebGL如何对格式转换的,为我们后续three.js导入数据模型做铺设。
常见的纹理格式
OpenGL ES2.0在多终端的差异
在WebKit中,默认支持纹理格式,主要有:
现实却是很残酷,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直接屏蔽掉,主要考虑两个问题:
- WebGL的目标是跨平台,兼容就要有牺牲
- 有些功能不常用,也不是行业标注
第一步,就是统一多平台的参数命名:
#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嘛。