虽然OpenGL能够满足大多数计算机图形应用,在某些情况下,它可能不是最好的解决办法,这就是为什么OpenGL的API催生了另外两个API。第一个是OpenGL ES,‘ES’意为嵌入式子系统,他是桌面版openGL的裁剪版,在系统资源相对缺乏的嵌入式设备中使用,例如移动电话、平板电脑电视和其他彩色屏幕设备。
另一个API就是WebGL,这使得OpenGL风格的函数能够在大多数的web浏览器下通过javascript调用。
##WebGL简介
WebGL通过提高性能,以及HTML5的Canvas元素中的3D渲染功能将OpenGL(更确切的说,OpenGL ES 2.0)带入互联网浏览器之中。OpenGL ES 2.0版的所有功能都可以找到他们的确切形式,除了因为使用JavaScript接口带来的必要小变化。
WebG现在可以在几乎所有现代Web浏览器上工作(微软的IE10记以前版本需要一个插件,IE11毫无问题,而且IE11的webGL性能是极其惊人的)。本例只注重渲染,不讨论事件处理和交互。
##在一个HTML5页面中设置WebGL
为了给WebGL提供一个“窗口”用于渲染,首先在网页创建一个HTML5 Canvas元素。在这个例子中,设置他的id为gl-canvas。在后面要使用它的id来初始化WebGL。
假设这个能够在浏览器上正常工作,现在woman可以继续进行下一步:创建一个WebGL上下文。有多种方法可以做到这一点,但是在这里我们将使用Khronos组织提供的一个公共方法,webgl-utils.js。它可以非常方便的吧嵌入到你的WebGL程序里。它包括WebGLUtils(类似GLUT在openGL中的低位)及其扩展方法setupWebGL(),其中它可以很容易的在一个HTML5画布中启用WebGL。
下面的例子展示了建立一个WebGL上下文,在所有支持WebGL的浏览器上都可以很好的工作。从setupWebGL()的返回值是一个JavaScript对象,它包含WebGL支持的所有OpenGL函数方法。
上例所指定在加载页面时(通过window.onload = init;
)执行一个init()
函数。init()函数获取gl-canvas的id,并把它传递给setupWebGL(),他将返回一个WebGL对象,可以用来判断初始化是否成功;返回false,则提示错误信息。架设webGL是可用的,我们将设置webGL的一些状态,并清除窗口——一旦webGL接管画布,所有内容由WebGL控制,并且画面变成红色。
现在知道了WebGL已经得到支持了,接下来要扩展实例程序、初始化指定着色器、设置顶点缓冲,以及最后渲染。
##初始化WebGL里的着色器
WebGL基于openGL ES2.0版,因此WebGL是一个基于着色器的API,和openGL一样,要求每个应用程序使用顶点和片段着色器来实现渲染,所以,你会遇到加载着色器的需求,和在openGL中一样。
在WebGL的应用程序要包含顶点着色器和片段着色器,最简单的方法就是直接包含在HTML页面中,这个页面需要被正确的标注出来。与WebGL的着色器相关的两个mime类型,如下表所示。
<script>标记类型 |
着色器类型 |
x-shader/x-vertex |
顶点着色器 |
x-shader/x-fragment |
片段着色器 |
对于WebGL程序,下面为主要的HTML页面,包括着色器源文件。他还引用了两个javascript文件,作用如下:
- demo.js,其中包括应用程序的JavaScript实现(包括init函数的最终实现)
- InitShaders.js,一个用来加载着色器的辅助函数,类似于LoadShaders()程序
html程序源文件
为了简化编译和链接WebGL的着色器代码,创建了一个InitShaders()程序,但是没有加载glsl文件;着色器定义在了HTML页面源代码中。为了组织好代码,创建InitShaders.js文件。
##WebGL着色器载入器:InitShaders.js
虽然InitShaders()采用HTML元素的ID寻找顶点着色器和片段着色器的代码。返回的是传递到glUseProgram()的程序名称。
有了编译和链接到着色器的方法,就可以继续初始化图形数据、加载纹理,并完成WebGL程序的其他部分。
##WebGL初始化顶点数据
WebGL带给JavaScript的一个显著特征就是类型化数组(typed arrays),它扩展为JavaScript数组概念,并满足OpenGL数据类型风格,几种类型化数组的类型如下表所示。
数组类型 |
C类型 |
Int8Array |
signed char |
Uint8Array |
unsigned char |
Uint8ClampedArray |
unsigned char |
Int16Array |
signed short |
Uint16Array |
unsigned short |
Int32Array |
signed int |
Uint32Array |
unsigned int |
Float32Array |
float |
Float64Array |
double |
第一次需要分配和填充(这两者可以在一个单一的操作里面做)一个类型化数组来存储顶点数据。在此之后,设置VBO即可,和在openGL中是一样的。
##初始化WebGL里的顶点缓冲
##在WebGL中使用纹理贴图
在webGL中使用纹理和openGL一样,但加载处理要简单得多,因为有HTML的帮助。事实上,从文件加载纹理仅仅需要一行代码即可完成。比如,加载一个名为的单一纹理。
HTML加载图片虽然简单,然而,他是异步加载的,所以要知道该图像文件何时接受并载入,可以在回调中处理。JavaScript在图像中有一个处理这种情况的方法:onload()
上面给出的onload函数实在图像被完全加载并且可以被WebGL使用的时候才调用一次。我们可以将所以的纹理初始化代码都封装到一个本地函数configureTexture中。
WebGL扩展的glPixelStore*()用于翻转图像数据,WebGL的宏UNPACK_FLIP_Y_WEBGL是旋转图像数据来匹配WebGL时需要的。
由于OpenGL ES 2.0版本的原因,WebGL只支持分辨率为2的幂的纹理。
demo.js的完整源文件