首页|行业资讯|企业名录|周边产品|数字城市|增强现实|工业仿真|解决方案|虚拟医疗|行业仿真|图形处理|军事战场
资讯首页
行业资讯 >> 学习教程>>正文
WebGL 简单范例 代码
2010年5月31日    评论:    分享:

    转自博客:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=166

 

    在上一篇文章,算是很简略地介绍了 WebGL 以及目前能让 WebGL 正常运作的浏览器;而这一篇,就是来写一个最简单的 WebGL 程序了~在这个例子里,就是单纯地在黑底的框框内,画出一个白色的三角型(如右图);基本上是以类似 2D 的模式在画,也不会考虑到 3D 的投影。

 

    不过要先强调的是,要写 WebGL 的话,基本上应该要了解:

 

    JavaScript 与网页的 DOM 的操作

 

    OpenGL ES 2.0 的程序架构

 

    如果对 OpenGL ES 2.0 完全没碰过的话,至少也要对 OpenGL 3.0 或是 OpenGL 2.x + GLSL 有概念才行。

 

    如果都没有的话,建议先去稍微研究一下这些东西,对于学习 WebGL 会比较好。

 

    而对于一个 WebGL 的程序,Heresy 会把他分为三个部份:

 

    HTML 部分,包含要绘制内容的 canvas 组件

 

    WebGL JavaScript 程序部分

 

    WebGL 程序所需使用的 GLSL 程序的部分(包含 vertex shader fragment shader

 

    首先,先讲最简单的 HTML 的部分。由于这部分除了网页本身的内容外,就只是单纯地需要额外配置一个 <canvas>,来指定 WebGL 的区域,所以其实相当地单纯。下方就是一个很简单的例子:

 

    <body onload="RunWebGL();"> <canvas id="canvas_object" width="500" height="500"></canvas></body>这样写的话,就是会在网页里产生一个 id 是「canvas_object」、大小是 500 x 500 的画布,可以用来呈现 WebGL 的绘制结果。

 

    另外,这个网页也会在读取完成后,就自动执行 RunWebGL() 这个 JavaScript 的函式、开始执行 WebGL 的程序;这个函式的性质接近一般 C/C++ 程序的 main(),也就是前面所提的第二部分。他的内容如下:

 

    function RunWebGL(){ 

 

      // get WebGL Context 

         var canvas = document.getElementById( "canvas_object" ); 

         g_WebGLContext = canvas.getContext( "experimental-webgl" );   // setup viewport 

         g_WebGLContext.viewport(0, 0, canvas.width, canvas.height);  // set clear color 

         g_WebGLContext.clearColor( 0.0, 0.0, 0.0, 1.0 );   // create shader and data 

         CreateShader(); 

         CreateData();   // main loop 

        setInterval( drawScene, 30 );

 

      }

 

    而在这边比较特别的,就是在编写 WebGL 程序时,必须先透过 DOM 来取得要使用的 Canvas、并透过他产生 WebGL rendering context,也就是函式一开始标示成黄色的区块。

 

    其中,g_WebGLContext 是一个全域变量,是用来指向 WebGL rendering context 的。而在程序上,就是先透过 DOM 找到 id 为「canvas_object」的组件,再透过 canvas getContext() 来取得 WebGL rendering context;不过要稍微注意的是,目前是使用「experimental-webgl」,但是以后等到 WebGL 正式版的时候,应该会改成使用「webgl」。

 

    而由于这是一个很简单的范例,所以在取得 WebGL Context 后,就只有简单的设定 viewport clear color,其它都使用 OpenGL ES 的默认值,然后就开始建立所需的 shader program 和对象数据、然后进入 main loop 了~

 

    由于 OpenGL 3.0 / OpenGL ES 2.0 基本上已经将 fixed pipeline 的东西丢了,所以连同在 WebGL 环境里,都是一定要自己编写 Vertex Shader Fragment Shader 的!

 

    而在 WebGL 里,每一个 shader 程序,都是一个独立的 <script>、藉由不同的 id type 来做区隔;id 基本上就是自己取的、用来识别用的名称,而 type 则有「x-shader/x-vertex」和「x-shader/x-fragment」两种。

 

    下面就是一个简单的 vertex shader 的范例,他基本上不会做任何坐标的转换、投影,只会直接把每一个 vertex 的位置信息转换为 vec4 的型态,继续往下传:

 

    <script id="vs_01" type="x-shader/x-vertex"> 

 

       attribute vec3 aVertexPosition;  

       void main(void) 

 

       {   

 

       gl_Position = vec4( aVertexPosition, 1 ); 

 

       }

 

    </script>

 

    而下方则是一个简单的 fragment shader,他会把所有的 fragment 的颜色都填为白色:

 

   <script id="fs_01" type="x-shader/x-fragment"> 

 

       void main(void) 

      

       {    gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ); 

 

       }

 

    </script>

 

    在上面这样写了之后,基本上就是写好了最单纯的 vertex shader fragment shader 了。

 

    而要使用这两个 shader 程序,在 JavaScript 程序的部分还需要先透过 DOM 的架构,把他们的程序代码读取出来成一个字符串,这部分 Heresy 是把他写成一个函式:

 

    function getShaderSource( id )

 

      {  // get shader script element 

 

         var shaderScript = document.getElementById( id ); 

 

         if( !shaderScript )    return null;   // get shader program string 

 

         var str = "";  var childNode = shaderScript.firstChild; 

 

         while( childNode ) 

             {    

 

              if( childNode.nodeType == childNode.TEXT_NODE )     

              str += childNode.textContent;   

              childNode = childNode.nextSibling; 

 

                }

 

           return str;}

 

     这边的程序,会先找到指定 id element,然后依序地把他里面的 text node 的数据读出来,并且累加到 str 这个字符串里,最后再传出来。

 

     而在取得 shader 程序的程序代码之后,还需要再以 OpenGL shader 的处理程序,进行编译、连结等动作;这边也就是在 RunWebGL() 中呼叫到的 CreateShader() 函式了~

 

     1: function CreateShader() 

     2: { 

     3:   // create vertex shader 

     4:   var vsSource = getShaderSource( "vs_01" ); 

     5:   var vertexShader = g_WebGLContext.createShader( g_WebGLContext.VERTEX_SHADER ); 

     6:  

     7:   // compile vertex shader 

     8:   g_WebGLContext.shaderSource( vertexShader, vsSource ); 

     9:   g_WebGLContext.compileShader( vertexShader );

     10:   if( !g_WebGLContext.getShaderParameter( vertexShader, g_WebGLContext.COMPILE_STATUS ) )

     11:     alert( g_WebGLContext.getShaderInfoLog( vertexShader ) );

     12: 

     13:   // create fragment shader

     14:   var fsSource = getShaderSource( "fs_01" );

     15:   var fragmentShader = g_WebGLContext.createShader( g_WebGLContext.FRAGMENT_SHADER );

     16: 

     17:   // compile fragment shader

     18:   g_WebGLContext.shaderSource( fragmentShader, fsSource );

     19:   g_WebGLContext.compileShader( fragmentShader );

     20:   if( !g_WebGLContext.getShaderParameter( fragmentShader, g_WebGLContext.COMPILE_STATUS ) )

     21:     alert( g_WebGLContext.getShaderInfoLog( fragmentShader ) );

     22: 

     23:   // create shader program

     24:   g_ShaderProgram = g_WebGLContext.createProgram();

     25:   g_WebGLContext.attachShader( g_ShaderProgram, vertexShader );

     26:   g_WebGLContext.attachShader( g_ShaderProgram, fragmentShader );

     27:   g_WebGLContext.linkProgram( g_ShaderProgram );

     28: 

     29:   if( !g_WebGLContext.getProgramParameter( g_ShaderProgram, g_WebGLContext.LINK_STATUS ) )

     30:   {

     31:     alert( "Shader 初始化失败" );

     32:     return;

     33:   }

     34: 

     35:   g_WebGLContext.useProgram( g_ShaderProgram );

     36: }

 

     在这个函式里,就是各别针对 vertex shader fragment shader,依序地读取 shader 的程序代码、建立 shader 对象、编译 shader 了;而在这两个 shader object 都建立完成后,就再将这两个 shader object attach shader program(全域变量 g_ShaderProgram)上,并且 link、使用这个包含了 vs_01 以及 fs_01 shader program 了。而如果都没出问题的话,在执行完 CreateShader() 后,也就完成了 WebGL shader 的配置了。

 

     接下来,就是 CreateData()、也就是建立要画的三角型的部分了;这部分也是相当简单,就是建立一个 vertex array,里面放三个只有位置信息的 vertex 了~

 

     function CreateData()

     { 

        g_VertexPositionAttribute = g_WebGLContext.getAttribLocation( g_ShaderProgram, "aVertexPosition" ); 

        g_WebGLContext.enableVertexAttribArray( g_VertexPositionAttribute );   // create scene data 

        g_VertexPositionBuffer = g_WebGLContext.createBuffer(); 

        g_WebGLContext.bindBuffer( g_WebGLContext.ARRAY_BUFFER, g_VertexPositionBuffer ); 

        var vertices = [   0.0,  0.8, 0.0,                    -0.8, -0.8, 0.0,                     0.8, -0.8, 0.0 ]; 

        g_WebGLContext.bufferData( g_WebGLContext.ARRAY_BUFFER, new WebGLFloatArray(vertices), g_WebGLContext.STATIC_DRAW);

 

     }

 

     在这段程序里,主要的动作是:

 

     透过 getAttribLocation() 取得 g_ShaderProgram 这个 shader program 中,名称为「aVertexPosition」的 attribute 地址(vertex shader 的)

 

     使用 enableVertexAttribArray() enable g_VertexPositionAttribute 这个 vertex attribute array

 

     使用 createBuffer() 建立一个新的 buffer

 

     使用 bindBuffer() g_VertexPositionBuffer 设定为目前使用的 buffer

 

     建立三个 vertex 的位置信息,分别为 (0, 0.8, 0)(-0.8, -0.8, 0)(0.8, -0.8, 0)

 

     vertices 的资料,写到目前 bind buffer 里(也就是 g_VertexPositionBuffer

 

     而在这些需要的数据都建立完成后,就是 RunWebGL() 的最后,执行 main loop 的部分了~

 

     setInterval( display, 30 );这行程序基本上就是透过 JavaScript 的定时器,每 30ms 去执行一次 display() 这个函式,来做画面的定时更新了;display() 的程序代码内容,则如下所列:

 

     function display()

     {

       g_WebGLContext.clear( g_WebGLContext.COLOR_BUFFER_BIT );  

       g_WebGLContext.bindBuffer( g_WebGLContext.ARRAY_BUFFER, g_VertexPositionBuffer ); 

       g_WebGLContext.vertexAttribPointer( g_VertexPositionAttribute, 3, g_WebGLContext.FLOAT, false, 0, 0 ); 

       g_WebGLContext.drawArrays( g_WebGLContext.TRIANGLES, 0, 3 );

 

    }

 

    而内容的话,主要就是先将现有画面的 color 都清除后,再重新画上的 vertex array 了~

 

    到了这边,最简单的 WebGL 程序也算完成了~原始码的部分,可以到这里下载,基本上因为都写在一起,所以也就只有一个 HTML 檔。

 

 

标签:WebGL范例代码
上一篇:WebGL入门—主流浏览器设置
下一篇:球幕与环幕联动系统
网友评论:WebGL 简单范例 代码
评论
留名: 验证码:
您可能还需要关注一下内容:
·ChinaJoy2016再升级,泛娱乐连接新发展
·我的900X3D为什么怀孕了,三星你要给个说法
·布局VR!幻维世界产业基金再出手!这次是幻维互动!
·聚焦eSmart:智能硬件必将崛起,科技改变数字生活
· Oculus Rift 消费者版 CV1拆解
·第二空间摘得2016CITE创新产品与应用奖
·幻维世界领投幻视 VR 游戏
·幻眼-提供最先进的增强现实营销解决方案
·中国VR(眼镜)距离Oculus还有几条街?
·国产VR电影投资百万 回报堪忧
☏ 推荐产品

Ladybug5全景
商家:力方国际

ProJet®
商家:力方国际

ProJet®
商家:视科创新

Premium1.5
商家:视科创新

巴可HDX主动立体投
商家:德浩科视

巴可HDF-W26投
商家:德浩科视

巴可30000流明2
商家:德浩科视

巴可4万流明2K投影
商家:德浩科视
☞ 外设导航
☏ 企业名录
【广州】中科院广州电子技术有限公司
【北京】第二空间(北京)科技有限公司
【北京】幻维世界(北京)网络科技有限公司
【厦门】厦门惠拓动漫科技有限公司
【厦门】厦门幻眼信息科技有限公司
【深圳】深圳南方百捷文化传播有限公司
【北京】北京思源科安信息技术有限公司
【上海】上海殊未信息科技有限公司
【北京】北京赢康科技开发有限公司
【武汉】武汉科码软件有限公司
友情链接 关于本站 咨询策划 行业推广 广告服务 免责声明 网站建设 联系我们 融资计划
北京第三维度科技有限公司 版权所有 京ICP备09001338
2008-2016 Beijing The third dimension Inc. All Rights Reserved.
Tel:010-57255801 Mob:13371637112(24小时)
Email:d3dweb@163.com  QQ:496466882
扫一扫 第三维度
官方微信号