webGL Learning Notes | webGL Tutorial (1)

Sorry, this article is not written in English and has not been translated into English yet .You can view this article in English with Google Translate, or please come back later.

闲扯淡

若干年前(那时候还不知道雾霾是什么),一个偶然的机会了解到了WebGL。当时出于好奇便找了些资料,想深入研究,但是由于各种原因放弃了。若干年后,来到了充满“黑暗雾霾故事“的帝都追随梦想,由于工作的原因,再次对webGL充满了浓厚额兴趣,为了不让自己的意志被时间消磨,我决定把webGL的过程写成文章,一是用来鞭励自己,二是坚持互联网的开源分享精神,给后面赶路的童鞋们提供些便利(其实最重要的是可以给博客吸引人气,有木有!![贱萌的笑])。

一些介绍

因为工作比较繁忙,绝大部分的东西是在业余时间进行研究的,而且OPEN GL方面确实需要些数学基础,所以进度,以及能研究的到多深入似乎取决于我的智商,所以还请各位多多理解。

另外:我将学习过程中用到的一些资料放在了 GithubYes-webGL https://github.com/zmofei/yes-webgl 项目上,希望能遇到志同的人一起来完善这个事情。

好了闲话少说,我们开始步入正题。

DEMO

前几篇文章会先从如何用webGL实现2D图案开始来介绍,我会说从最基础的部分说起(可能会比较枯燥,请自备男/女朋友、瓜子、花生等解闷)。

此次DEMO,我们在画布中通过WebGL绘制一个红色矩形:

YES!webGL!我们开始吧

开始,还是大致介绍一下webGL实现的过程。

实现webGL你需要理解下面的一些概念,canvas,vertex shader,fragment shader,buffer

  • canvas : 画布,如果用过canvas的同学应该很熟悉它了,webGL也是通过canvas画布展现出来的。
  • vartex shader : 顶点着色器,用来储存图像的位置相关信息,比如坐标、大小等。
  • fragment shader : 片远着色器,用来描述对象的颜色文理等信息。
  • buffer : 缓冲区,通常情况下如果绘制多个点,或者繁杂的纹理的时候会特别使用到buffer object,其他情况下,图形会在该区域进行缓冲,缓冲完成之后显示在屏幕上。

那么,这些名词是如何协同工作的呢?先让我们看一张图:

webGL渲染实例图

上图描述了webGL处理图形的简单过程:

  1. 首先通过canvas获取webgl的上下文。
  2. 通过vartex shader(顶点着色器)和 fragment shader(片元着色器)指定图形的形状和样式。
  3. 将这些图形颜色等数据放入相应的缓冲区。
  4. 绘制在显示器上。

单纯从字面意思来说可能不是在么好理解,下面结合DEMO的代码进行详细的说明。

一、获取webGL执行环境

HTML

<canvas id="webgl"></canvas>

JavaScript

var canvas = document.getElementById('webgl');
var webgl = canvas.getContext('webgl');

这一步很简单,和canvas一样,我们在进行webGL渲染之前,需要先获得webgl的执行环境(即上下文),首先我们通过getElementById获取到了我们用来渲染webGL的DOM元素,然后通过getContext('webgl')来获取webGL上下文。

但是需要留意的是,在DEMO中我们并为对浏览器的兼容性进行处理,实际上getContext的参数可能为下面四个中的一个["webgl","experimental-webgl","webkit-3d","moz-webgl"],第一个就不用多解释,第二个出现在webgl还是个实验性功能的时候,后面两个从前缀中不难判断出他们的用处。

所以,通常情况下在正式的项目中,我们需要这样一个方法来获取webGL的上下文(为了DEMO的足够简单,在DEMO中并没有体现出来,后续会放一个google写的用来初始化webGL的一个“类库”)。

/**
 * Creates a webgl context.
 * @param {!Canvas} canvas The canvas tag to get context
 *     from. If one is not passed in one will be created.
 * @return {!WebGLContext} The created context.
 */
var webglContext = function(canvas) {
  var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
  var context = null;
  for (var ii = 0; ii < names.length; ++ii) {
    try {
      context = canvas.getContext(names[ii]);
    } catch(e) {}
    if (context) {
      break;
    }
  }
  return context;
}

拿到webGL上下文之后我们可以打印出来其具体的值然后简单的看一下它的__proto__:

"__proto__":{
    ACTIVE_ATTRIBUTES: 35721,
    ACTIVE_TEXTURE: 34016,
    ACTIVE_UNIFORMS: 35718,
    ALIASED_LINE_WIDTH_RANGE: 33902,
    ALIASED_POINT_SIZE_RANGE: 33901,
    ALPHA: 6406ALPHA_BITS: 3413,
    //...
    activeTexture: function activeTexture() { [native code] },
    attachShader: function attachShader() { [native code] },
    bindAttribLocation: function bindAttribLocation() { [native code] },
    bindBuffer: function bindBuffer() { [native code] }
    //...
}

在他的原型链上我们看到了一些类似ACTIVE_ATTRIBUTES之类的定值,这些值是这些属性的标识,后续的很多操作是通过这些标识来绑定到webGL对象上的,比如:

//创建vertex shader
webgl.createShader(webgl.VERTEX_SHADER);
//清除颜色缓冲区
webgl.clear(webgl.COLOR_BUFFER_BIT);

这些方法中的参数就是webGL原型链中的一些定值(比如VERTEX_SHADER:35633),当然了你也可以用35633代替webgl.VERTEX_SHADER,其仍然能正正常工作,至于这些值是固定的么?我尝试换了几个浏览器,通过console.log打印出来发现,他们都是固定的数值,我的理解是,这些数字是固定的,可以标识webGL对象的某些属性。就像我们的身份证号码一样,一个号码标识了一个人。

结语

OK,获取到了webGL之后,我们就要去渲染图形了,下一次我会和大家说一些关于vertex shader 和 fragment shader的相关知识。

98200
  • logo
    • HI, THERE!I AM MOFEI

      (C) 2010-2024 Code & Design by Mofei

      Powered by Dufing (2010-2020) & Express

      IPC证:沪ICP备2022019571号-1