小八——WebGL心路历程(1),从一个原生的webGL程序粗放认识webGL

HTML5时代的到来,让WebGL这个重磅核武器渐渐被大多人所熟悉并且使用。笔者最近两周左右的时间因为项目的原因,一直在看WebGL相关的文章。

说说我的基础吧:计算机本科毕业生水平,大学本科用MFC编写图形学的基础,除此之外在使用WebGL之前自己偷摸着用了一阵子的opengl以及jogl,也就是写几个小例子的水平。写网页的话有点HTML的小基础,写javascript基本每次都是现学的。本人眼高手低,心想着WebGL肯定api也跟这两者差不多,应该很快就入门。没想到入门就吃了闭门羹。终于静下心来买了一本《WebGL入门指南》慢慢研读,研读下来感悟不少,一本不到两百多页的书硬是被我越读越厚。利用这个博客将我这一段时间的所得写下来吧。第一次在CSDN写博客,有什么不足的地方见谅以及指出。本人的联系邮箱是:terryleeoo@foxmail.com

         大学时候有位老师对我说,什么事情都得从小事开始做起。那么我的心路历程也用原生的一个WebGL例子作为引子开始介绍WebGL

         例子引自WebGL高级编程

<!DOCTYPE HTML> 
<html lang="en"> 
<head>
<title>Listing 2-1, A First WebGL Example</title>
<meta charset="utf-8"> 
<script type="text/javascript">
var gl;
var canvas;
var shaderProgram;
var vertexBuffer;
function createGLContext(canvas) {
  var names = ["webgl", "experimental-webgl"];
  var context = null;
  for (var i=0; i < names.length; i++) {
    try {
      context = canvas.getContext(names[i]);
    } catch(e) {}
    if (context) {
      break;
    }
  }
  if (context) {
    context.viewportWidth = canvas.width;
    context.viewportHeight = canvas.height;
  } else {
    alert("Failed to create WebGL context!");
  }
  return context;
}
function loadShader(type, shaderSource) {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, shaderSource);
  gl.compileShader(shader);
  
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("Error compiling shader" + gl.getShaderInfoLog(shader));
      gl.deleteShader(shader);   
      return null;
  }
  return shader;  
}
function setupShaders() {
  var vertexShaderSource = 
    "attribute vec3 aVertexPosition;                 \n" +
    "void main() {                                   \n" +
    "  gl_Position = vec4(aVertexPosition, 1.0);     \n" +
    "}                                               \n";           
   
   var fragmentShaderSource = 
     "precision mediump float;                    \n"+
     "void main() {                               \n"+
     "  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);  \n"+
     "}                                           \n";
  var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
  var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);  
  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert("Failed to setup shaders");
  }
  gl.useProgram(shaderProgram);  
  shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); 
}
function setupBuffers() {
  vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  var triangleVertices = [
         0.0,  0.5,  0.0,
        -0.5, -0.5,  0.0,
         0.5, -0.5,  0.0
  ];
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
  vertexBuffer.itemSize = 3;
  vertexBuffer.numberOfItems = 3;
}
function draw() { 
  gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
  gl.clear(gl.COLOR_BUFFER_BIT);
  
  gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
  gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  
  gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems);
}
function startup() {
  canvas = document.getElementById("myGLCanvas");
  gl = createGLContext(canvas);
  setupShaders(); 
  setupBuffers();
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  draw();  
}
</script>
</head>
<body οnlοad="startup();">
  <canvas id="myGLCanvas" width="500" height="500"></canvas>
</body>
</html>

很不幸地说,这个例子看似代码很长,出来的效果,如下图:

有点失望是吧,这么一大段的代码,出来的结果却是这样的。

 

我在这里说说自己对这个例子的几点感悟,希望对于想要学WebGL的同学有所帮助(有关HTML以及JS一些基础的内容,自行百度脑补XD)

 

1.      这个例子是最基础的webGL程序,你甚至可以把它当成一个模板应用在你后面的一些例子当中。当然了,如果对于只是使用webGL来快速开发而不是研究webGL的朋友来说,你会有更好的方法来达到你的目的。比如使用一些成熟的WebGL框架。

 

2.      createGLContext函数判断浏览器是否支持支持WebGL,如果支持的话返回一个context对象,我对这个context对象的理解就相当于opengl里面的gl,事实证明例子中把该函数的返回值也赋给了一个名为gl的变量。对于这个函数,您大可不必大费周章,因为很多时候您对它的操作也就是copy+paste。

 

3.      来到关键的setupShaders函数,对于webGL来说,个人认为最最关键的技术就在于顶点着色器和片段着色器了。为什么要使用这两个东西呢?这么来说吧,如果我只用CPU来完成绘图工作的话,效率已经很慢了,如果我再用效率更低的js来绘图的话,可想而知效率会怎么样?那么webGL是将点的渲染交给GPU,采用GLSL的类C语言的语法编写这一部分的代码,将代码传入CPU编译连接,这样就提高了效率。这一部分的代码主要有两种:顶点着色器和片段着色器。关于这两个知识点,我会在后面的文章中说明。

 

4.      setupBuffers函数定义了图形的顶点,你还可以在这里面定义图形的颜色等等信息。

 

5.      最后的draw函数,利用之前做好的准备和数据画出图形

 

整个过程就是这样了,我的建议是,对于这一大段代码,您大可不必大费周章每行都明白。现在,你只需要知道每一步是干什么的,以及能大概在脑子里面有个大体的流程,知道WebGL的程序的流程就好。

后面的内容我将以Three.js这个框架为基础,谈谈自己最近的感受。等最后,再回来看看这个程序,就会很明白每一步的细节了。需要说明的是,《webGL入门指南》这本书虽然讲的很好,而且基于Three.js这个框架,但是在中间又引入本书作者自己的Sim.js框架让我很不习惯。因为本来Three.js已经封装了一层代码的情况下,我不太喜欢有人再给我封装一层不符合我的学习习惯,这就是导致我这本书越读越厚的原因了。另外,我在很纠结的情况下也去拜读了一下Sim.js框架的代码,从中学到了很多,也写了自己的一个小框架,会在后面的学习中一点点引入。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值