webgl_web管理ad - CSDN
webgl 订阅
WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。 展开全文
WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。
信息
中文名
web图形库
结    合
JavaScript和OpenGL ES 2.0
外文名
Web Graphics Library
类    别
3D绘图标准
特    点
供硬件3D加速渲染
WebGL设计
WebGL 1.0基于OpenGL ES 2.0,并提供了3D图形的API。它使用HTML5Canvas并允许利用文档对象模型接口。WebGL 2.0基于OpenGL ES 3.0,确保了提供许多选择性的WebGL 1.0扩展,并引入新的API。可利用部分Javascript实现自动存储器管理。 [1] 
收起全文
  • webgl入门视频课程从基础开始介绍webgl技术,介绍基本的webgl渲染管线,各种常用的缓冲区的作用,以及用法,结合程序实例做到全方位的讲解;精讲三维的理论,针对三维理论中的三个矩阵变换一个坐标变换深入讲解.针对webgl...
  • WebGL视频教程

    2020-06-04 08:45:36
    本课程主要对原生WebGL进行讲解,不需要你有特定的图形基础,稍微了解一点JavaScript编程及时即可。通过本课程学习你可以对WebGL渲染管线和着色器语言建立一个整体的认识,有了一定的WebGL基础,更容易理解three.js...
  • 相对于Flash,Flex,Silverlight等富客户端技术,WebGL之ThreeJS:通过OpenGL ES 2.0,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能...
  • three.js 是 JavaScript 编写的 WebGL 第三方库。Three.js 也是一款运行在浏览器中的 3D 引擎,你可 以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。 Three.js 实战系列,Three.js(webgl) webpack+...
  • WebGL可以做什么?

    2018-03-09 22:48:54
    WebGL允许开发者在浏览器中实现实时的3D互动图形。WebGL可以应用于互动音乐电视、游戏、数据可视化、艺术、3D设计环境、3D空间建模、3D物体建模、绘制数学函数和创建物理模拟。因为是被设计成直接工作在显卡端的,...

    WebGL允许开发者在浏览器中实现实时的3D互动图形。WebGL可以应用于互动音乐电视游戏数据可视化艺术3D设计环境3D空间建模3D物体建模绘制数学函数创建物理模拟

    因为是被设计成直接工作在显卡端的,所以WebGL比目前其他的典型的web技术都要更加复杂。总的来说,它是相当的低等级的。这也正是它为什么能够如此迅速的完成大量的计算,并实现复杂的实时3D渲染的原因。

    你不需要完全理解WebGL内在的工作原理。因为有很多第三方WebGL图形库可以帮你完成一些复杂的操作。但是如果你想成为一个高级开发者,充分利用WebGL的各种高级特性,那建议你最好还是深入了解一下其中的内涵。

    在WebGL中编程,通常的目标都是想要渲染某种场景。这其中包括多重并发的绘制工作,称之为绘制调用(draw call),这些调用都是在GPU端通过一个叫做渲染管线(Rendering Pipeline)的处理流程来实现的。

    在WebGL中,和其他大多数实时3D图形系统一样,三角形是用于绘制模型的最基本的元素。因此,在WebGL中需要通过使用JavaScript来生成绘制信息,这些绘制信息包括指定在什么位置绘制三角形、如何绘制三角形、这些三角形的外观长的什么样子(颜色、形状、纹理等等)。然后将这些信息传递给到GPU端,GPU进行处理,最后再返回绘制结果。


    WebGL官网:http://www.hewebgl.com/

    基于WebGL的技术三维模型在线预览:http://www.yanhuangxueyuan.com/3D.html

    转载地址:http://blog.csdn.net/u010028980/article/details/8798527

    展开全文
  • 概述了这篇教程的目的,编写了WebGL的第一个示例。

    1. 概述

    不得不说现在三维图形渲染技术更新换代实在是太快,OpenGL很多资料还没来得及学习就已经有点落伍了。NeHe的学习教程还有之前用的《OpenGL编程指南》第七版(也就是红宝书)都非常好,可惜它们都是从固定管线开始讲起的;而现在可编程管线的技术已经是非常常见的基础技术了。后来我还看过《OpenGL编程指南》第八版(白皮书),这本教程是从可编程管线(着色器)开始讲起的,看的时候就觉得没有前面的基础打底,显得非常的晦涩,远不如红宝书易懂。羞愧的说,我已经多次入门失败了。

    这也正是我写这篇教程的原因,希望从繁杂的资料中总结真正有用的知识(当然也希望能帮助到你)。我觉得WebGL是学习OpenGL系列三维图形渲染技术很好的入门点。WebGL是OpenGL的浏览器版本,基本上可以认为是OpenGL的子集,能被WebGL保留而不剔除的技术,必须是三维图形渲染技术的精华。在这里给大家强烈推荐《WebGL编程指南》这本书,我这篇教程正是在这本书的基础之上总结出来的。

    在学习OpenGL/WebGL的时候,我还感觉到很多资料举得例子往往都太简单了,确实是一看就懂,但是在实际遇到的问题的时候却往往解决不了。我还是认为在实际中解决问题,更能加深对知识的理解。正好最近我在研究GIS中地形的绘制,那么我就通过一步一步绘制地形的示例,来总结WebGL的相关知识。如果你不懂GIS这些术语也不要紧,只需要知道我这里的最终目的是想绘制的是一个大地高程模型,是一个包含XYZ坐标的点集,表达了地形的情况。

    2. 示例:绘制一个点

    编写WebGL程序跟编写Web前端程序的步骤是一样的,包含HTML和JavaScript两个部分,通过浏览器进行调试。

    1) HelloPoint1.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>Draw a point (1)</title>
      </head>
    
      <body onload="main()">
        <canvas id="webgl" width="400" height="400">
        Please use a browser that supports "canvas"
        </canvas>
    
        <script src="../lib/webgl-utils.js"></script>
        <script src="../lib/webgl-debug.js"></script>
        <script src="../lib/cuon-utils.js"></script>
        <script src="HelloPoint1.js"></script>
      </body>
    </html>
    

    这一段HTML非常简单,从实际表现上来说就是创建了一个画布<canvas>。<canvas>是HTML5引入的的一个绘制标签,可以在画布中绘制任意图形。WebGL正是通过<canvas>元素进行绘制的。
    除此之外,这段代码还通过<script>标签引入了几个外部JS文件。其中lib目录中的几个JS文件是一些通用的组件(来自《WebGL编程指南》的源码),可以先暂时不用关心其具体实现;最后一个导入的HelloPoint1.js正是我们编写的绘制模块。而在<body>标签中定义的onload事件属性绑定的正是HelloPoint1.js中的main()函数。

    2) HelloPoint1.js

    // 顶点着色器程序
    var VSHADER_SOURCE = 
      'void main() {\n' +
      '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // Set the vertex coordinates of the point
      '  gl_PointSize = 10.0;\n' +                    // Set the point size
      '}\n';
    
    // 片元着色器程序
    var FSHADER_SOURCE =
      'void main() {\n' +
      '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // Set the point color
      '}\n';
    
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
    
      // 获取WebGL渲染上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }
    
      // 初始化着色器
      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed to intialize shaders.');
        return;
      }
    
      // 指定清空<canvas>的颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
    
      // 清空<canvas>
      gl.clear(gl.COLOR_BUFFER_BIT);
    
      // 绘制一个点
      gl.drawArrays(gl.POINTS, 0, 1);
    }
    

    这段JS代码的主要内容就是前面提到的main函数,一旦HTML被浏览器加载成功,这段脚本就会执行。在main函数中主要有一下几步:

    (1) 准备工作

    document.getElementById(‘webgl’):文档对象模型DOM的函数,获取到HTML页面的元素。

    getWebGLContext(canvas):获取WebGL渲染上下文,保存在gl变量中。因为不同浏览器获取函数不太一样,所以通过组件cuon-utils提供的函数来统一行为。

    (2) 着色器

    initShaders:初始化着色器。

    首先要知道什么是着色器。如果你只学习过固定管线或者其他的二维绘图组件(如GDI),就会非常困惑着色器是什么,为什么要用着色器。比如说在固定管线中,绘制点就是drawPoint,绘制线就drawLine。而在WebGL中,绘制工作则主要被分解成顶点着色器和片元着色器两个步骤了。

    在启动JS程序后,绘制工作首先进入的是顶点着色器,在顶点着色器中描述顶点特性(如位置、颜色等),顶点就是三维空间的点,比如三角形的三个顶点;然后进入到片元着色器,在片元着色器中逐片元处理像素(如光照、阴影、遮挡)。最后片元传入到颜色缓冲区,进行显示。渲染过程如下:
    WebGL渲染管线

    这个过程是一个类似水流的流向过程,所以这个过程被称为渲染管线(Pipeline)。并且,这个过程是需要我们去编程控制的,比如观察者的视角变化需要在顶点着色器去调控;光线对颜色的变化需要在片元着色器去调控等;因此,这个过程就是可编程管线。通过着色器程序,三维图像渲染就更加的灵活强大。

    在initShaders()函数中,传入了预先定义的JS字符串VSHADER_SOURCE和FSHADER_SOURCE。需要说明是,着色器程序是以字符串的形式嵌入到JS文件中运行的。这个函数同样是cuon-utils组件提供的,调用之后就告诉WebGL系统着色器已经建立好了并可以随时使用。

    (3) 顶点着色器

    顶点着色器的定义如下:

    // 顶点着色器程序
    var VSHADER_SOURCE = 
      'void main() {\n' +
      '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // Set the vertex coordinates of the point
      '  gl_PointSize = 10.0;\n' +                    // Set the point size
      '}\n';
    

    前面说到顶点着色器程序是嵌入在JS中的程序,所以虽然传入的是字符串,但其实本质是着色器描述语言(GLSL:OpenGL Shading Language)。既然是语言也就有自己的函数与变量定义。main()函数是每个着色器程序定义的入口。在main函数中,将顶点的坐标赋值给内置变量gl_Position,点的尺寸赋值给内置变量gl_PointSize。

    注意这里的gl_Position是必须赋值的,否则着色器不会正常工作。赋值的类型是vec4,也就是一个四维矢量。一般来说,描述点位只需要三维矢量就可以了,但是很多情况下需要四个分量的齐次坐标。齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w)。所以如果第四个分量是1,那么就是普通的三维坐标;如果第四分量为0,就表示无穷远的点。

    (4) 片元着色器

    片元着色器的定义如下:

    // 片元着色器程序
    var FSHADER_SOURCE =
      'void main() {\n' +
      '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // Set the point color
      '}\n';
    

    如同顶点着色器一样,片元着色器将点的颜色赋值给gl_FragColor变量,gl_FragColor是片元着色器唯一的内置变量,控制像素在屏幕上的最终颜色。

    (5) 清空缓冲区

    gl.clearColor():设置清空的背景色。
    gl.clear(gl.COLOR_BUFFER_BIT): 清空颜色缓冲区。

    (6) 绘制操作

    gl.drawArrays(gl.POINTS, 0, 1):绘制一个点。
    顶点着色器只是指定了绘制的顶点,还需要指定顶点到底成点、成线还是成面,gl.drawArrays()就是这样一个函数,这里告诉WebGL系统应该绘制一个点。

    3. 结果

    最终的运行结果很简单,在Chrome打开HelloPoint1.html,页面显示了一个绘制一个点的窗口:
    WebGL示例显示结果

    4. 参考

    本来部分代码和插图来自《WebGL编程指南》。

    代码和数据地址

    上一篇
    目录
    下一篇

    展开全文
  • WEBGL-工作原理

    2020-08-01 17:45:26
    WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点。 当你调用: var primitiveType = gl.TRIANGLES; var offset = 0; var count = 9...

    WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点。
    当你调用:

    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 9;
    gl.drawArrays(primitiveType, offset, count);
    

    这里的9表示“处理9个顶点”,所以将会有9个顶点被转换。
    在这里插入图片描述
      左侧是你提供的数据。顶点着色器(Vertex Shader)是你写进GLSL 中的一个方法,每个顶点调用一次,在这个方法中做一些数学运算后设置了一个特殊的gl_Position变量, 这个变量就是该顶点转换到裁剪空间中的坐标值,GPU接收该值并将其保存起来。

    假设你正在画三角形,顶点着色器每完成三次顶点处理,WebGL就会用这三个顶点画一个三角形。 它计算出这三个顶点对应的像素后,就会光栅化这个三角形,“光栅化”其实就是“用像素画出来” 的花哨叫法。对于每一个像素,它会调用你的片断着色器询问你使用什么颜色。 你通过给片断着色器的一个特殊变量gl_FragColor设置一个颜色值,实现自定义像素颜色。

    使用它们可以做出非常有趣的东西,但如你所见,到目前为止的例子中, 处理每个像素时片断着色器可用信息很少,幸运的是我们可以给它传递更多信息。 想要从顶点着色器传值到片断着色器,我们可以定义“可变量(varyings)”。

    一个简单的例子,将顶点着色器计算出的裁剪空间坐标从顶点着色器传递到片断着色器。

    我们来画一个简单的三角形,从之前的例子继续,让我们把矩形改成三角形。

    // 定义一个三角形填充到缓冲里
    function setGeometry(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array([
                 0, -100,
               150,  125,
              -175,  100]),
          gl.STATIC_DRAW);
    }
    

    我们只需要画三个顶点:

    // 绘制场景
    function drawScene() {
      ...
      // 绘制几何体
      var primitiveType = gl.TRIANGLES;
      var offset = 0;
      var count = 3;
      gl.drawArrays(primitiveType, offset, count);
    }
    

    然后在我们的顶点着色器中定义一个varying(可变量)用来给片断着色器传值。

    varying vec4 v_color;
    ...
    void main() {
      // 将位置和矩阵相乘
      gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
    
      // 从裁减空间转换到颜色空间
      // 裁减空间范围 -1.0 到 +1.0
      // 颜色空间范围 0.0 到 1.0
      v_color = gl_Position * 0.5 + 0.5;
    }
    

    在片断着色器中定义同名varying变量:

    precision mediump float;
    
    varying vec4 v_color;
    
    void main() {
      gl_FragColor = v_color;
    }
    

    WebGL会将同名的可变量从顶点着色器输入到片断着色器中。

    运行下面的代码:

    "use strict";
    
    function main() {
      // Get A WebGL context
      /** @type {HTMLCanvasElement} */
      var canvas = document.getElementById("canvas");
      var gl = canvas.getContext("webgl");
      if (!gl) {
        return;
      }
    
      // setup GLSL program
      var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    
      // look up where the vertex data needs to go.
      var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
    
      // lookup uniforms
      var matrixLocation = gl.getUniformLocation(program, "u_matrix");
    
      // Create a buffer.
      var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    
      // Set Geometry.
      setGeometry(gl);
    
      var translation = [200, 150];
      var angleInRadians = 0;
      var scale = [1, 1];
    
      drawScene();
    
      // Setup a ui.
      webglLessonsUI.setupSlider("#x", {value: translation[0], slide: updatePosition(0), max: gl.canvas.width });
      webglLessonsUI.setupSlider("#y", {value: translation[1], slide: updatePosition(1), max: gl.canvas.height});
      webglLessonsUI.setupSlider("#angle", {slide: updateAngle, max: 360});
      webglLessonsUI.setupSlider("#scaleX", {value: scale[0], slide: updateScale(0), min: -5, max: 5, step: 0.01, precision: 2});
      webglLessonsUI.setupSlider("#scaleY", {value: scale[1], slide: updateScale(1), min: -5, max: 5, step: 0.01, precision: 2});
    
      function updatePosition(index) {
        return function(event, ui) {
          translation[index] = ui.value;
          drawScene();
        }
      }
    
      function updateAngle(event, ui) {
        var angleInDegrees = 360 - ui.value;
        angleInRadians = angleInDegrees * Math.PI / 180;
        drawScene();
      }
    
      function updateScale(index) {
        return function(event, ui) {
          scale[index] = ui.value;
          drawScene();
        }
      }
    
      // Draw the scene.
      function drawScene() {
        webglUtils.resizeCanvasToDisplaySize(gl.canvas);
    
        // Tell WebGL how to convert from clip space to pixels
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    
        // Clear the canvas.
        gl.clear(gl.COLOR_BUFFER_BIT);
    
        // Tell it to use our program (pair of shaders)
        gl.useProgram(program);
    
        // Turn on the attribute
        gl.enableVertexAttribArray(positionAttributeLocation);
    
        // Bind the position buffer.
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    
        // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
        var size = 2;          // 2 components per iteration
        var type = gl.FLOAT;   // the data is 32bit floats
        var normalize = false; // don't normalize the data
        var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
        var offset = 0;        // start at the beginning of the buffer
        gl.vertexAttribPointer(
            positionAttributeLocation, size, type, normalize, stride, offset)
    
        // Compute the matrix
        var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
        matrix = m3.translate(matrix, translation[0], translation[1]);
        matrix = m3.rotate(matrix, angleInRadians);
        matrix = m3.scale(matrix, scale[0], scale[1]);
    
        // Set the matrix.
        gl.uniformMatrix3fv(matrixLocation, false, matrix);
    
        // Draw the geometry.
        var primitiveType = gl.TRIANGLES;
        var offset = 0;
        var count = 3;
        gl.drawArrays(primitiveType, offset, count);
      }
    }
    
    // Fill the buffer with the values that define a triangle.
    // Note, will put the values in whatever buffer is currently
    // bound to the ARRAY_BUFFER bind point
    function setGeometry(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array([
                 0, -100,
               150,  125,
              -175,  100]),
          gl.STATIC_DRAW);
    }
    
    main();
    

    当你移动,缩放,旋转三角形时,发现颜色随位置变化,不跟着三角形移动。

    回想一下,我们只计算了三个顶点,调用了三次顶点着色器,所以也只计算出了三个颜色值, 但是我们的三角形却有很多颜色,这就是称之为可变量的varying的原因啦!

    WebGL先获得顶点着色器中计算的三个颜色值,在光栅化三角形时将会根据这三个值进行插值。 每一个像素在调用片断着色器时,可变量的值是与之对应的插值。

    让我们从上例的三个顶点开始分析
    在这里插入图片描述
    我们的给顶点着色器施加了一个包含平移,旋转和缩放的的矩阵,并将结果转换到裁剪空间。 默认平移,旋转和缩放值为:平移 = 200, 150,旋转 = 0,缩放 = 1,所以这里只进行了平移。 画布大小(背景缓冲)为 400×300,所以三个顶点在裁剪空间中为以下坐标值。
    在这里插入图片描述
    同时将这些值转换到颜色空间中赋给我们定义的可变量v_color。
    在这里插入图片描述
    利用这三个值进行插值后传进每个像素运行的片断着色器中。
    在这里插入图片描述
    想要给片断着色器传值,我们可以先把值传递给顶点着色器然后再传给片断着色器。 让我们来画一个由两个不同颜色三角形组成的矩形。我们需要给顶点着色器添加一个属性值, 把值通过属性传递给它后它再直接传递给片断着色器。

    attribute vec2 a_position;
    attribute vec4 a_color;
    ...
    varying vec4 v_color;
    
    void main() {
       ...
      // 直接把属性值中的数据赋给可变量
      v_color = a_color;
    }
    

    现在要给WebGL提供要用的颜色。

    // 寻找顶点着色器中需要的数据
      var positionLocation = gl.getAttribLocation(program, "a_position");
      var colorLocation = gl.getAttribLocation(program, "a_color");
      ...
      // 给颜色数据创建一个缓冲
      var colorBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      // 设置颜色
      setColors(gl);
      ...
    
    // 给矩形的两个三角形
    // 设置颜色值并发到缓冲
    function setColors(gl) {
      // 生成两个随机颜色
      var r1 = Math.random();
      var b1 = Math.random();
      var g1 = Math.random();
    
      var r2 = Math.random();
      var b2 = Math.random();
      var g2 = Math.random();
    
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array(
            [ r1, b1, g1, 1,
              r1, b1, g1, 1,
              r1, b1, g1, 1,
              r2, b2, g2, 1,
              r2, b2, g2, 1,
              r2, b2, g2, 1]),
          gl.STATIC_DRAW);
    }
    

    在渲染的时候设置颜色属性:

    gl.enableVertexAttribArray(colorLocation);
    
    // 绑定颜色缓冲
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    
    // 告诉颜色属性怎么从 colorBuffer (ARRAY_BUFFER) 中读取颜色值
    var size = 4;          // 每次迭代使用4个单位的数据
    var type = gl.FLOAT;   // 单位数据类型是32位的浮点型
    var normalize = false; // 不需要归一化数据
    var stride = 0;        // 0 = 移动距离 * 单位距离长度sizeof(type) 
                           // 每次迭代跳多少距离到下一个数据
    var offset = 0;        // 从绑定缓冲的起始处开始
    gl.vertexAttribPointer(
        colorLocation, size, type, normalize, stride, offset)
    
    gl.enableVertexAttribArray(colorLocation);
    
    // 绑定颜色缓冲
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    
    // 告诉颜色属性怎么从 colorBuffer (ARRAY_BUFFER) 中读取颜色值
    var size = 4;          // 每次迭代使用4个单位的数据
    var type = gl.FLOAT;   // 单位数据类型是32位的浮点型
    var normalize = false; // 不需要归一化数据
    var stride = 0;        // 0 = 移动距离 * 单位距离长度sizeof(type) 
                           // 每次迭代跳多少距离到下一个数据
    var offset = 0;        // 从绑定缓冲的起始处开始
    gl.vertexAttribPointer(
        colorLocation, size, type, normalize, stride, offset)
    

    调整顶点的数量为6用来画两个三角形:

    // 画几何体
    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 6;
    gl.drawArrays(primitiveType, offset, count);
    

    运行下面的代码:

    "use strict";
    
    function main() {
      // Get A WebGL context
      /** @type {HTMLCanvasElement} */
      var canvas = document.getElementById("canvas");
      var gl = canvas.getContext("webgl");
      if (!gl) {
        return;
      }
    
      // setup GLSL program
      var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    
      // look up where the vertex data needs to go.
      var positionLocation = gl.getAttribLocation(program, "a_position");
      var colorLocation = gl.getAttribLocation(program, "a_color");
    
      // lookup uniforms
      var matrixLocation = gl.getUniformLocation(program, "u_matrix");
    
      // Create a buffer for the positons.
      var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      // Set Geometry.
      setGeometry(gl);
    
      // Create a buffer for the colors.
      var colorBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      // Set the colors.
      setColors(gl);
    
      var translation = [200, 150];
      var angleInRadians = 0;
      var scale = [1, 1];
    
      drawScene();
    
      // Setup a ui.
      webglLessonsUI.setupSlider("#x", {value: translation[0], slide: updatePosition(0), max: gl.canvas.width });
      webglLessonsUI.setupSlider("#y", {value: translation[1], slide: updatePosition(1), max: gl.canvas.height});
      webglLessonsUI.setupSlider("#angle", {slide: updateAngle, max: 360});
      webglLessonsUI.setupSlider("#scaleX", {value: scale[0], slide: updateScale(0), min: -5, max: 5, step: 0.01, precision: 2});
      webglLessonsUI.setupSlider("#scaleY", {value: scale[1], slide: updateScale(1), min: -5, max: 5, step: 0.01, precision: 2});
    
      function updatePosition(index) {
        return function(event, ui) {
          translation[index] = ui.value;
          drawScene();
        }
      }
    
      function updateAngle(event, ui) {
        var angleInDegrees = 360 - ui.value;
        angleInRadians = angleInDegrees * Math.PI / 180;
        drawScene();
      }
    
      function updateScale(index) {
        return function(event, ui) {
          scale[index] = ui.value;
          drawScene();
        }
      }
    
      // Draw the scene.
      function drawScene() {
        webglUtils.resizeCanvasToDisplaySize(gl.canvas);
    
        // Tell WebGL how to convert from clip space to pixels
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    
        // Clear the canvas.
        gl.clear(gl.COLOR_BUFFER_BIT);
    
        // Tell it to use our program (pair of shaders)
        gl.useProgram(program);
    
        // Turn on the position attribute
        gl.enableVertexAttribArray(positionLocation);
    
        // Bind the position buffer.
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    
        // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
        var size = 2;          // 2 components per iteration
        var type = gl.FLOAT;   // the data is 32bit floats
        var normalize = false; // don't normalize the data
        var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
        var offset = 0;        // start at the beginning of the buffer
        gl.vertexAttribPointer(
            positionLocation, size, type, normalize, stride, offset)
    
        // Turn on the color attribute
        gl.enableVertexAttribArray(colorLocation);
    
        // Bind the color buffer.
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    
        // Tell the color attribute how to get data out of colorBuffer (ARRAY_BUFFER)
        var size = 4;          // 4 components per iteration
        var type = gl.FLOAT;   // the data is 32bit floats
        var normalize = false; // don't normalize the data
        var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
        var offset = 0;        // start at the beginning of the buffer
        gl.vertexAttribPointer(
            colorLocation, size, type, normalize, stride, offset)
    
        // Compute the matrix
        var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
        matrix = m3.translate(matrix, translation[0], translation[1]);
        matrix = m3.rotate(matrix, angleInRadians);
        matrix = m3.scale(matrix, scale[0], scale[1]);
    
        // Set the matrix.
        gl.uniformMatrix3fv(matrixLocation, false, matrix);
    
        // Draw the geometry.
        var primitiveType = gl.TRIANGLES;
        var offset = 0;
        var count = 6;
        gl.drawArrays(primitiveType, offset, count);
      }
    }
    
    
    // Fill the buffer with the values that define a rectangle.
    // Note, will put the values in whatever buffer is currently
    // bound to the ARRAY_BUFFER bind point
    function setGeometry(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array([
              -150, -100,
               150, -100,
              -150,  100,
               150, -100,
              -150,  100,
               150,  100]),
          gl.STATIC_DRAW);
    }
    
    // Fill the buffer with colors for the 2 triangles
    // that make the rectangle.
    // Note, will put the values in whatever buffer is currently
    // bound to the ARRAY_BUFFER bind point
    function setColors(gl) {
      // Pick 2 random colors.
      var r1 = Math.random();
      var b1 = Math.random();
      var g1 = Math.random();
      var r2 = Math.random();
      var b2 = Math.random();
      var g2 = Math.random();
    
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array(
            [ r1, b1, g1, 1,
              r1, b1, g1, 1,
              r1, b1, g1, 1,
              r2, b2, g2, 1,
              r2, b2, g2, 1,
              r2, b2, g2, 1]),
          gl.STATIC_DRAW);
    }
    
    main();
    

    你可能注意到这两个三角形是纯色的。我们传递给每个三角形的顶点的颜色值是相同的, 所以我们传递的varying会被插值成相同的颜色,如果我们传递不同的颜色,就会看到插值的颜色。

    // 给矩形的两个三角形
    // 设置颜色值并发到缓冲
    function setColors(gl) {
      // 给每个顶点定义不同的颜色
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array(
            [ Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1]),
          gl.STATIC_DRAW);
    }
    

    运行下面的代码:

    "use strict";
    
    function main() {
      // Get A WebGL context
      /** @type {HTMLCanvasElement} */
      var canvas = document.getElementById("canvas");
      var gl = canvas.getContext("webgl");
      if (!gl) {
        return;
      }
    
      // setup GLSL program
      var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    
      // look up where the vertex data needs to go.
      var positionLocation = gl.getAttribLocation(program, "a_position");
      var colorLocation = gl.getAttribLocation(program, "a_color");
    
      // lookup uniforms
      var matrixLocation = gl.getUniformLocation(program, "u_matrix");
    
      // Create a buffer for the positons.
      var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      // Set Geometry.
      setGeometry(gl);
    
      // Create a buffer for the colors.
      var colorBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      // Set the colors.
      setColors(gl);
    
      var translation = [200, 150];
      var angleInRadians = 0;
      var scale = [1, 1];
    
      drawScene();
    
      // Setup a ui.
      webglLessonsUI.setupSlider("#x", {value: translation[0], slide: updatePosition(0), max: gl.canvas.width });
      webglLessonsUI.setupSlider("#y", {value: translation[1], slide: updatePosition(1), max: gl.canvas.height});
      webglLessonsUI.setupSlider("#angle", {slide: updateAngle, max: 360});
      webglLessonsUI.setupSlider("#scaleX", {value: scale[0], slide: updateScale(0), min: -5, max: 5, step: 0.01, precision: 2});
      webglLessonsUI.setupSlider("#scaleY", {value: scale[1], slide: updateScale(1), min: -5, max: 5, step: 0.01, precision: 2});
    
      function updatePosition(index) {
        return function(event, ui) {
          translation[index] = ui.value;
          drawScene();
        }
      }
    
      function updateAngle(event, ui) {
        var angleInDegrees = 360 - ui.value;
        angleInRadians = angleInDegrees * Math.PI / 180;
        drawScene();
      }
    
      function updateScale(index) {
        return function(event, ui) {
          scale[index] = ui.value;
          drawScene();
        }
      }
    
      // Draw the scene.
      function drawScene() {
        webglUtils.resizeCanvasToDisplaySize(gl.canvas);
    
        // Tell WebGL how to convert from clip space to pixels
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    
        // Clear the canvas.
        gl.clear(gl.COLOR_BUFFER_BIT);
    
        // Tell it to use our program (pair of shaders)
        gl.useProgram(program);
    
        // Turn on the position attribute
        gl.enableVertexAttribArray(positionLocation);
    
        // Bind the position buffer.
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    
        // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
        var size = 2;          // 2 components per iteration
        var type = gl.FLOAT;   // the data is 32bit floats
        var normalize = false; // don't normalize the data
        var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
        var offset = 0;        // start at the beginning of the buffer
        gl.vertexAttribPointer(
            positionLocation, size, type, normalize, stride, offset)
    
        // Turn on the color attribute
        gl.enableVertexAttribArray(colorLocation);
    
        // Bind the color buffer.
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    
        // Tell the color attribute how to get data out of colorBuffer (ARRAY_BUFFER)
        var size = 4;          // 4 components per iteration
        var type = gl.FLOAT;   // the data is 32bit floats
        var normalize = false; // don't normalize the data
        var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
        var offset = 0;        // start at the beginning of the buffer
        gl.vertexAttribPointer(
            colorLocation, size, type, normalize, stride, offset)
    
        // Compute the matrix
        var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
        matrix = m3.translate(matrix, translation[0], translation[1]);
        matrix = m3.rotate(matrix, angleInRadians);
        matrix = m3.scale(matrix, scale[0], scale[1]);
    
        // Set the matrix.
        gl.uniformMatrix3fv(matrixLocation, false, matrix);
    
        // Draw the geometry.
        var primitiveType = gl.TRIANGLES;
        var offset = 0;
        var count = 6;
        gl.drawArrays(primitiveType, offset, count);
      }
    }
    
    
    // Fill the buffer with the values that define a rectangle.
    // Note, will put the values in whatever buffer is currently
    // bound to the ARRAY_BUFFER bind point
    function setGeometry(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array([
              -150, -100,
               150, -100,
              -150,  100,
               150, -100,
              -150,  100,
               150,  100]),
          gl.STATIC_DRAW);
    }
    
    // Fill the buffer with colors for the 2 triangles
    // that make the rectangle.
    // Note, will put the values in whatever buffer is currently
    // bound to the ARRAY_BUFFER bind point
    function setColors(gl) {
      // Make every vertex a different color.
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array(
            [ Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1,
              Math.random(), Math.random(), Math.random(), 1]),
          gl.STATIC_DRAW);
    }
    
    main();
    

    可能不值一提的是上例还演示了使用多个属性并且通过顶点着色器向片断着色器传值。 如果你看了处理图片的例子, 那里面还用了另外一个属性传递纹理坐标。

    关于buffer和attribute的代码

    缓冲操作是在GPU上获取顶点和其他顶点数据的一种方式。 gl.createBuffer创建一个缓冲;gl.bindBuffer是设置缓冲为当前使用缓冲; gl.bufferData将数据拷贝到缓冲,这个操作一般在初始化完成。

    一旦数据存到缓冲中,还需要告诉WebGL怎么从缓冲中提取数据传给顶点着色器的属性。

    要做这些,首先需要获取WebGL给属性分配的地址,如下方代码所示:

    // 询问顶点数据应该放在哪里
    var positionLocation = gl.getAttribLocation(program, "a_position");
    var colorLocation = gl.getAttribLocation(program, "a_color");
    

    这一步一般也是在初始化部分完成。

    一旦知道了属性的地址,在绘制前还需要发出三个命令。

    gl.enableVertexAttribArray(location);
    

    这个命令是告诉WebGL我们想从缓冲中提供数据。

    gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
    

    这个命令是将缓冲绑定到 ARRAY_BUFFER 绑定点,它是WebGL内部的一个全局变量。

    gl.vertexAttribPointer(
        location,
        numComponents,
        typeOfData,
        normalizeFlag,
        strideToNextPieceOfData,
        offsetIntoBuffer);
    

    这个命令告诉WebGL从 ARRAY_BUFFER 绑定点当前绑定的缓冲获取数据。 每个顶点有几个单位的数据(1 – 4),单位数据类型是什么(BYTE, FLOAT, INT, UNSIGNED_SHORT, 等等…), stride 是从一个数据到下一个数据要跳过多少位,最后是数据在缓冲的什么位置。

    单位个数永远是 1 到 4 之间。

    如果每个类型的数据都用一个缓冲存储,stride 和 offset 都是 0 。 对 stride 来说 0 表示 “用符合单位类型和单位个数的大小”。 对 offset 来说 0 表示从缓冲起始位置开始读取。 它们使用 0 以外的值时会复杂得多,虽然这样会取得一些性能能上的优势, 但是一般情况下并不值得,除非你想充分压榨WebGL的性能。

    希望这些关于缓冲和属性的内容对你来说讲的足够清楚。

    vertexAttribPointer 中的 normalizeFlag 参数是什么意思?

    标准化标记(normalizeFlag)适用于所有非浮点型数据。如果传递false就解读原数据类型。 BYTE 类型的范围是从 -128 到 127,UNSIGNED_BYTE 类型的范围是从 0 到 255, SHORT 类型的范围是从 -32768 到 32767,等等…

    如果标准化标记设为true,BYTE 数据的值(-128 to 127)将会转换到 -1.0 到 +1.0 之间, UNSIGNED_BYTE (0 to 255) 变为 0.0 到 +1.0 之间,SHORT 也是转换到 -1.0 到 +1.0 之间, 但比 BYTE 精确度高。

    最常用的是标准化颜色数据。大多数情况颜色值范围为 0.0 到 +1.0。 使用4个浮点型数据存储红,绿,蓝和阿尔法通道数据时,每个顶点的颜色将会占用16字节空间, 如果你有复杂的几何体将会占用很多内存。代替的做法是将颜色数据转换为四个 UNSIGNED_BYTE , 其中 0 表示 0.0,255 表示 1.0。现在每个顶点只需要四个字节存储颜色值,省了 75% 空间。

    我们来修改之前代码实现。当我们告诉WebGL如何获取颜色数据时将这样

    // 告诉颜色属性如何从colorBuffer中提取数据 (ARRAY_BUFFER)
      var size = 4;                 // 每次迭代使用四个单位数据
      var type = gl.UNSIGNED_BYTE;  // 数据类型是8位的 UNSIGNED_BYTE 类型。
      var normalize = true;         // 标准化数据
      var stride = 0;               // 0 = 移动距离 * 单位距离长度sizeof(type) 
                                    // 每次迭代跳多少距离到下一个数据
      var offset = 0;               // 从缓冲的起始处开始
      gl.vertexAttribPointer(
          colorLocation, size, type, normalize, stride, offset)
    

    如下向缓冲添加数据:

    // 给矩形的两个三角形
    // 设置颜色值并发到缓冲
    function setColors(gl) {
      // 设置两个随机颜色
      var r1 = Math.random() * 256; // 0 到 255.99999 之间
      var b1 = Math.random() * 256; // 这些数据
      var g1 = Math.random() * 256; // 在存入缓冲时
      var r2 = Math.random() * 256; // 将被截取成
      var b2 = Math.random() * 256; // Uint8Array 类型
      var g2 = Math.random() * 256;
    
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Uint8Array(   // Uint8Array
            [ r1, b1, g1, 255,
              r1, b1, g1, 255,
              r1, b1, g1, 255,
              r2, b2, g2, 255,
              r2, b2, g2, 255,
              r2, b2, g2, 255]),
          gl.STATIC_DRAW);
    }
    

    结果:
    在这里插入图片描述

    展开全文
  • 一.笔者自述   对于原生WebGL的学习,相信对于很多搞前端图形开发的小伙伴的痛点是花了很多时间,却收效甚微;...那为什么我们还要学习原生的WebGL,原生的WebGL对于我们来说意味着什么?接下来笔者就以自...

    一.笔者自述       

     对于原生WebGL的学习,相信对于很多搞前端图形开发的小伙伴的痛点是花了很多时间,却收效甚微;好在现在存在诸如Three.js、Babylon.js、cesium.js等功能强大和齐全的WebGL第三方库;有了这些第三方库,我们可以用更少的代码构建出绚丽多彩的网络3D应用;那为什么我们还要学习原生的WebGL,原生的WebGL对于我们来说意味着什么?接下来笔者就以自身的学习经历回答这两个问题:

     首先,笔者在学习WebGL是做科研课题的需要,刚开始的时候也是很茫然,不知道怎么学,学了一段时间Three.js,又觉得必须把原生的WebGL学一下,不然不明白Three.js到底是怎么实现的(强迫症患者哈),于是就学习一段时间的原生WebGL,后来发现用Three.js做科研课题更加合适,里面提供有各种各样的功能,不用自己再去写(ps:如果自己去写这些功能,我可能毕不了业。。。),于是乎我的Three.js越来越进步,用的越来越熟悉;然而,近期身为即将毕业找工作的我,发现很多岗位都要求具备原生的WebGL开发能力,特别是h5渲染引擎的开发,所以峰回路转,我再一次选择学习原生WebGL,于是便决定把自己的学习经历和一些例子分享给广大爱好WebGL开发的道友们,希望我们一起度过原生WebGL的这个劫。

    其次,学习原生的WebGL,意味着我们的底层开发能力更上一层楼,如果你再学习一下计算机图形学的相关知识,我们也可以自己动手开发自己的渲染引擎,是不是觉得很高大上?尤其当我们掌握了原生WebGL开发的相关知识,回过头来看哪些第三方库,一切疑惑自然解开了,正所谓“初听不知曲中意, 再听已是曲中人”,你理解了,就自然不会再疑惑它们究竟是怎么实现的。

    二.WebGL开发需要准备什么

    1.WebGL简介

    关于WebGL的介绍,笔者在很早以前写过一篇基础介绍的文章,可以供大家参考:关于WebGL的一些基础性介绍

    2.开发要求

     编程软件:这里笔者使用的是WebStorm(看个人习惯,不做强制性要求),由于开发原生WebGL会涉及到着色器的编程,Webstorm提供了一个方便着色器代码编写的插件:GLSL Support;安装好这个插件后,着色器代码的关键字将会带上颜色,与普通变量区分,如下图:

           

    要安装这个插件,你可以自己到官网下载然后手动添加到webstorm插件里面,也可以在webstorm的setting(

    设置)>Plugins(插件)里面搜索GLSL Support,安装即可。

    运行环境:对于WebGL的支持程度各大浏览器都不一样,市面上主流的l谷歌、火狐、opera、safari等了浏览器都支持,如下图所示,具体可在:https://caniuse.com/#feat=webgl获得相关信息。我们可以看到各大浏览器对WebGL的支持情况,谷歌浏览器是支持度最好的,火狐其次;笔者选择了谷歌浏览器,原因是谷歌浏览器调试代码超级方便,而且谷歌浏览器也提供了一个WebStorm调试插件JetBrains IDE Support,可以说给程序的调试带来了极大的方便,这个插件也很好安装,有两个方法:1、上百度搜查并下载,手动拖拽扩展到谷歌浏览器的“扩展程序”里面即可;2、在谷歌应用商店搜索安装(打开谷歌商店需要翻墙);等笔者闲暇时间,一定写一篇关于这个插件的调试详细教程分享给大家,请大家多关注我的博客。

     编程语言:HTML、CSS、JavaScript;其中最为重要的是JavaScript,它是WebGL载体语言,就像C++于OpenGL的重要性一样,所以一定要具备一定的javascript编程基础。

     

    3.着色器语言:glsl 

    关于着色器语言的介绍,可以参考:着色器介绍;而对于着色器的编写一般有三种形式,第一种是将着色器代码单独写在一个文件,顶点着色器可命名为vShader.glsl, 片元着色器可用命名为Shader.glsl;第二种是将着色器代码以定义字符串变量的形式写在javascript代码内;第三种是将着色器代码卸载HTML文档的<script> </script>中间,将其表示为脚本。本教程用的第三种方法,如下图:

    4.着色器编译

    关于着色器的编译可以参考:着色器介绍,笔者在这里不再讲详细,直接上本教程要用的着色器创建,编译,链接代码,读者可以根据注释理解哈,在后面的章节我将讲解这个shader.js文件如何用于创建着、编译和链接着色器:

    //shader.js
    //创建着色器
    function createShader(gl, type, source) {
        let shader = gl.createShader(type);//创建着色器
        gl.shaderSource(shader, source);//附加着色器源文件到Shader
        gl.compileShader(shader);//编译着色器
        let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);//判断着色器是是否编译成功
        if(success) {
            return shader;
        } else {
            console.log("着色器创建失败!");
        }
    
        console.log(gl.getShaderInfoLog(shader));//获取着色器信息
        gl.deleteShader(shader);//删除着色器
    }
    
    //链接着色器程序
    function createProgram(gl, vertexShader, fragmentShader) {
        let program = gl.createProgram();//生成程序对象
        gl.attachShader(program, vertexShader);//向程序对象分配着色器
        gl.attachShader(program, fragmentShader);//向程序对象分配着色器
        gl.linkProgram(program);//链接着色器
    
        let success = gl.getProgramParameter(program, gl.LINK_STATUS);//判断着色器是否链接成功
        if(success) {
            return program;
        } else {
            console.log("着色器链接失败!");
        }
    
        console.log(gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
    }
    
    //初始化着色器
    function initShader(gl, vShaderText, fShaderText) {
        let vShader = createShader(gl, gl.VERTEX_SHADER, vShaderText);
        let fShader = createShader(gl, gl.FRAGMENT_SHADER, fShaderText);
    
        return createProgram(gl, vShader, fShader);
    }

    希望经过笔者在前面的这么多介绍,大家对WebGL有一个初步的认识,从下一节开始,将带领大家进行一些基础知识的学习和demo的开发。

    展开全文
  • 我看好WebGL

    2018-07-04 14:07:38
    未来都是未知的,虽然我们无法确定未来的科技会发展成什么样,人们的生活会发生什么样的变化,甚至我们以后使用的手机会变成什么样都是无法确定。... ... ... ...超低的开发成本成为的企业首选 强大的跨平台特性只要有浏览器...

    未来
    未来都是未知的,虽然我们无法确定未来的科技会发展成什么样,人们的生活会发生什么样的变化,甚至我们以后使用的手机会变成什么样都是无法确定。虽然我们无法预测长远的未来,但是,我们能够看清将会发生的一些变化,这其中就就有HTML5。

    HTML5

    HTML5的优势现在已经很明显,在这里先列几个重点:

    • 超低的开发成本成为的企业首选
    • 强大的跨平台特性只要有浏览器就能查看
    • 实时更新页面抛弃版本升级问题
    • 多媒体特性可以直接播放视频和音频,不需要再安装flash插件
    • 自适应的设计可兼容pc和移动端
    • 画布特性可以直接在浏览器绘制图形

    html5

    HTML5虽然向前的兼容性有一定的问题,不兼容ie,低版本浏览器兼容问题。但是,我们必须顺应时代的发展,才能够屹立不倒,即使你现在不需要,不代表你在以后用不到。HTML5强大的特性时刻在提醒我们,它就是web的未来。

    既然HTML5这么强大,那么我们能直接用浏览器进行3D渲染吗?答案是:可以。WebGL就是来解决浏览器和显卡之间的问题而诞生的,我可以通过直接用javaScript进行图形渲染,再通过HTML5这个平台强大的特性真正实现了一次开发,多平台适用的愿望。

    WebGL

    WebGL (Web图形库) 是一种JavaScript API,用于在任何兼容的Web浏览器中呈现交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0紧密相符合的API,可以在HTML5 元素中使用。

    WebGL虽然是基于OpenGL扩展而来的,但是它使用在了HTML5的浏览器中,这意味着HTML5的那些优势都能够被WebGL直接使用,多个平台,多种设备直接使用,一个网址打开即可查看效果统统现在可以依靠HTML5直接实现!

    那我们用WebGL以后能够做什么?

    • 数据可视化
    • WebAR,ar
    • 3D物理模型
    • 游戏
    • 3D动画

    上面的每一样,都是足够我们用很长的时间来研究的方向。WebGL现在的技术已经足以满足了我们所需要的技术需求,只要我们确定前方的路线,迈步向前即可。

    我看好WebGL主要是因为WebGL作为3D图形渲染工具,它是最直接的,可以直接浏览器查看效果;它是简单的,WebGL有很多库比如Three.js、Babylon等甚至我们不需要专业知识都可以制作出3D效果;它是成本偏低的,由于库的支持相对简单入手,很多企业都将WebGL作为招聘首选;它是未来几年的发展的重点,搭上了HTML5发展的高速车,这几年很多企业会将C/S架构改为B/S架构,近些年的WebGL的资源需求会越来越多。

    Three.js

    Three.js作为以WebGL封装的3D库,它的优势有哪些:

    1. 直接使用前端熟悉的JavaScript进行开发
      WebGL作为运行在浏览器中的一套协议,我们可以不需要进行C语言等相关的知识的学习,只需要使用我们熟悉的JavaScript语言就可以进行3D开发。

    2. 对底层WebGL进行合理封装
      WebGL直接用于开发还是有一定难度,尤其是对OpenGL图形没有研究的话,开发WebGL会难上加难。但是Three.js很好的解决了这个问题,降低开发难度,并且只需要更少的代码就可以实现我们所需要的效果。

    3. 保留底层开发的特性
      虽然Three.js对WebGL底层进行了很好的封装,得益于Three.js的合理的封装,我们在Three.js开发当中也可以直接进行shader、顶点数据处理等的原生开发。

    4. 结构严谨灵活易于扩展
      Three.js基于面向对象的思维设计,结构严谨并且灵活,大大降低各个模块之间的耦合性,不会产生相互依赖,增加功能或者修改代码都可以很简单的实现。

    说到Three.js,不得不提一下WebGL的现在的尴尬局面,WebGL是基于OpenGL的一个版本演变过来的,所以OpenGL的开发者有一定的学习优势,但是还得必须学习一门JavaScript语言,再加上专门研究图形对互联网前端也需要一定的了解程度,无形之中增加的学习成本。

    作为前端开发者虽然熟悉前端的内容,但是由于对图形学的研究欠缺,对从前端转行到WebGL开发增加了很多难度。所以现在的市场上有一种奇怪的现象,WebGL的开发人员匮乏,很多公司都愿意招收没有工作经验的WebGL开发人员。

    Three.js对原生的WebGL进行封装,采用了面向对象的思维,降低了前端开发入门WebGL的难度。只要我们熟悉一下Three.js的封装的思路,就能够很快的上手并且快速开发出产品。

    课程介绍

    《Three.js基础入门》作为入门课程,重点在于基础讲解,协助初学者了解Three.js的数据结构,基础的API以及相关的辅助插件使用和配置。来帮助初学者达到快速入门的目的。

    课程特色

    • 语言通俗易懂:全文使用了通俗易懂的语言将知识讲解清晰透彻,即使小白也能明白其中原理。
    • 数据接口清晰:课程内将使用到的接口功能以及如何使用清晰的罗列,以达到复用。
    • 案例结尾:每一节的内容都会制作当节内容的案例方便大家查看效果以及学习。
    • 快速上手:从头带领大家从基础到进阶、实战,学完本课程可以轻松实现小案例。

    本课程学完之后,大家可以对Three.js有一定认识,能够将Three.js应用到项目当中,通过面向对象的思维将Three.js的代码融合到现有的代码当中。

    展开全文
  • WebGL教程(电子书)

    2019-12-25 16:10:07
    WebGL教程(电子书) 最近准备编写一本WebGL快速入门的电子书教程,电子书编写完整后,会免费开源到我的个人技术博客,目前还在编写中,已经写好的会把电子书每一小节以文章的形式发布才CSDN上。 第一章、WebGL零基础...
  • 作者:窦金兰— 字节跳动IES前端工程师希望通过这篇文章,大家能够对 OpenGL/WebGL 有一个基础的认识~~OpenGL定义OpenGL 是一套规范,...
  • WebGL 技术储备指南...WebGL 虽然还未有广泛应用,但极具潜力和想象空间。本文是我学习 WebGL 时梳理知识脉络的产物,花点时间整理出来与大家分享。 示例WebGL 很酷,有以下 demos 为证: ...
  • WebGL

    2019-08-30 10:20:58
    WebGL是什么东西? WebGL是Web上的3D图形的新标准,它是专用于绘制2D图形和交互式3D图形的目的,它是OpenGL ES 2.0库,用于手机和其他移动设备的低级3D的API衍生,WebGL提供ES2.0(嵌入式系统)类似的功能并在现在3D...
  • 终于开始WebGL的示例了,...... 开始    使用WebGL的步骤,很简单:  1. 获得WebGL的渲染环境(也叫渲染上下文)。  2. 发挥你的想象力,利用《WebGL参考手册》中的函数,参考《OpenGL ES 2.0编程指南》和...
  • WEBGL编程指南pdf

    2020-07-28 23:31:03
    原书名:WebGL Programming Guide: Interactive 3D Graphics Programming with WebGL (OpenGL) 原出版社: Addison-Wesley Professional 作者: (美)Kouichi Matsuda Rodger Lea(松田浩一,罗杰.李) 译者: 谢光磊 ...
  • Three.js和其它webgl框架

    2018-08-24 11:23:08
    什么是WEBGLWebGL (Web图形库) 是一种JavaScript API,用于在任何兼容的Web浏览器中呈现交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0紧密相符合的API,可以在HTML5 元素中使用。(MDN...
  • 原书名:WebGL Programming Guide: Interactive 3D Graphics Programming with WebGL (OpenGL) 原出版社: Addison-Wesley Professional 作者: (美)Kouichi Matsuda Rodger Lea(松田浩一,罗杰.李) 译者: 谢光磊 ...
  • WebGL 是一项在网页浏览器呈现3D画面的技术,有别于过去需要安装浏览器插件,通过 WebGL 的技术,只需要编写网页代码即可实现3D图像的展示。WebGL 可以为 Canvas 提供硬件3D加速渲染,这样 Web 开发人员就...
  • webGL编程示例源码

    2020-06-30 20:22:57
    WebGL编程指南》的主要篇幅讲解了WebGL 原生API 和三维图形学的基础知识,包括渲染管线、着色器、矩阵变换、着色器编程语言(GLSL ES)等等,也讲解了使用WebGL 渲染三维场景的一般技巧,如光照、阴影、雾化等等。...
  • 为了方便读者学习和阅读,这篇文章主要是列出笔者撰写的原生WebGL博文的链接: 一.WebGL二维几何开发 1.原生webgl学习(一) 原生WebGL学习和入门引言 2.原生webgl学习(二) 用WebGL绘制一个三角形 3.原生webgl...
1 2 3 4 5 ... 20
收藏数 25,111
精华内容 10,044
关键字:

webgl