# 说在前面

  • getContext
  • clearColor clear

WebGL 使得在支持 HTML 的 canvas 标签的浏览器中,不需要安装任何插件,便可以使用基于 OpenGL ES 2.0 的 API 在 canvas 中进行 2D 和 3D 渲染。

THREE.js和BABYLON.js等很多框架封装了 WebGL,提供了各个平台之间的兼容性。使用这些框架而非原生的 WebGL 可以更容易地开发 3D 应用和游戏。

# 一些概念

# 光栅化引擎

WebGL 经常被当成 3D API,人们总想“我可以使用 WebGL 和一些神奇的东西做出炫酷的 3D 作品”。

事实上 WebGL 仅仅是一个光栅化引擎,它可以根据你的代码绘制出点,线和三角形。

想要利用 WebGL 完成更复杂任务,取决于你能否提供合适的代码,组合使用点,线和三角形代替实现。

# GLSL

WebGL 在电脑的 GPU 中运行。因此你需要使用能够在 GPU 上运行的代码。

这样的代码需要提供成对的方法。每对方法中一个叫顶点着色器, 另一个叫片断着色器,并且使用一种和 C 或 C++类似的强类型的语言 GLSL。

# 着色器程序

每一对着色器组合起来称作一个 program(着色程序)。

几乎整个 WebGL API 都是关于如何设置这些成对方法的状态值以及运行它们。

对于想要绘制的每一个对象,都需要先设置一系列状态值,然后通过调用 gl.drawArrays 或 gl.drawElements 运行一个着色方法对。

# 着色器的数据

  • 属性 Attribute 和缓冲 buffer

    缓冲是发送到 GPU 的一些二进制数据序列(在 JS 中一般就是类型化数组,通过 ArrayBuffer 送进缓冲)

    属性用来指明怎么从缓冲中获取所需数据并将它提供给顶点着色器

    缓冲不是随意读取的。事实上顶点着色器运行的次数是一个指定的确切数字, 每一次运行属性会从指定的缓冲中按照指定规则依次获取下一个值。

  • 全局变量 Uniform

    全局变量在着色程序运行前赋值,在运行过程中全局有效。

  • 纹理 Texture

    纹理是一个数据序列,可以在着色程序运行中随意读取其中的数据。大多数情况存放的是图像数据,但是纹理仅仅是数据序列, 你也可以随意存放除了颜色数据以外的其它数据。

  • 可变量 Varyings

    可变量是一种顶点着色器给片断着色器传值的方式,顶点着色器中设置的可变量会在片断着色器运行中获取不同的插值。

稍微总结一下

在 JS 中创建缓冲,通过属性指定传值给 WebGL。 在 JS 中创建变量,通过全局变量传值给 WebGL。
在 WebGL 中,顶点着色器通过可变量传值给片段着色器。

gl.getAttribLocation(program, "attrubute_name");
gl.getUniformLocation(program, "uniform_name");

# 核心问题

WebGL 只关心两件事:裁剪空间中的坐标值和颜色值。

你需要提供两个着色器来做这两件事,一个顶点着色器提供裁剪空间坐标值,一个片断着色器提供颜色值。

注意:无论你的画布有多大,裁剪空间的坐标范围永远是 -1 到 1 。

# 准备工作

# 准备 3D 渲染

<canvas id="glcanvas" width="320" height="240">
    你的浏览器似乎不支持或者禁用了 HTML5 <code>&lt;canvas&gt;</code> 元素。
</canvas>

# 准备 WebGL 上下文

const canvas = document.querySelector("#glcanvas");
// 初始化 WebGL 上下文
const gl = canvas.getContext("webgl");

// 确认 WebGL 支持性
if (!gl) {
  alert("无法初始化 WebGL,你的浏览器、操作系统或硬件等可能不支持 WebGL。");
  return;
}

// 使用完全不透明的黑色清除所有图像
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 用上面指定的颜色清除缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
  • 我们所要做的第一件事就是是获取 canvas 的引用,把它保存在 ‘canvas’ 变量里。
  • 当我们获取到 canvas 之后,我们会调用getContext 函数并向它传递"webgl"参数,来尝试获取 WebGLRenderingContext
  • 如果 WebGL 上下文成功初始化,变量 ‘gl’ 会用来引用该上下文。在这个例子里,我们用黑色清除上下文内已有的元素。

# 渲染结果

一个黑色矩形