本文地址: https://wysaid.org/721.html
原创,转载请注明出处
第一话,准备工作(blog.wysaid.org)
第一步
观看本教程时,请先确保自己有一定的编程基础,我不会给你讲什么javascript的基础语法的。
但鉴于一般学编程的人不一定懂网页页面设计,我会附带少量DIV,CSS这方面必备的知识。
那么,废话不多说,开始吧。做一件事千万不能着急,磨刀不误砍柴工这个道理相信大家都懂。
做一件事之前先做充足/一定/少量是非常有必要的。比如WebGL做出来的东西肯定是显示在图形界面上的,而不是一个只有功能的控制台程序,那么我们首先应该准备的就是一个简单优雅的界面。
需要了解的知识(为了便于显示,我会给所有的div元素加上边框):div标签是网页设计里面用得非常多的,用于控制网页显示的元素。我们也将用到它来控制显示的界面,包括位置、大小以及可能会处理的鼠标事件等等。此外,我们还需要一个按钮,来点击以运行出结果。
如下:
第二步
本教程为WebGL教程,所以,现在必须引入canvas,你可能知道,从canvas里面创建名叫”2d”的上下文进行绘图。也就是大家所乐道HTML5方式,但是WebGL使用的方式为”experimental-webgl”或者”webgl”,如果后者创建不成功,那么请试试前者,本教程使用前者。
请不要用爪机观看本教程,适当的动手有助于进步。以及,你必须先安装一个支持WebGL的浏览器(IE11+,chrome,firefox,opera等)
为了便于控制,我们将canvas元素写在刚才的div里面:
也许你看不出来canvas已经写进去了,那么你可以试着多点几下上面的run,我将用html5方式在上面的canvas上画出一个红色矩形
第三步
前面说了半天,还没真正说到WebGL本身。那么经过上面两小节的描述,现在进入我们的第一个WebGL小程序:hello webgl
首先,你需要初始化webgl,以获得一个上下文,让浏览器知道你想绘图到什么地方。代码类似于这样:
1 2 3 4 5 6 7 8 |
var webgl = null; function webglInit() { var myCanvasObject = document.getElementById("webglView"); var myDivObject = document.getElementById("containerView"); webgl = myCanvasObject.getContext("experimental-webgl"); if (webgl == null) alert("你的浏览器不支持webgl"); webgl.viewport(0, 0, myDivObject.clientWidth, myDivObject.clientHeight); } |
千万注意上面注释部分那一句,viewport设置的宽高是div的宽高,而不是canvas的,也许你想知道为什么,那么我解释一下:在设计中,你不一定想让canvas具有固定的大小,所以你可能用css控制了元素随着浏览器窗口的变化而变动,但是canvas的宽高属性是独立出来的,不受style控制,即便根据父元素改变了大小,直接获取的宽高值也不对。这里有两种解决办法,一是像上面那样写,二是使用js代码响应每一次窗口大小的变动,把canvas对象的width和height重设。后面如果涉及到复杂一点的布局的时候再讨论。
这里获取到了webgl对象,接下来就要创建Shader对象了。为了节省篇幅,后面的就不写容错代码,只写功能了:
1 2 3 4 5 6 7 8 |
var vertexShaderObject = null; var fragmentShaderObject = null; function shaderInitWithVertexAndFragmentShader(vsh, fsh) { webgl.shaderSource(vertexShaderObject, vsh); webgl.shaderSource(fragmentShaderObject, fsh); webgl.compileShader(vertexShaderObject); webgl.compileShader(fragmentShaderObject); } |
上面这一步获取到了Shader Object对象,那么,再接下来当然是ShaderProgram了,有了program可就差不多大功告成了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var programObject; var v4PositionIndex; function initShaderProgram(positionName) { programObject = webgl.createProgram(); webgl.attachShader(programObject, vertexShaderObject); webgl.attachShader(programObject, fragmentShaderObject); webgl.bindAttribLocation(programObject, v4PositionIndex, positionName); webgl.linkProgram(programObject); if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) { alert(webgl.getProgramInfoLog(programObject)); return; } webgl.useProgram(programObject); } |
是的,代码就这么简单,我们快要看到我们的第一个webgl程序了。写了一堆辅助函数,下面就要调用它们了,但是调用就要直接写吗?不,我说了,磨刀不误砍柴工。初学一样东西,把准备工作做足,后面才方便继续。因为我们的demo是随着我们的努力不断进步了。不要说学到下一章我们就把第一章的内容丢掉这样的话。我们将在此基础上不断完善,所以这个demo的功能必须写得稍微分开一点。
接下来就是一步完成绘制的函数,加上它,就相当于我们的第一个webgl程序了:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function renderWebGL(vertices, vSize, vLen, vsh, fsh, positionName) { webglInit(); shaderInitWithVertexAndFragmentShader(vsh, fsh); initShaderProgram(positionName); var buffer = webgl.createBuffer(); webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer); webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW); webgl.enableVertexAttribArray(v4PositionIndex); webgl.vertexAttribPointer(v4PositionIndex, vSize, webgl.FLOAT, false, 0, 0); webgl.clearColor(0.0, 0.0, 0.0, 1.0); webgl.clear(webgl.COLOR_BUFFER_BIT); webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, vLen); } |
第四步
虽然我说我们的第一个WebGL程序已经写完了,但是不是还感觉少了写什么?对,那就是显示。上面所有的代码相当于对WebGL的一个简单封装,我们要让它显示点什么东西出来才对。让我们的应用我们的封装吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
//使用上面封装的函数在绘制一个渐变色三角形, 由于前面封装的功劳,我们现在可以绘制很多东西而只需要提供shader文本代码和顶点就行了。 function renderTriangle() { var vertices = [ 0.0, 0.5, -0.5, -0.5, 0.5, -0.5, ]; var vsh = "precision mediump float;" + "attribute vec4 position;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " gl_Position = position;" + " textureCoordinate = position.xy + 0.5;" + "}"; var fsh = "precision mediump float;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " gl_FragColor = vec4(textureCoordinate, 0.0, 1.0);" + "}"; renderWebGL(vertices, 2, 3, vsh, fsh, "position"); } function renderRectangle() { var vertices = [ 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5 ]; var vsh = "precision mediump float;" + "attribute vec4 position;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " gl_Position = position;" + " textureCoordinate = position.xy + 0.5;" + "}"; var fsh = "precision mediump float;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " gl_FragColor = vec4(textureCoordinate, 0.0, 1.0);" + "}"; renderWebGL(vertices, 2, 4, vsh, fsh, "position"); } function renderCircle() { var vertices = [ 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0 ]; var vsh = "precision mediump float;" + "attribute vec4 position;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " gl_Position = position;" + " textureCoordinate = position.xy;" + "}"; var fsh = "precision mediump float;" + "varying vec2 textureCoordinate;" + "void main()" + "{" + " if(length(textureCoordinate) < 0.5)" + " gl_FragColor = vec4(textureCoordinate + 0.5, 0.0, 1.0);" + " else gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);" + "}"; renderWebGL(vertices, 2, 4, vsh, fsh, "position"); } |
好的,第一期教程到此为止,请关注lesson 2。系列教程地址:webgl-lesson.wysaid.org
这个更刺c激,准备好手纸哦 A 片。。 288d.pw
出问题的同学,不要用给出的代码,要用源码
我晕。。。
就是我在canvas外面加了div了还是不得行
你把你没弄成功的页面发给我看看吧。也许弄知道什么原因
<!–
Your browser doesn’t support the HTML5 element canvas.
–!>
Your browser doesn’t support the HTML5 element canvas.
这个样子还是不得行呢?
大师兄,你是如何在文章里使用canvas元素的?我使用它,浏览器会无法识别?
但是单独的页面就可以。
给canvas元素外面加上一个div框起来哈
大师兄,我照着你写的。
http://codepad.org/4zviSmWz
总是提示vertexShaderCompile Error
fragmentShaderCompileError.
告诉missing shaders.
能帮我看下是怎么回事吗?里面的封装基本都是你的。
直接看这篇文章的下一篇lesson 2,开头我给出了这一篇用到的代码,你好好对比一下~