【WebGL初学系列之二】WebGL第一个程序,三角形

来源:互联网 发布:kingwear智能手表软件 编辑:程序博客网 时间:2024/06/12 01:29

   开始WebGL程序之前,还是得进行一些理论上的知识,不然会让自己的代码写得不明不白。上一篇文章就是写得关于WebGL的一些基础知识http://nbcoders.com/detail/156

    第一:首先获取WebGL上下文。

    第二:编写顶点着色器

    第三:开始一些自己的绘制工作(调用WebGL API)

    这里我们就以画一个三角形为例子,开始我们的WegGL程序吧。

    首先获取WebGL的上下文环境,也就是渲染环境,我们要利用HTML5的canvas元素。所以我们这里要新建一个Canvas元素,这里canvas可以对应一个WebGL的渲染环境,也可以对应一个canvas-2d的渲染环境。编写如下代码:

    <html>            <body>            <canvas id="webglCanvas" style="border:1px solid blue;" width='600px' height='600px'></canvas>        </body>    </html>

    可以简单运行试试效果,有个蓝色的细框。接下来我们要获取WebGL的渲染区域,然后操作WebGL渲染区域。这里通过canvas的getContext方法获取WebGL的上下文环境。

    var webglContext = document.getElementById().getContex("experimental-webgl");

    这里完整代码如下:

 function initCanvas(canvasId) {            var canvas = document.getElementById(canvasId);            var context = null;            try{                 context = canvas.getContext("experimental-webgl");            }catch(ex)            {                 alert(ex.toString());            }            if(!context)            {                 alert("我靠,你的浏览器不支持WebGL,换个浏览器吧!");                 return null;            }            return context;       }
   获取了绘图上下文之后,接下来就是要开始写shader程序和绘制相关代码了。在编写Shader代码前,先简单回顾介绍一下着色器。着色器有两种,顶点着色器和片段着色器。简单点的来说,顶点着色器就是负责处理顶点的位置,片段着色器就是用来处理顶点的颜色。前面已经介绍过顶点着色器和片段着色器,废话就不多说了,来点演示的。顶点着色器和片段着色器的shader代码如下:

<span style="white-space:pre"></span><script id="shader-vs" type="x-shader/x-vertex">            attribute vec3 v3Position;            void main(void)            {                gl_Position = vec4(v3Position, 1.0);            }        </script>        <script id="shader-fs" type="x-shader/x-fragment">            void main(void)            {               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);            }        </script>
  上面一段代码只是shader程序,要创建着色器还是要通过WebGL API,这里着色器用createShader函数创建,该函数的参数只有一个,用于控制创建着色器的类型,是一个枚举类型。顶点着色器用VERTEX_SHADER表示,片段着色器用FRAGMENT_SHADER表示,最后函数返回一个创建好的对象。再来解释一下上面那段shader代码。当我们创建好着色器之后,我们还需要将3d内容转换成要绘制显示的内容。Shader程序用字符串来表示的,所以,这里写了一个解析器来解析Shader代码,将其转换。

             //解析Shader代码             function shaderSourceFromScript(scriptID)             {                 var shaderScript = document.getElementById(scriptID);                 if (shaderScript == null) return "";                 var sourceCode = "";                 var child = shaderScript.firstChild;                 while (child)                 {                     if (child.nodeType == child.TEXT_NODE) sourceCode += child.textContent;                     child = child.nextSibling;                 }                 return sourceCode;             }
当然,这里我们并不能说就完事了,因为我们只是刚好解析好Shader代码,接下来的事情是要对Shader代码进行编译和链接。着色器的编译源码的WebGL Api是compileShader(shaderObject),链接API为attachShader(programObject, shaderObject),这里也不对这个函数进行细说了,查查就知道。编译和链接的代码如下:

            //编译shader程序             function compileShader(context, shaderVertexCode, shaderFragmentCode, vertexShaderobject, fragmentShaderObject)             {                 //将shader代码装载到shader Object中                 context.shaderSource(vertexShaderobject, shaderVertexCode);                 context.shaderSource(fragmentShaderObject, shaderFragmentCode);                 //编译shader代码                 context.compileShader(vertexShaderobject);                 context.compileShader(fragmentShaderObject);                 //检查是否编译成功                 if (!context.getShaderParameter(vertexShaderobject, context.COMPILE_STATUS))                 {                     alert("error:vertexShaderObject");                     return;                 }                 if (!context.getShaderParameter(fragmentShaderObject, context.COMPILE_STATUS))                 {                     alert("error:framentShaderObject");                     return;                 }             }                          //链接Shader程序             function linkShader(context, programObj, vertexShaderObj, fragmentShaderObj)             {                 //一个程序对象只能并且必须附带一个顶点着色器和片段着色器                 context.attachShader(programObj, vertexShaderObj);                 context.attachShader(programObj, fragmentShaderObj);                 //将着色器变量关联到一个属性索引                 context.bindAttribLocation(programObj, v3PositionIndex, "v3Position");                 context.linkProgram(programObj);                 //检查是否链接成功                 if (!context.getProgramParameter(programObj, context.LINK_STATUS))                 {                     alert("error:ProgramObject");                     return;                 }                 return programObj;             }                            //初始化Shader程序               function initShader(context)               {                //创建shaderobject                vertexShaderObj = context.createShader(context.VERTEX_SHADER);                fragmentShaderObj = context.createShader(context.FRAGMENT_SHADER);                //编译shader                compileShader(context, shaderSourceFromScript("shader-vs"), shaderSourceFromScript("shader-fs"), vertexShaderObj, fragmentShaderObj);                //链接shader                //创建一个程序对象                programObj = context.createProgram();                programObj = linkShader(context, programObj, vertexShaderObj, fragmentShaderObj);                //context指定使用shader程序                context.useProgram(programObj);               }
 经过这步之后,Shader程序就已经编译和链接好了。接下来,我们要想渲染出我们想要的图形来,我们还需要向WebGL提供我们相应的数据。所以我们接下来的操作是建立缓冲,用来保存顶点数据。这里的第一个程序,只需要保存一个三角形的顶点位置,因为基本每一句我都写了注释,所以,直接上代码:

            //初始化顶点数据              function initVextexData(context)              {                  //顶点坐标                  var jsArrayData = [                       0.0, 1.0, 0.0,                      -1.0, 0.0, -1.0,                       1.0, 0.0, 0.0                  ]                  //创建一个webgl能够访问的缓冲                  var triangleBuffer = context.createBuffer();                  //绑定buffer                  context.bindBuffer(context.ARRAY_BUFFER, triangleBuffer);                  //将js数据拷贝到buffer上                  context.bufferData(context.ARRAY_BUFFER, new Float32Array(jsArrayData), context.STATIC_DRAW);                  return triangleBuffer;              }
 好吧,还有一步,绘制场景(即绘制所以对象)

       function start()           {                //初始化webgl渲染区域                webglContext = initCanvas("webglCanvas");                               //初始化shader程序                initShader(webglContext);                //初始化顶点数据                triangleBuffer = initVextexData(webglContext);                //开始绘制                //清空屏幕                webglContext.clearColor(0.0, 0.0, 0.0, 1.0);                webglContext.clear(webglContext.COLOR_BUFFER_BIT);                 //webgl中顶点数组数据可能N个,我们这里需要告诉webgl我们用哪一个,                //绑定一个顶点数组数据                webglContext.bindBuffer(webglContext.ARRAY_BUFFER, triangleBuffer);                //启动关联索引上的数据                webglContext.enableVertexAttribArray(v3PositionIndex);                //指定关联索引上的数据元素或者元素数据的正确信息                webglContext.vertexAttribPointer(v3PositionIndex, 3, webglContext.FLOAT, false, 0, 0);                //绘制数据                webglContext.drawArrays(webglContext.TRIANGLES, 0, 3);       }
最后全部的代码如下:

<html><head> <script id="shader-vs" type="x-shader/x-vertex">            attribute vec3 v3Position;            void main(void)            {                gl_Position = vec4(v3Position, 1.0);            }        </script>        <script id="shader-fs" type="x-shader/x-fragment">            void main(void)            {               gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);            }        </script><script type="text/javascript">var webglContext = null;var vertexShaderObj = null;var fragmentShaderObj = null;var programObj = null;var v3PositionIndex = null;var triangleBuffer = null;             //解析Shader代码             function shaderSourceFromScript(scriptID)             {                 var shaderScript = document.getElementById(scriptID);                 if (shaderScript == null) return "";                 var sourceCode = "";                 var child = shaderScript.firstChild;                 while (child)                 {                     if (child.nodeType == child.TEXT_NODE) sourceCode += child.textContent;                     child = child.nextSibling;                 }                 return sourceCode;             }             //编译shader程序             function compileShader(context, shaderVertexCode, shaderFragmentCode, vertexShaderobject, fragmentShaderObject)             {             //将shader代码装载到shader Object中                 context.shaderSource(vertexShaderobject, shaderVertexCode);                 context.shaderSource(fragmentShaderObject, shaderFragmentCode);                 //编译shader代码                 context.compileShader(vertexShaderobject);                 context.compileShader(fragmentShaderObject);                 //检查是否编译成功                 if (!context.getShaderParameter(vertexShaderobject, context.COMPILE_STATUS))                 {                     alert("error:vertexShaderObject");                     return;                 }                 if (!context.getShaderParameter(fragmentShaderObject, context.COMPILE_STATUS))                 {                     alert("error:framentShaderObject");                     return;                 }             }             //链接Shader程序             function linkShader(context, programObj, vertexShaderObj, fragmentShaderObj)             {                 //一个程序对象只能并且必须附带一个顶点着色器和片段着色器                 context.attachShader(programObj, vertexShaderObj);                 context.attachShader(programObj, fragmentShaderObj);                 //将着色器变量关联到一个属性索引                 context.bindAttribLocation(programObj, v3PositionIndex, "v3Position");                 context.linkProgram(programObj);                 //检查是否链接成功                 if (!context.getProgramParameter(programObj, context.LINK_STATUS))                 {                     alert("error:ProgramObject");                     return;                 }                 return programObj;             }            function initShader(context){//创建shaderobjectvertexShaderObj = context.createShader(context.VERTEX_SHADER);fragmentShaderObj = context.createShader(context.FRAGMENT_SHADER);//编译shadercompileShader(context, shaderSourceFromScript("shader-vs"), shaderSourceFromScript("shader-fs"), vertexShaderObj, fragmentShaderObj);//链接shader//创建一个程序对象programObj = context.createProgram();programObj = linkShader(context, programObj, vertexShaderObj, fragmentShaderObj);//context指定使用shader程序context.useProgram(programObj);}            //初始化canvasfunction  initCanvas(canvasId) {var canvas = document.getElementById(canvasId);var context = null;try{context = canvas.getContext("experimental-webgl");}catch(ex){alert(ex.toString());}if(!context){alert("我靠,你的浏览器不支持WebGL,换个浏览器吧!");return null;}//获得了绘图上下文之后,设置视口context.viewport(0, 0, canvas.width, canvas.height);return context;}//初始化顶点数据             function initVextexData(context)             {                 //顶点坐标                 var jsArrayData = [                      0.0, 1.0, 0.0,                     -1.0, 0.0, -1.0,                      1.0, 0.0, 0.0                 ]                 //创建一个webgl能够访问的缓冲                 var triangleBuffer = context.createBuffer();                 //绑定buffer                 context.bindBuffer(context.ARRAY_BUFFER, triangleBuffer);                 //将js数据拷贝到buffer上                 context.bufferData(context.ARRAY_BUFFER, new Float32Array(jsArrayData), context.STATIC_DRAW);                 return triangleBuffer;             } function start(){//初始化webgl渲染区域webglContext = initCanvas("webglCanvas");//初始化shader程序initShader(webglContext);                //初始化顶点数据                triangleBuffer = initVextexData(webglContext);                //开始绘制                //清空屏幕                webglContext.clearColor(0.0, 0.0, 0.0, 1.0);                webglContext.clear(webglContext.COLOR_BUFFER_BIT);                 //webgl中顶点数组数据可能N个,我们这里需要告诉webgl我们用哪一个,                //绑定一个顶点数组数据                webglContext.bindBuffer(webglContext.ARRAY_BUFFER, triangleBuffer);                //启动关联索引上的数据                webglContext.enableVertexAttribArray(v3PositionIndex);                //指定关联索引上的数据元素或者元素数据的正确信息                webglContext.vertexAttribPointer(v3PositionIndex, 3, webglContext.FLOAT, false, 0, 0);                //绘制数据                webglContext.drawArrays(webglContext.TRIANGLES, 0, 3);}</script>></head><body onload="start()"><canvas id = "webglCanvas" style = "border:1px solid blue" width = "600px" height = "600px"></canvas></body></html>
运行效果如下:

  地址:http://nbcoders.com/detail/164

0 0
原创粉丝点击