在阅读WebKit源码中,讨论了Canvas在iOS平台使用的CoreGraphics框架作为渲染的工具,它运行在CPU上。WebGL是直接运行在GPU上的API,因此优化空间更大,对程序员要求更高。这次我们看看,WebGL如何对格式转换的,为我们后续three.js导入数据模型做铺设。
在WebKit中,默认支持纹理格式,主要有:
现实却是很残酷,iOS设备以上格式都是支持的,Android设备差异化就不同了,简单的说,要想确认Android是否支持某种纹理,只需要在glext.h文件中查找宏定义即可.比如,在Android的glext.h中,却无此定义,而在iOS的OpenGL ES2.0库中,我们可以找到
#define GL_RGB16F_EXT 0x881B区别于上图的主流的纹理格式,在OpenGL ES2.0中存在大量的扩展功能
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 ······苹果为苹果自家的平台做了大量的高级扩展
/*------------------------------------------------------------------------* * 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中定义为:
#define GL_BGRA_EXT 0x80E1iOS中的定义:
#define GL_BGRA 0x80E1WebKit作为WebGL标准实现的程序,首先就要面临的是PC/Android/iOS/Linux等多平台,在硬件兼容上的差异。既然底层硬件无法统一,必然在标准的实现上就会有取舍。我们先看看WebGL对应OpenGL ES2.0硬件支持的定义.
【类型变化了,先挖个坑,后续我们在讨论】Native采用宏定义:
#define GL_RGBA 0x1908 glActiveTexture(tex); typeof tex is unsigned intJS使用成员变量:
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中的定义与函数,在WebGL中都可以找到,用法完全相同【暂时这么讲,先挖坑】。
定义参数 300+ 定义函数 150+ 都要背会哦这个头文件里的内容,大不相同,为了满足部分高级程序员更高的渲染特效、性能优化,采用了各个平台的支持,比如:深度测试、蒙版测试、多种纹理格式、多线程支持、离屏渲染、管道操作、纹理压缩、视频流等等,包罗万象。这里告诉大家一个好消息和一个坏消息。好消息是:
WebGL对这个文件的大部分API都不支持~~坏消息是:
该支持的API,还是要支持滴~~实在无法统一的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嘛。