介绍遵循WebGL的基本概念,做一个简单的画直线的例子。主要参考以下两篇文章:DrawapointDrawatriangleOriginMyGitHubDrawaline下面就不对每个函数的使用做详细的解释了。个人比较喜欢先对整体逻辑有个感觉,然后在实际使用中根据需要去检查。材料。通过Canvas元素使用WebGL的基本概念中提到创建WebGL上下文:constcanvasObj=document.querySelector("#demo");constglContext=canvasObj.getContext("webgl");if(!glContext){alert("浏览器不支持WebGL");返回;然后准备顶点数据。准备顶点数据和缓冲区WebGL中的所有对象都在3D空间中,画一条线需要两个顶点,每个顶点都有一个3D坐标:letvertices=[-0.5,-0.5,0.0,0.5,-0.5,0.0];缓冲区有很多种,顶点缓冲区对象的类型是gl.ARRAY_BUFFER。/***设置缓冲区*@param{*}glWebGL上下文*@param{*}vertexData顶点数据*/functionsetBuffers(gl,vertexData){//创建一个空白缓冲区对象constbuffer=gl.createBuffer();//绑定目标gl.bindBuffer(gl.ARRAY_BUFFER,buffer);//WebGL不支持直接使用JavaScript原始数组类型,需要转换constdataFormat=newFloat32Array(vertexData);//初始化数据存储gl.bufferData(gl.ARRAY_BUFFER,dataFormat,gl.STATIC_DRAW);},bufferData方法会将数据复制到当前绑定的缓冲区对象中,该对象提供参数来管理给定的数据:STATIC_DRAW:缓冲区的内容可能会被频繁使用,不会经常改变。DYNAMIC_DRAW:缓冲区的内容可能会被频繁使用和更改。STREAM_DRAW:缓冲区的内容可能不会经常使用。线条的数据不会改变,每次渲染都保持不变,所以这里使用的类型是STATIC_DRAW。现在顶点数据已存储在显卡内存中,可以准备顶点着色器了。Vertexshadervertexshader需要用GLSLES语言来写,前端有两种写法:scripttagwrapping,和获取DOM对象一样使用。纯字符串。每个顶点都有一个三维坐标,创建一个vec3类型的输入变量vertexPos,vec3代表一个三元组floating-点向量。main是入口函数,gl_Position是shader的内置变量,GLSL中一个变量最多有4个分量,最后一个分量用于透视划分。gl_Position设置的值成为该顶点着色器的输出。这里,请回忆一下基本概念中提到的状态机。以下是普通字符形式:/***createvertexshader*@param{*}glWebGLcontext*/functioncreateVertexShader(gl){//vertexshaderglslcodeconstsource=`attributevec3vertexPos;voidmain(void){gl_Position=vec4(vertexPos,1);}`;//创建着色器constshader=gl.createShader(gl.VERTEX_SHADER);//设置顶点着色器代码gl.shaderSource(shader,source);//编译gl.compileShader(shader);//判断编译是否成功if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){alert("Compileshadererror:"+gl.getShaderInfoLog(shader));gl.deleteShader(着色器);返回空值;}返回着色器;为了让WebGL使用这个着色器,它的源代码必须在运行时动态编译。createShader函数创建一个gl.VERTEX_SHADER类型的着色器对象;compileShader函数对其进行编译。接下来准备片段着色器。片段着色器片段着色器也是用GLSLES语言编写的。片段着色器所做的是计算像素的最终颜色输出,在这里简单地指定输出白色。gl_FragColor是一个表示颜色的内置变量,4个分量分别对应R、G、B、A。/***创建片段着色器*@param{*}glWebGL上下文*/functioncreateFragmentShader(gl){//片段着色器glsl代码constsource=`voidmain(void){gl_FragColor=vec4(1.0,1.0,1.0,1.0);}`;//创建着色器constshader=gl.createShader(gl.FRAGMENT_SHADER);//设置片段着色器代码gl.shaderSource(shader,source);//编译gl.compileShader(shader);//判断编译是否成功gl.deleteShader(着色器);返回空值;}返回着色器;},两个shader都准备好之后,需要先链接合并,然后才能使用。着色器程序着色器程序对象是最终链接的多个着色器的组合版本。将着色器链接到程序中时,它将每个着色器的输出链接到下一个着色器的输入。当输出与输入不匹配时,会出现连接错误。createProgram函数创建一个对象;attachShader添加一个着色器;linkProgram链接添加的着色器。当需要激活着色器时,使用此对象作为参数调用useProgram函数。/***初始化着色器程序*@param{*}glWebGL上下文*@param{*}vertexShader顶点着色器*@param{*}fragmentShader片段着色器*/functioninitShaderProgram(gl,vertexShader,fragmentShader){//创建着色器objectconstshaderProgram=gl.createProgram();//添加着色器gl.attachShader(shaderProgram,vertexShader);gl.attachShader(shaderProgram,fragmentShader);//多个着色器合并链接gl.linkProgram(shaderProgram);//检查是否创建成功返回空值;}返回着色器程序;至此,输入的顶点数据已经发送到GPU并指示如何在顶点和片段着色器中对其进行处理。最后,剩下的就是画画了。drawvertexAttribPointer函数告诉WebGL如何解释顶点数据;enableVertexAttribArray函数启用顶点属性,默认禁用;useProgram函数激活着色器;drawArrays函数绘制,第一个参数是绘制图元的类型,绘制的是直线,gl.LINE_STRIP也是。/***初始化着色器程序*@param{*}glWebGLcontext*@param{*}shaderProgram着色器程序对象*/functiondraw(gl,shaderProgram){//获取对应的数据索引constvertexPos=gl.getAttribLocation(shaderProgram,"顶点位置");//解析顶点数据gl.vertexAttribPointer(vertexPos,3,gl.FLOAT,false,0,0);//启用顶点属性,默认情况下禁用。gl.enableVertexAttribArray(vertexPos);//激活着色器gl.useProgram(shaderProgram);//Drawgl.drawArrays(gl.LINE_STRIP,0,2);}Example这是一个例子,整体逻辑大致是这样的:constcanvasObj=document.querySelector("#demo");constglContext=canvasObj.getContext("webgl");让顶点=[-0.5,-0.5,0.0,0.5,-0.5,0.0];//顶点数据setBuffers(glContext,vertices);//缓冲数据constvertexShader=createVertexShader(glContext);//顶点着色器constfragmentShader=createFragmentShader(glContext);//片段着色器constshaderProgram=initShaderProgram(glContext,vertexShader,fragmentShader);//shader着色器程序对象draw(glContext,shaderProgram);//绘图涉及的方法和变量很多。一开始我真的很困惑。多看几遍代码就习惯了。接下来总结一下这期间出现的一些疑惑,详见JavaScriptWebGL基础疑惑。参考资料WebGL基础绘图一:画点你好,三角形WebGLlessonsWebGLMDN