当前位置: 首页 > 科技观察

WebGL初探

时间:2023-03-12 10:31:12 科技观察

目前我们有很多快速接触WebGL绘制复杂图形的方案,但最后发现我们忽略了很多细节。当然,这对于初学者学习WebGL是很有必要的,能够快速的引起我们学习WebGL的兴趣。当学习到更深入的阶段,我们要了解WebGL的工作机制,这对我们的编程也会有很大的帮助。以上也是我想写这样一个系列的原因。简介用更专业的描述,WebGL(WebGraphicsLibrary)是一个JavaScriptAPI,用于渲染交互式3D和2D图形,不需要插件,兼容下一代浏览器。它通过HTML5中的元素实现功能。WebGL是由KhronosGroup而不是W3C组织开发的。目前,我们可以使用的是WebGL的第一个版本,它继承自OpenGLES2.0。OpenGLES(OpenGLforEmbeddedSystems)是OpenGL3D图形API的子集,专为移动电话、PDA和游戏机等嵌入式设备而设计。下面是版本关系图:HelloWorld首先,我们将通过实现一个简单的WebGL程序(清空绘图区)来敲开WebGL的大门。下面将实现最简单的WebGL功能之一:创建画布元素WebGL使用HTML5中的元素。为了使用WebGL进行3D渲染,您首先需要一个画布元素。这里创建了一个canvas元素,并使用onload事件初始化WebGL上下文。您的浏览器似乎不支持HTML5元素。获取WebGL上下文目前所有浏览器基本都支持WebGL,只是IE11和Edge浏览器略有不同。下面是初始化WebGL的基本封装:functioninitWebGL(canvas){//创建一个全局变量window.gl=null;try{//尝试获取标准上下文,如果失败,回退到实验上下文gl=canvas.getContext("webgl")||canvas.getContext("experimental-webgl");}catch(e){throw'创建失败。';}//如果没有GL上下文,立即放弃if(!gl){alert("WebGL初始化失败,可能是浏览器不支持。");gl=null;}returngl;}这里是使用canvas的getContext(contextType,contextAttributes)方法确定浏览器是否支持WebGL并创建其上下文。当返回值为canvascontext时,表示浏览器支持WebGL,为null则创建失败。注意在IE11和Edge浏览器下,需要使用“experimental-webgl”来创建WebGL,这里做了兼容性处理。设置背景色为黑色,清空空白绘图区下的缓冲区。vargl;//WebGL的全局变量functionstart(){varcanvas=document.getElementById("glcanvas");//初始化WebGL上下文gl=initWebGL(canvas);//只有当WebGL可用时才继续if(gl){//设置清除颜色为黑色,不透明gl.clearColor(0.0,0.0,0.0,1.0);//清除颜色和深度缓冲区gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);}}这样,我们就可以浏览您在显示器中看到黑色区域。您可能已经注意到WebGL遵循传统的OpenGL颜色分量范围,从0.0到1.0。RGB值越高,颜色越亮。注意这里的clear()方法清除的是color和depthbuffer,不是绘图区域的,它继承自OpenGL(基于多缓冲模型)。其实有一个模板缓存,但是很少用到。更进一步,我们完成了上面的第一个WebGL程序,但是我们还没有触及WebGL的核心:可编程着色器。接下来,我们将使用可编程着色器在屏幕上绘制点。可编程着色器是一个比较复杂的概念,它也有自己的编程语言GLSL。后面会有专门的文章详细讲解programmableshader。这里我们只需要简单了解绘制过程:编写shader程序//vertexshaderprogramvarVSHADER_SOURCE='voidmain(){\n'+'gl_Position=vec4(0.0,0.0,0.0,1.0);\n'+//设置顶点位置'gl_PointSize=10.0;\n'+//设置点大小'}\n';//片元着色器程序varFSHADER_SOURCE='voidmain(){\n'+'gl_FragColor=vec4(1.0,1.0,1.0,1.0);\n'+//设置点的颜色,这里是白色'}\n';上面的程序是不是感觉很眼熟?是的,GLSL语言与C语言非常相似。着色器程序包含一个返回空的主函数。vec4()构造函数用于生成四维向量(x,y,z,w)。编译着色器首先需要使用createShader(type)方法生成对应类型的WebGLShader。接下来,使用shaderSource(shader,sourceCode)作为GLSL源代码的挂钩函数。***使用compileShader(shader)完成shader的编译。在程序中,我们做了编译后检查。当shader编译失败时,会报失败并删除shader。functioncreateShader(gl,type,sourceCode){//编译着色器类型:顶点着色器和片段着色器。varshader=gl.createShader(type);gl.shaderSource(shader,sourceCode);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){varinfo=gl.getShaderInfoLog(shader);console.log("UnabletocompileWebGLprogram.\n\n"+info);gl.deleteShader(shader);returnnull;}returnshader;}连接可用程序此时shader还是不可用,需要分配给WebGLProgram。这里有三个主要步骤。首先,您需要使用createProgram()方法来创建和初始化一个WebGLProgram对象。接下来,使用gl.attachShader(program,shader)将对象附加到两个已编译的着色器。***,使用linkProgram(program)连接WebGLProgram和shader。functioncreateProgram(gl,vshader,fshader){//创建着色器对象returnnull;}//创建一个编程对象varprogram=gl.createProgram();if(!program){returnnull;}//给创建的shader对象赋值gl.attachShader(program,vertexShader);gl.attachShader(program,fragmentShader);//连接编程对象gl.linkProgram(program);//查看链接结果varlinked=gl.getProgramParameter(program,gl.LINK_STATUS);if(!linked){varerror=gl.getProgramInfoLog(program);console.log('Linkprogramfailed:'+error);gl.deleteProgram(program);gl.deleteShader(fragmentShader);gl.deleteShader(vertexShader);returnnull;}returnprogram;}使用可用的shader程序这一步主要使用useProgram(program)方法告诉GPU使用该程序。functioninitShaders(gl,vshader,fshader){varprogram=createProgram(gl,vshader,fshader);if(!program){console.log('创建程序失败。');returnfalse;}gl.useProgram(program);gl.program=program;returntrue;}画点***,使用drawArrays(mode,first,count)画点,这个函数很强大渲染功能,后续文章会详细介绍。您在这里只需要知道传递“POINTS”即可得出一个点。//画一个点gl.drawArrays(gl.POINTS,0,1);至此,我们完成了绘制点的所有程序。当运行上面的程序时,我们会在浏览器中看到一个白点。结束语到现在为止,虽然我们还没有使用WebGL绘制三维图形,但是我们已经进入了WebGL的世界。我们使用WebGL绘制了简单的图形。但这只是WebGL绘图的冰山一角。我们当然不会使用WebGL来绘制这么简单的图形。为了画出更复杂的图形,我们还有很多细节需要了解。但无论如何,我们已经开始了WebGL的第一步,其实问题并没有我们想象的那么难。